AngularJS
1 вырос, чтобы стать одним из самых популярных платформ приложений одной страницы.Разработано преданной командой в Google, результат существенным и широко используется в обоих сообществ и отраслевых проектов .
Одна из причин успеха AngularJS “является его выдающиеся способности к тестированию.Это сильно поддерживается Karma __11 | 11 2 (впечатляющий тест бегун написан Войта Jina) и его многочисленные плагины.Карма, в сочетании с его товарищи Mocha __21 | 17 3 , Chai 18 4 | __6 и Sinon 20 5 , предлагает полный набор инструментов для производства качественного кода, который легко поддерживать, ошибка-бесплатно и хорошо документированы .
“Ну, я просто запустить приложение и посмотреть, все ли работает.Мы никогда не было никаких проблем сделать это “.не
– Нет одним ever
Основной фактор, который заставил меня перейти от “Ну, я просто запустить приложение и посмотреть, если все работает”, чтобы было то, что впервые, я мог __54 “Я получил юнит-тестов!” | Внимание на каком matters и на то, что мне нравится в программировании: создание интеллектуальных алгоритмов и красивые интерфейсы .
Я помню компонент, который должен был управлять меню правой кнопкой мыши в приложении.Поверьте мне, это было сложный компонент.В зависимости от десятков смешанных условиях, это может показать или скрыть кнопки, подменю и т.д. Один день, мы обновили приложение в производство.Я помню, как я чувствовал, когда я запустил приложение, открыл что-то, правой кнопкой мыши и не видел меню нет контекстная — только пустую коробку уродливые, что было определенное доказательство, что что-то пошло не так на самом деле.После закрепив ее, вновь обновил приложение и извинился перед клиентами, я решил полностью переписать этот компонент в тестовом приводом стиле развития.Тестовый файл заканчивал тем, что в два раза дольше, как и файл компонента.Это была улучшена много, поскольку, особенно его плохой работы, но она никогда не удалось снова в производстве.Несокрушимая код .
Слово о единице Testing
Модульное тестирование стало стандартом в большинстве софтверных компаний.Ожидания клиентов достигли нового максимума, и никто не принимает получение двух бесплатных регрессии по цене одного обновлениябольше .
Если вы знакомы с модульного тестирования, то вы уже знаете, насколько уверенно чувствует себя, когда разработчик рефакторинга кода испытания.Если вы не знакомы, то представьте себе избавиться от стресса развертывания, “код-и-молись” стиль кодирования и нескончаемый развитие функций.Лучшая часть?Это автоматический .
Модульное тестирование улучшает orthogonality.По сути, код называется “ортогональным”, когда это легко изменить.Крепление ошибку или добавив функцию не влечет за собой ничего, кроме изменения поведение кода, как описано в прагматический программист: от подмастерья к Master 6 .Модульные тесты значительно улучшить ортогональность Кодекса, заставляя вас писать модульные логические единицы, а больших кусков кода .
Модульное тестирование также предоставляет вам документацию, которая всегда в курсе и что информирует вас о намерениях код и функционального поведения.Даже если метод имеет загадочное название — что плохо, но мы не будем получать в том, что здесь — вы сразу знаете, что он делает, читая свое испытание .
Модульное тестирование имеет еще большое преимущество.Она заставляет вас на самом деле использовать свой код и обнаружить недостатки дизайна и неприятные запахи.Возьмите функции.Что может быть лучше, чтобы убедиться, что функции отсоединяется от остальной части вашего кода, чем, будучи в состоянии проверить их без шаблонного кода
Кроме того, модульное тестирование открывает дверь, чтобы проверить приводом development.В то время как это не тема этой статьи, я не могу подчеркнуть достаточно, что развитие тестами является прекрасным и продуктивный способ, чтобы написать код .
Что и чего не Test
Тесты должны определить API Кодекса.Это один принцип, который будет направлять нас через это путешествие.AngularJS приложение, по определению, состоит из модулей.Элементарные кирпичи материализуется различных концепций, связанных с зернистостью, на котором вы смотрите на них.На уровне приложения, эти кирпичи модули AngularJS.На уровне модуля, они директивы, контроллеры, услуги, фильтры и фабрики.Каждый из них способен общаться с другим через внешний интерфейс .
Все эти кирпичи разделяют общий атрибут.Они ведут себя, как черные ящики, что означает, что они имеют внутреннюю поведение и внешний интерфейс материализованный входами и выходами.Это именно то, что модульные тесты для: для внешних интерфейсов тестовых кирпича ».
Игнорирование внутренние как можно больше считается хорошей практикой.Модульное тестирование — и тестирование в целом — является сочетание стимулов и реакций .
Начальная загрузка среды тестирования для AngularJS
Чтобы установить достойную среду тестирования для вашего AngularJS приложения, потребуется несколько модулей NPM.Давайте быстрый взгляд на них .
Карма: Захватывающий тест 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
Мы видели, как мокко обеспечивает испытаний и тестирования люкс-тематические возможности для JavaScript. Chai 18 4 , со своей стороны, предлагает различные способы проверки things в тестовых случаях.Эти проверки выполняются с помощью так называемых “утверждения” и в основном отмечают тест несостоявшимся или передается. Документация Chai имеет more __52 | 19 на различных утверждений стилей .
Sinon
Sinon 20 5 описывает себя как “автономные испытания шпионы, окурки и издевается для JavaScript.” Spies, заглушки и издевается над всем ответить на тот же вопрос: Как сделатьВы эффективно заменить одно с другим, когда работает тест?Предположим, у вас есть функция, которая принимает другую в качестве параметра и вызывает его.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();
});
it('shou ...
Если вы хотите прочитать полностью статью, посетите сайт наших спонсоров