angularjs testing strategies
DESCRIPTION
A question of why we test, what makes AngularJS easy to test, and strategies to test AngularJS.TRANSCRIPT
![Page 1: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/1.jpg)
AngularJS testing
strategies
Nate Peterson@njpetersonPa
![Page 2: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/2.jpg)
What’s not in this talk
![Page 3: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/3.jpg)
What’s this talk about
![Page 4: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/4.jpg)
Why do we care about testing?
![Page 5: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/5.jpg)
Tests help us fail fast
![Page 6: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/6.jpg)
Tests give us confidence
![Page 7: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/7.jpg)
Tests help us understand what we’re doing and where we’re going
![Page 8: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/8.jpg)
JavaScript is a dynamically typed
language with almost no help from compiler
![Page 9: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/9.jpg)
“One of the fundamental reasons for choosing Angular is cited as that
it is built with testing in mind.”
![Page 10: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/10.jpg)
![Page 11: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/11.jpg)
![Page 12: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/12.jpg)
function MyController() {
var dep1 = new Dep1(); var dep2 = new Dep2(); //do something with dep1 and dep2 ...}
![Page 13: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/13.jpg)
someModule.controller('MyController', ['$scope', 'dep1', 'dep2', function($scope, dep1, dep2) { ... $scope.aMethod = function() { ... } ... }]);
The Angular way
![Page 14: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/14.jpg)
![Page 15: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/15.jpg)
function AddCtrl() { var operand1 = $(#operand1); var operand2 = $(#operand2); var result = $(#result); this.add = function() { result = operand1 + operand2; }}
![Page 16: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/16.jpg)
var operand1 = $('<input type="text" id="operand1" />');
var operand2 = $('<input type="text" id="operand1" />');
var result = $('<input type="text" id= "result" />');
var span = $('<span>'); $('body').html('<div class="ex1">') .find('div') .append(operand1) .append(operand2) .append(result); var ac = new AddCtrl(); operand1.val('1'); operand2.val('1'); ac.add(); expect(result.val()).toEqual('2'); $('body').empty();
![Page 17: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/17.jpg)
Controllers - The Angular wayfunction AddCtrl($scope) { $scope.Calc = function() { $scope.result = $scope.operand1 + $scope.operand2; }}
![Page 18: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/18.jpg)
Controllers - The Angular wayvar $scope = {};
var ctrl = $controller(‘AddCtrl’), {$scope: $scope };$scope.operand1 = 1;$scope.operand2 = 1; $scope.calc();
expect($scope.result).toEqual(2);
![Page 19: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/19.jpg)
Two types of testing that
compliment each other
![Page 20: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/20.jpg)
unit testingand
e2e testing
![Page 21: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/21.jpg)
How much reality do you needin your tests?
![Page 22: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/22.jpg)
Knowing what to test is just as important as how to test
![Page 23: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/23.jpg)
Test all the things
is not a strategy
![Page 24: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/24.jpg)
“I get paid for code that works, not for tests, so my philosophy is to test as little as possible to reach a given level of confidence…”
-- Kent Beck
![Page 25: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/25.jpg)
Focus on behaviors rather than implementation details
![Page 26: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/26.jpg)
Example – Testing a simple controller
![Page 27: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/27.jpg)
app.controller('AddCtrl', function($scope) { $scope.calc = function() { $scope.result = $scope.operand1 + $scope.operand2; }});
![Page 28: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/28.jpg)
app.controller('AddCtrl', function($scope) { $scope.calc = function() { $scope.result = $scope.operand1 + $scope.operand2; }});
describe('adding 1 + 1', function() { beforeEach(module('myApp')); });
![Page 29: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/29.jpg)
app.controller('AddCtrl', function($scope) { $scope.calc = function() { $scope.result = $scope.operand1 + $scope.operand2; }});
describe('adding 1 + 1', function() { beforeEach(module('myApp')); var ctrl, scope; beforeEach(inject(function($controller, $rootScope) { scope = $rootScope.$new(); ctrl = $controller('AddCtrl', { $scope: scope }); }));});
![Page 30: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/30.jpg)
app.controller('AddCtrl', function($scope) { $scope.calc = function() { $scope.result = $scope.operand1 + $scope.operand2; }});
describe('adding 1 + 1', function() { beforeEach(module('myApp')); var ctrl, scope; beforeEach(inject(function($controller, $rootScope) { scope = $rootScope.$new(); ctrl = $controller('AddCtrl', { $scope: scope }); }));
it('should equal 2', function() { scope.operand1 = 1; scope.operand2 = 1; scope.calc();
expect(scope.result).toEqual(2); })});
![Page 31: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/31.jpg)
Example – mocking $http
![Page 32: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/32.jpg)
var app = angular.module('myApp', []);
app.controller('MoviesController', function($scope, $http) { $http.get("/api/movies") .then(function (result) { $scope.movies = result.data; });});
![Page 33: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/33.jpg)
describe("myApp", function () { beforeEach(module('myApp')); describe("MoviesController", function () { var scope, httpBackend, http, controller;
});
![Page 34: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/34.jpg)
describe("myApp", function () { beforeEach(module('myApp')); describe("MoviesController", function () { var scope, httpBackend, http, controller;
beforeEach(inject(function ($rootScope, $controller, $httpBackend, $http) {
scope = $rootScope.$new(); httpBackend = $httpBackend; http = $http; controller = $controller; })); });
![Page 35: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/35.jpg)
describe("myApp", function () { beforeEach(module('myApp')); describe("MoviesController", function () { var scope, httpBackend, http, controller;
beforeEach(inject(function ($rootScope, $controller, $httpBackend, $http) {
scope = $rootScope.$new(); httpBackend = $httpBackend; http = $http; controller = $controller; httpBackend.when("GET", "/api/movies") .respond([{}, {}, {}]); })); });});
![Page 36: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/36.jpg)
describe("myApp", function () { beforeEach(module('myApp')); describe("MoviesController", function () { var scope, httpBackend, http, controller;
beforeEach(inject(function ($rootScope, $controller, $httpBackend, $http) {
scope = $rootScope.$new(); httpBackend = $httpBackend; http = $http; controller = $controller; httpBackend.when("GET", "/api/movies") .respond([{}, {}, {}]); }));
it('should GET movies', function () { httpBackend.expectGET('/api/movies'); controller('MoviesController', { $scope: scope, $http: http });
}); });});
![Page 37: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/37.jpg)
describe("myApp", function () { beforeEach(module('myApp')); describe("MoviesController", function () { var scope, httpBackend, http, controller;
beforeEach(inject(function ($rootScope, $controller, $httpBackend, $http) {
scope = $rootScope.$new(); httpBackend = $httpBackend; http = $http; controller = $controller; httpBackend.when("GET", "/api/movies") .respond([{}, {}, {}]); }));
it('should GET movies', function () { httpBackend.expectGET('/api/movies'); controller('MoviesController', { $scope: scope, $http: http }); httpBackend.flush(); }); });});
![Page 38: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/38.jpg)
Example - mocking services
![Page 39: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/39.jpg)
angular.module('myApp', []) .factory('greeter', function () { return 'Hello';}).factory('worldGreeter', function (greeter) { return greeter + ' World';});
![Page 40: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/40.jpg)
angular.module('myApp', []) .factory('greeter', function () { return 'Hello';}).factory('worldGreeter', function (greeter) { return greeter + ' World';});
describe('worldGreeter', function () { beforeEach(inject(function (_worldGreeter_) { worldGreeter = _worldGreeter_; }));
});
![Page 41: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/41.jpg)
angular.module('myApp', []) .factory('greeter', function () { return 'Hello';}).factory('worldGreeter', function (greeter) { return greeter + ' World';});
describe('worldGreeter', function () { beforeEach(inject(function (_worldGreeter_) { worldGreeter = _worldGreeter_; }));
it('should work with mocked greeter', function () { expect(worldGreeter).toEqual('WAT World'); });});
![Page 42: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/42.jpg)
angular.module('myApp', []) .factory('greeter', function () { return 'Hello';}).factory('worldGreeter', function (greeter) { return greeter + ' World';});
describe('worldGreeter', function () {
beforeEach(module('myApp', function($provide) { $provide.value('greeter', 'WAT'); })); beforeEach(inject(function (_worldGreeter_) { worldGreeter = _worldGreeter_; }));
it('should work with mocked greeter', function () { expect(worldGreeter).toEqual('WAT World'); });});
![Page 43: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/43.jpg)
angular.module('myApp', []) .factory('greeter', function () { return 'Hello';}).factory('worldGreeter', function (greeter) { return greeter + ' World';});
describe('worldGreeter', function () {
beforeEach(module('myApp', function ($provide) { $provide.decorator('greeter', function ($delegate) { return 'WAT'; }); })); beforeEach(inject(function (_worldGreeter_) { worldGreeter = _worldGreeter_; }));
it('should work with mocked greeter', function () { expect(worldGreeter).toEqual('WAT World'); });});
![Page 44: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/44.jpg)
Example – testing a directive
![Page 45: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/45.jpg)
var app = angular.module('myApp', []);app.directive('simpleDirective', function (){ return { restrict: 'E', template: '<div>{{value}}</div>', scope: { value: '=' } };});
![Page 46: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/46.jpg)
describe('Testing simpleDirective', function() { var scope, elem, directive, compiled, html; beforeEach(function () { module('myApp‘); }); });
it('Should set the text of the element to whatever was passed.', function() { });});
![Page 47: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/47.jpg)
describe('Testing simpleDirective', function() { var scope, elem, directive, compiled, html; beforeEach(function (){ module('myApp'); html = '<simple-directive value="abc"></simple-directive>'; });
it('Should set the text of the element to whatever was passed.', function() { });});
![Page 48: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/48.jpg)
describe('Testing simpleDirective', function() { var scope, elem, directive, compiled, html; beforeEach(function (){ module('myApp'); html = ‘<simple-directive value="abc"></simple-directive>'; inject(function($compile, $rootScope) { scope = $rootScope.$new(); elem = angular.element(html); compiled = $compile(elem); compiled(scope); }); });
it('Should set the text of the element to whatever was passed.', function() { });});
![Page 49: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/49.jpg)
describe('Testing simpleDirective', function() { var scope, elem, directive, compiled, html; beforeEach(function (){ module('myApp'); html = ‘<simple-directive value="abc"></simple-directive>'; inject(function($compile, $rootScope) { scope = $rootScope.$new(); elem = angular.element(html); compiled = $compile(elem); compiled(scope); }); });
it('Should set the text of the element to whatever was passed.', function() { expect(elem.text()).toBe('blah'); });});
![Page 50: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/50.jpg)
describe('Testing simpleDirective', function() { var scope, elem, directive, compiled, html; beforeEach(function (){ module('myApp'); html = ‘<simple-directive value="abc"></simple-directive>'; inject(function($compile, $rootScope) { scope = $rootScope.$new(); elem = angular.element(html); compiled = $compile(elem); compiled(scope); }); });
it('Should set the text of the element to whatever was passed.', function() { scope.abc = 'blah'; scope.$digest();
expect(elem.text()).toBe('blah'); });});
![Page 51: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/51.jpg)
e2e testing / protractor
![Page 52: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/52.jpg)
<body> <h1>Sample</h1> <div> Two Way Data Binding Sample <br/><br/> <input type="text" ng-model="name" /> <span ng-show="name"><h4>Hello {{name}}</h4></span> </div> </body>
![Page 53: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/53.jpg)
describe(demo page', function() { it('should greet the user', function() { browser.get('[some route]'); }); });
<body> <h1>Sample</h1> <div> Two Way Data Binding Sample <br/><br/> <input type="text" ng-model="name" /> <span ng-show="name"><h4>Hello {{name}}</h4></span> </div> </body>
![Page 54: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/54.jpg)
describe(demo page', function() { it('should greet the user', function() { browser.get('[some route]'); element(by.model('name')).sendKeys('Nate Peterson'); }); });
<body> <h1>Sample</h1> <div> Two Way Data Binding Sample <br/><br/> <input type="text" ng-model="name" /> <span ng-show="name"><h4>Hello {{name}}</h4></span> </div> </body>
![Page 55: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/55.jpg)
describe(demo page', function() { it('should greet the user', function() { browser.get('[some route]'); element(by.model('name')).sendKeys('Nate Peterson'); var greeting = element(by.binding('name')); }); });
<body> <h1>Sample</h1> <div> Two Way Data Binding Sample <br/><br/> <input type="text" ng-model="name" /> <span ng-show="name"><h4>Hello {{name}}</h4></span> </div> </body>
![Page 56: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/56.jpg)
describe(demo page', function() { it('should greet the user', function() { browser.get('[some route]'); element(by.model('name')).sendKeys('Nate Peterson'); var greeting = element(by.binding('name')); expect(greeting.getText()).toEqual('Hello 'Nate Peterson');
}); });
<body> <h1>Sample</h1> <div> Two Way Data Binding Sample <br/><br/> <input type="text" ng-model="name" /> <span ng-show="name"><h4>Hello {{name}}</h4></span> </div> </body>
![Page 57: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/57.jpg)
What’s worked well so far
![Page 58: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/58.jpg)
Use of a Mock API for e2e tests
![Page 59: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/59.jpg)
What’s been hard
![Page 60: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/60.jpg)
Bloated controllers that lead to
bloated specs
![Page 61: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/61.jpg)
Complicated unit test setup
![Page 62: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/62.jpg)
Hard to read tests
![Page 63: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/63.jpg)
Questions?
![Page 64: AngularJS Testing Strategies](https://reader034.vdocuments.site/reader034/viewer/2022042515/554f63d2b4c9058a148b49a0/html5/thumbnails/64.jpg)
AngularJS testing
strategies
Nate Peterson@njpetersonPa