AngularJS
1 вырос, чтобы стать одним из самых популярных сред разработки приложений более одной страницы.Разработано специально созданной группы в Google, результат является существенным, и широко используется как в общинах и отраслевых проектов .
Одна из причин успеха AngularJS “является его незаурядные способности к тестированию.Это решительно поддержали Karma 11 2 (зрелищным тест бегун, написанная Войта Jina) и его многочисленные плагины.Карма, в сочетании с его товарищи Mocha 17 3 , Chai 18 4 и Sinon 20 5 , предлагает полный набор инструментов для производства качественного кода, который легко поддерживать, ошибка-бесплатно и хорошо документированы .
“Ну, я просто запустить приложение и посмотреть, все ли работает.Мы никогда не было никаких проблем сделать это “.не
– Нет одним ever
Основным фактором, который заставил меня перейти от “Ну, я просто запустить приложение и посмотреть, все ли работает” в том, что, в первый раз, я мог бы __54 “У меня есть юнит-тесты!” | Сосредоточьтесь на том, matters и о том, что я люблю в программировании: создание интеллектуальных алгоритмов и красивые интерфейсы .
Я помню компонент, который должен был управлять меню правой кнопкой мыши в приложении.Поверьте мне, это было сложный компонент.В зависимости от десятков смешанных условиях, это может показать или скрыть кнопки, подменю и т.д. Однажды, мы обновили приложение для производства.Я помню, как я чувствовал, когда я запустили приложение, открыл что-то, щелкнуть правой кнопкой мыши и не видел меню не контекстную — Просто пустая уродливый ящик, окончательное доказательство того, что что-то пошло очень неправильно.После того, как установил это, вновь обновил приложение и извинился перед клиентами, я решил полностью переписать этот компонент в тестовом приводом стиле развития.Тестовый файл заканчивал тем, что в два раза длиннее и файл компонента.Он был гораздо лучше, поскольку, особенно его плохой работы, но она никогда не подводил снова в производстве.Несокрушимая код .
Слово о единице Testing
Модульное тестирование стало стандартом в большинстве софтверных компаний.Ожидания клиентов достигли нового максимума, и никто не принимает получение двух бесплатных регрессии по цене одного обновления больше .
Если вы знакомыс модульного тестирования, то вы уже знаете, насколько уверенно разработчик чувствует, когда рефакторинга протестированного кода.Если вы не знакомы, то представьте себе, чтобы избавиться от стресса развертывания, “код-и-молись” стиль кодирования и нескончаемый развитие функций.Большая часть?Это автоматический .
Модульное тестирование улучшает orthogonality.По сути, код называется “ортогональным”, когда это легко изменить.Крепление ошибку или добавив функцию не влечет за собой ничего, кроме изменения поведение кода, как описано в Прагматический Программист: От Journeyman к Master 6 .Юнит-тесты значительно улучшить ортогональность кода, заставив вас написать модульные логические единицы, а большой код куски .
Модульное тестирование также предоставляет вам документации, которая всегда в курсе и что информирует вас о намерениях Кодекса и функционального поведения.Даже если метод имеет загадочное название — что плохо, но мы не будем получать в том, что здесь — вы сразу знаете, что он делает, читая свой тест .
Модульное тестирование имеет еще одним важным преимуществом.Это заставляет вас на самом деле использовать свой код и обнаружить недостатки дизайна и неприятные запахи.Возьмите функции.Что может быть лучше, чтобы убедиться, что функции являются отсоединяется от остальной части вашего кода, чем, будучи в состоянии проверить их без каких-либо шаблонного кода
Кроме того, модульное тестирование открывает дверь, чтобы проверить приводом development.Хотя это не тема этой статьи, я не могу подчеркнуть достаточно, что развитие тестами является прекрасным и продуктивный способ, чтобы написать код .
Что и чего не Test
Тесты должны определить API Кодекса.Это один принцип, который будет направлять нас через этот путь.AngularJS приложение, по определению, состоит из модулей.Элементарные кирпичи материализуется различных концепций, связанных с зернистостью, на котором вы смотрите на них.На прикладном уровне, эти кирпичи модули AngularJS.На уровне модуля, они директивы, контроллеры, услуги, фильтры и фабрики.Каждый из них имеет возможность общаться с другим через внешний интерфейс .
Все эти кирпичи общий атрибут.Они ведут себя, как черныйкоробки, что означает, что они имеют внутреннюю поведение и внешний интерфейс материализуется входов и выходов.Это именно то, что модульные тесты для: для внешних интерфейсов тестовых кирпичей “.
Не обращая внимания на внутренние, насколько это возможно, считается хорошей практикой.Модульное тестирование — и тестирование в общем — является сочетание стимулов и реакций .
Бутстрапирование Test Окружающая среда для AngularJS
Чтобы установить достойную среду тестирования для вашего AngularJS приложения, вы будете нуждаться в себя несколько модулей NPM.Давайте быстрый взгляд на них .
Репутация: Spectacular Тест Runner
Karma 11 2 является двигатель, который работает тесты на код.Хотя она была написана для AngularJS, это не специально привязаны к нему и может быть использован для любого приложения JavaScript.Это настраиваемый через файл JSON и использования различных плагинов .
Все примеры, приведенные в этой статье, можно найти в посвящена GitHub project 14 наряду с следующий файл конфигурации для кармы .
// Karma configuration
// Generated on Mon Jul 21 2014 11:48:34 GMT+0200 (CEST)
module.exports = function(config) {
config.set({
// base path used to resolve all patterns (e.g. files, exclude)
basePath: '',
// frameworks to use
frameworks: ['mocha', 'sinon-chai'],
// list of files / patterns to load in the browser
files: [
'bower_components/angular/angular.js',
'bower_components/angular-mocks/angular-mocks.js',
'src/*.js',
'test/*.mocha.js'
],
// list of files to exclude
exclude: [],
// preprocess matching files before serving them to the browser
preprocessors: {
'src/*.js': ['coverage']
},
coverageReporter: {
type: 'text-summary',
dir: 'coverage/'
},
// test results reporter to use
reporters: ['progress', 'coverage'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests on file changes
autoWatch: true,
// start these browsers
browsers: ['PhantomJS'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false
});
};
Этот файл может быть автоматически генерируется, набрав karma init
в окне терминала.Доступные ключи описанные в Кармыdocumentation 15 .
Обратите внимание, как источники и тестовые файлы были объявлены.Существует также новичок: ngMock 16 (т.е. angular-mocks.js
).ngMock является модуль AngularJS, что обеспечивает несколько утилит тестирования (подробнее об этом в конце этой статьи) .
Mocha
Mocha 17 3 является система тестирования для JavaScript.Он обрабатывает тестов и тестов, и он предлагает хорошие возможности отчетности.Он использует декларативный синтаксис в гнездо ожиданий в случаях и люксы.Давайте посмотрим на следующем примере (бесстыдно похищенной с домашней страницы Mocha): стандарт
describe('Array', function() {
describe('#indexOf()', function() {
it('should return -1 when the value is not present', function() {
assert.equal(-1, [1,2,3].indexOf(5));
assert.equal(-1, [1,2,3].indexOf(0));
});
});
});
Вы можете видеть, что все тесты содержится в describe
вызова.Что интересно гнездования вызовов функций в этом случае является то, что Тесты следовать structure.Здесь Array
Набор состоит только из одного подсвитой, #indexOf
.Могут быть добавлены другие, конечно.Это подсвита состоит из одного случая, который сам по себе содержит два утверждения и ожидания.Организация наборов тестов в единое целое имеет важное значение.Это гарантирует, что ошибки тестирования будут представлены со значимыми сообщений, таким образом облегчая процесс отладки .
Chai
Мы видели, как Mocha тестовый ванной и тест-тематические возможности для JavaScript. Chai 18 4 , со своей стороны, предлагает различные способы проверки things в тестовых случаях.Эти проверки выполняются с помощью так называемых “утверждения” и в основном отмечают тестовый случай как не удалось и не передаются. Документация Chai имеет more 19 на различных утверждений стилей .
Sinon
Sinon 20 5 описывает себя как “автономные испытания шпионы, заглушки и издевается над для JavaScript.” Шпионов заглушки и издевается над всем ответить на тот же вопрос: Как сделатьВы эффективно заменить одно с другим при запуске теста?Предположим, у вас есть функция, которая принимает еще один в качестве параметра и вызывает его.Sinon предоставляет интеллектуальный и краткий способ контролировать ли называется функция и многое другое (с которым аргументы, сколько раз и т.д.). .
Модульное тестирование на прикладном Level
Точка внешнего интерфейса модуля в AngularJS приложения является его способность бытьвводят в другой модуль —, что он существует и имеет действительный определение .
beforeEach(module('myAwesomeModule'));
Это достаточно, и выдаст ошибку, если myAwesomeModule
нигде не найти .
Модульное тестирование в модуле Level
Модуль AngularJS может объявить несколько типов объектов.Некоторые из них услуги, в то время как другие являются более специализированными.Мы пойдем по каждому из них, чтобы увидеть, как они могут быть перезагружена в контролируемой среде, а затем проходят .
Фильтры, услуги и заводы: история зависимостей Injection
Фильтры, услуги и заводы (мы называем их услуг в целом) может быть по сравнению с статических объектов или одиночек в традиционном объектно-ориентированной модели.Они легко проверить, потому что они нуждаются в очень несколько вещей, чтобы быть готовым, и эти вещи, как правило другие услуги .
AngularJS ссылки услуг других служб или объектов с помощью очень экспрессивные модели зависимостей инъекции, которые в основном означает, просят что-то в аргументах метода в .
Что такое большое о пути AngularJS “инъекций зависимостей является то, что насмешливый кусок зависимостей код и инъекционных вещи в тестовых супер-легкий.На самом деле, я даже не уверен, что это может быть проще.Давайте рассмотрим эту весьма полезную завод:
angular.module('factories', [])
.factory('chimp', ['$log', function($log) {
return {
ook: function() {
$log.warn('Ook.');
}
};
}]);
Посмотрите, как $log
впрыскивается, вместо стандартного console.warn
?В то время как AngularJS не будет печатать $log
заявления в консоли Кармы, избежать побочных эффектов в юнит-тестов настолько, насколько возможно.Я как-то уменьшить на половину длительности юнит-тестов заявку путем насмешливый __30 отслеживания HTTP запросов | которые были все молча неудачу в локальной среде, очевидно .
describe('factories', function() {
beforeEach(module('factories'));
var chimp;
var $log;
beforeEach(inject(function(_chimp_, _$log_) {
chimp = _chimp_;
$log = _$log_;
sinon.stub($log, 'warn', function() {});
}));
describe('when invoked', function() {
beforeEach(function() {
chimp.ook();
});
it('should say Ook', function() {
expect($log.warn.callCount).to.equal(1);
expect($log.warn.args[0][0]).to.equal('Ook.');
});
});
});
Образец для тестирования фильтров, услуг или других инъекций является то же самое.Контроллеры могут быть немного сложнее, чтобы проверить, хотя, как мы увидим сейчас .
Controllers
Тестирование контроллера может привести к некоторой путанице.Что мы испытываем?Давайте сосредоточимся на том, что контроллер должен делать.Вы должны быть использованы для рассмотрения любой проверенный элемент как черный ящик в настоящее время.Помните, что AngularJS является модель-представление-то, что (MVW) база, которая является своеобразной иронии судьбы, потому что один из немногих способов определения что-либо в AngularJS приложения использовать ключевое слово controller
.Тем не менее, любой вид приличный контроллер, как правило, выступает в качестве прокси между моделью и представлением, через объекты в одну сторону, а обратного вызова в другой .
Контроллер, как правило, настраивает вид при помощи некоторых государственных объектов, таких как следующий (для гипотетического текстового редактирования приложения):
angular.module('textEditor', [])
.controller('EditionCtrl', ['$scope', function($scope) {
$scope.state = {toolbarVisible: true, documentSaved: true};
$scope.document = {text: 'Some text'};
$scope.$watch('document.text', function(value) {
$scope.state.documentSaved = false;
}, true);
$scope.saveDocument = function() {
$scope.sendHTTP($scope.document.text);
$scope.state.documentSaved = true;
};
$scope.sendHTTP = function(content) {
// payload creation, HTTP request, etc.
};
}]);
Скорее всего, что государство будет изменяться как вид и контроллер.toolbarVisible
атрибут будет переключаться, скажем, кнопки и клавиши быстрого вызова.Юнит-тесты не должны проверить взаимодействие между видом и остальной Вселенной;это то, что из конца в конец тесты для .
documentSaved
значение будет в основном обрабатываются контроллером, однако.Давайте проверим это .
describe('saving a document', function() {
var scope;
var ctrl;
beforeEach(module('textEditor'));
beforeEach(inject(function($rootScope, $controller) {
scope = $rootScope.$new();
ctrl = $controller('EditionCtrl', {$scope: scope});
}));
it('should have an initial documentSaved state', function(){
expect(scope.state.documentSaved).to.equal(true);
});
describe('documentSaved property', function() {
beforeEach(function() {
// We don't want extra HTTP requests to be sent
// and that's not what we're testing here.
sinon.stub(scope, 'sendHTTP', function() {});
// A call to $apply() must be performed, otherwise the
// scope's watchers won't be run through.
scope.$apply(function () {
scope.document.text += ' And some more text';
});
});
it('should watch for document.text changes', function() {
expect(scope.state.documentSaved).to.equal(false);
});
describe('when calling the saveDocument function', function() {
beforeEach(function() {
scope.saveDocument() ...
Если вы хотите прочитать полностью статью, посетите сайт наших спонсоров