Intro To Unit Testing In AngularJS
Jim Lynch Front-End Engineer at Altered Image twitter.com/webWhizJim Slides available here: http://www.slideshare.net/ JimLynch22/intro-to-unit-testing-in-angularjs
Who is This Talk For? • People interested in unit testing. • AngularJS developers. • Front-End developers.
Why Test? • To prevent regression (recurring bugs). • Catches bugs before end users see them. • Removes fear from refactoring. • Much quicker and less error-prone than manual testing. • Can be a form of documentation for your code.
If You Don’t Test… WRITE UNIT TESTS!!
Anatomy of a Test Suite
Anatomy of a Test Suite Test Suite
Anatomy of a Test Suite Test Case Test Case Test Suite
Anatomy of a Test Suite Test Case Assertion Assertion Assertion Test Case Test Suite
Anatomy of a Test Suite Test Suite • A collection of independent tests. • Usually exists as its own file. • Contains methods for setting up for and tearing down unit tests. Test Case Assertion Assertion Assertion Test Case Test Suite
Anatomy of a Test Suite Test Case • Tests a single “piece” of your application independent of the other code. • A function that can either pass or fail. • Each case should test a different “situation” from the user’s perspective (BDD). Test Case Assertion Assertion Assertion Test Case Test Suite
Anatomy of a Test Suite Test Case Assertion Assertion Assertion Test Case Test Suite Assertion • Uses a matcher API for comparing values 
 eg. expected(var).toEqual(5) • Tells the test case when it should pass and when it should fail. • If output values for SUT (system under test) are as expected from known input then behavior of SUT is as expected.
Unit testing in JavaScript uses a peculiar syntax…
If you are ever feeling lost, just remember that a test suite in JavaScript is this:
A describe full of it’s with some beforeEach’s
Test Suite Anatomy for JS
 Testing Frameworks it describeTest Suite Test Case Assertion expect it expect expect
Building Your First Test Suite • A test suite is simply a Javascript file. • Karma will automatically consider *.spec.js files to be test suites. Step 1) Create an empty *.spec.js file.
describe describe(‘MyController’, function() { }) Building Your First Test Suite Adding a describe.
describe describe(‘MyController’, function() { }) A name for your test suite 
 (can be anything, but it should describe what you are testing!). Building Your First Test Suite Adding a describe.
describe describe(‘MyController’, function() { }) A function that takes no arguments. This creates the “wrapper” around your test cases. Building Your First Test Suite Adding a describe.
describe describe(‘MyController’, function() { }) it Building Your First Test Suite it(‘Should do something…’, function() { }); Adding an it.
describe describe(‘MyController’, function() { }) Some text that describes the purpose of this test case. Can be anything but usually begins with the word should. it Building Your First Test Suite it(‘Should do something…’, function() { }); Adding an it.
describe describe(‘MyController’, function() { }) it Building Your First Test Suite it(‘Should do something…’, function() { }); A function that takes no arguments. The code for this test case is contained in this function. Adding an it.
describe describe(‘MyController’, function() { }) it Building Your First Test Suite it(‘Should do something…’, function() { }); Adding an assertion. expect expect(true).toEqual(true);
describe describe(‘MyController’, function() { }) it Building Your First Test Suite it(‘Should do something…’, function() { }); Adding an assertion. expect expect(true).toEqual(true); The expect keyword lets the test case know that we want to do an assertion here.
describe describe(‘MyController’, function() { }) it Building Your First Test Suite it(‘Should do something…’, function() { }); Adding an assertion. expect expect(true).toEqual(true); The expect method takes one argument: the variable whose value you wish to check.
describe describe(‘MyController’, function() { }) it Building Your First Test Suite it(‘Should do something…’, function() { }); Adding an assertion. expect expect(true).toEqual(true); Depending on how you wish to compare the two values, a matcher method is chained onto the end of the expect.
describe describe(‘MyController’, function() { }) it Building Your First Test Suite it(‘Should do something…’, function() { }); Adding an assertion. expect expect(true).toEqual(true); The matcher method takes one argument: the expected value for the variable being passed into the expect method.
Building Your First Test Suite You did it! describe(‘MyController’, function() { }) it(‘Should do something…’, function() { }); expect(true).toEqual(true); Ahhh, so a test suite is really just…
A describe full of it’s! …with some beforeEach’s.
beforeEach • Goes inside the describe but outside of the it’s. describe it expect it expect beforeEach beforeEach • Gives you access to your module, controllers, services, etc. through DI.
beforeEach describe(‘MyController’, function() { }) it(‘Should do something…’, function() { }); expect(true).toEqual(true); beforeEach(module(‘YOUR_MODULE’));
beforeEach beforeEach(module(‘YOUR_MODULE’)); Keyword that runs argument before every it.
beforeEach beforeEach(module(‘YOUR_MODULE’)); Allows you to load in your module so that you have access to it’s controllers, services, filters, etc.
beforeEach beforeEach(module(‘YOUR_MODULE’)); Replace this with the name of your project’s module.
Injecting a Controller with beforeEach describe(‘MyController’, function() { }) it(‘Should do something…’, function() { }); expect(true).toEqual(true); beforeEach(module(‘YOUR_MODULE’)); var myController = $controller('MyController', {}) beforeEach(inject(function(_$controller_) { $controller = _$controller_; }));
Injecting a Controller with beforeEach beforeEach(inject(function(_$controller_) { $controller = _$controller_; })); A method from the angular- mocks.js file that allows you to inject services into your unit tests.
Injecting a Controller with beforeEach beforeEach(inject(function(_$controller_) { $controller = _$controller_; })); Angular knows to “unwrap”, the underscores, find corresponding provider, and give you a reference to the service. Q. But what’s the deal with those underscores on either side?
Injecting a Controller with beforeEach beforeEach(inject(function(_$controller_) { $controller = _$controller_; })); Angular knows to “unwrap”, the underscores, find corresponding provider, and give you a reference to the service. Suppose you didn’t use the underscores. You want to set a variable named $controller available inside of your “it’s” equal to the function’s argument, but the function argument must be named $controller in order to be injected properly. Doing this is not possible in JavaScript so the Angular team implemented the underscore notation to work around the issue.
Injecting a Controller with beforeEach beforeEach(inject(function(_$controller_) { $controller = _$controller_; })); You can then use this global reference anywhere in the test suite to instantiate controllers.
Using the Injected Controller var myController = $controller('MyController', {}) This var has all of the properties and methods you defined for the specified controller.
Using the Injected Controller var myController = $controller('MyController', {}) This is the global $controller variable that was set in the beforeEach.
Using the Injected Controller var myController = $controller('MyController', {}) Replace this with the name of the controller you want to instantiate.
Pass in any arguments to your controller with this object. var myController = $controller('MyController', {}) Using the Injected Controller
The Complete Suite describe(‘MyController’, function() { }) it(‘Should do something…’, function() { }); expect(true).toEqual(true); beforeEach(module(‘YOUR_MODULE’)); var myController = $controller('MyController', {}) beforeEach(inject(function(_$controller_) { $controller = _$controller_; })); A good start to a nice looking test suite:
Okay, so how do I run these test suites? Q ) KarmaA )
Fun Facts About Karma • Created at Google- now open source. • It’s a command line test runner. • Integrates with practically all CI tools. • Runs tests on all browsers (even PhantomJS).
How Does Karma Work? • It integrates nicely with Gulp and Grunt (gulp test) or runs on its own (karma start). • It’s installed from npm: npm install karma • The karma.conf.js file allows you to configure it to run with your desired settings. • It automatically sees *.spec.js files in your project folder as test suites.
How do I add Karma to My Project?
Easy Way Hard(er) Way Use a yeoman generator to scaffold a project that already has karma set up for you (such as the Gulp-Angular generator). Install and configure it manually. karma-runner.github.io Adding Karma to Your Project And then you’re ready to start testing!
All together now! A JavaScript test suite is:
A describe full of it’s with some beforeEach’s
Thanks! twitter.com/webWhizJim jim@wisdomofjim.com https://www.teepublic.com/t-shirt/468156- describes-full-of-its-white-text www.wisdomofjim.com The official “Describe’s Full of It’s” T-Shirt! Available now! Slides available here: http:// www.slideshare.net/JimLynch22/intro-to-unit- testing-in-angularjs

Intro to Unit Testing in AngularJS

  • 1.
    Intro To UnitTesting In AngularJS
  • 2.
    Jim Lynch Front-End Engineer atAltered Image twitter.com/webWhizJim Slides available here: http://www.slideshare.net/ JimLynch22/intro-to-unit-testing-in-angularjs
  • 3.
    Who is ThisTalk For? • People interested in unit testing. • AngularJS developers. • Front-End developers.
  • 4.
    Why Test? • Toprevent regression (recurring bugs). • Catches bugs before end users see them. • Removes fear from refactoring. • Much quicker and less error-prone than manual testing. • Can be a form of documentation for your code.
  • 5.
    If You Don’tTest… WRITE UNIT TESTS!!
  • 6.
    Anatomy of aTest Suite
  • 7.
    Anatomy of aTest Suite Test Suite
  • 8.
    Anatomy of aTest Suite Test Case Test Case Test Suite
  • 9.
    Anatomy of aTest Suite Test Case Assertion Assertion Assertion Test Case Test Suite
  • 10.
    Anatomy of aTest Suite Test Suite • A collection of independent tests. • Usually exists as its own file. • Contains methods for setting up for and tearing down unit tests. Test Case Assertion Assertion Assertion Test Case Test Suite
  • 11.
    Anatomy of aTest Suite Test Case • Tests a single “piece” of your application independent of the other code. • A function that can either pass or fail. • Each case should test a different “situation” from the user’s perspective (BDD). Test Case Assertion Assertion Assertion Test Case Test Suite
  • 12.
    Anatomy of aTest Suite Test Case Assertion Assertion Assertion Test Case Test Suite Assertion • Uses a matcher API for comparing values 
 eg. expected(var).toEqual(5) • Tells the test case when it should pass and when it should fail. • If output values for SUT (system under test) are as expected from known input then behavior of SUT is as expected.
  • 13.
    Unit testing inJavaScript uses a peculiar syntax…
  • 14.
    If you areever feeling lost, just remember that a test suite in JavaScript is this:
  • 15.
    A describe full of it’s withsome beforeEach’s
  • 16.
    Test Suite Anatomyfor JS
 Testing Frameworks it describeTest Suite Test Case Assertion expect it expect expect
  • 17.
    Building Your FirstTest Suite • A test suite is simply a Javascript file. • Karma will automatically consider *.spec.js files to be test suites. Step 1) Create an empty *.spec.js file.
  • 18.
    describe describe(‘MyController’, function(){ }) Building Your First Test Suite Adding a describe.
  • 19.
    describe describe(‘MyController’, function(){ }) A name for your test suite 
 (can be anything, but it should describe what you are testing!). Building Your First Test Suite Adding a describe.
  • 20.
    describe describe(‘MyController’, function(){ }) A function that takes no arguments. This creates the “wrapper” around your test cases. Building Your First Test Suite Adding a describe.
  • 21.
    describe describe(‘MyController’, function() { }) it BuildingYour First Test Suite it(‘Should do something…’, function() { }); Adding an it.
  • 22.
    describe describe(‘MyController’, function() { }) Sometext that describes the purpose of this test case. Can be anything but usually begins with the word should. it Building Your First Test Suite it(‘Should do something…’, function() { }); Adding an it.
  • 23.
    describe describe(‘MyController’, function() { }) it BuildingYour First Test Suite it(‘Should do something…’, function() { }); A function that takes no arguments. The code for this test case is contained in this function. Adding an it.
  • 24.
    describe describe(‘MyController’, function() { }) it BuildingYour First Test Suite it(‘Should do something…’, function() { }); Adding an assertion. expect expect(true).toEqual(true);
  • 25.
    describe describe(‘MyController’, function() { }) it BuildingYour First Test Suite it(‘Should do something…’, function() { }); Adding an assertion. expect expect(true).toEqual(true); The expect keyword lets the test case know that we want to do an assertion here.
  • 26.
    describe describe(‘MyController’, function() { }) it BuildingYour First Test Suite it(‘Should do something…’, function() { }); Adding an assertion. expect expect(true).toEqual(true); The expect method takes one argument: the variable whose value you wish to check.
  • 27.
    describe describe(‘MyController’, function() { }) it BuildingYour First Test Suite it(‘Should do something…’, function() { }); Adding an assertion. expect expect(true).toEqual(true); Depending on how you wish to compare the two values, a matcher method is chained onto the end of the expect.
  • 28.
    describe describe(‘MyController’, function() { }) it BuildingYour First Test Suite it(‘Should do something…’, function() { }); Adding an assertion. expect expect(true).toEqual(true); The matcher method takes one argument: the expected value for the variable being passed into the expect method.
  • 29.
    Building Your FirstTest Suite You did it! describe(‘MyController’, function() { }) it(‘Should do something…’, function() { }); expect(true).toEqual(true); Ahhh, so a test suite is really just…
  • 30.
  • 31.
    beforeEach • Goes insidethe describe but outside of the it’s. describe it expect it expect beforeEach beforeEach • Gives you access to your module, controllers, services, etc. through DI.
  • 32.
    beforeEach describe(‘MyController’, function() { }) it(‘Shoulddo something…’, function() { }); expect(true).toEqual(true); beforeEach(module(‘YOUR_MODULE’));
  • 33.
  • 34.
    beforeEach beforeEach(module(‘YOUR_MODULE’)); Allows you toload in your module so that you have access to it’s controllers, services, filters, etc.
  • 35.
  • 36.
    Injecting a Controller withbeforeEach describe(‘MyController’, function() { }) it(‘Should do something…’, function() { }); expect(true).toEqual(true); beforeEach(module(‘YOUR_MODULE’)); var myController = $controller('MyController', {}) beforeEach(inject(function(_$controller_) { $controller = _$controller_; }));
  • 37.
    Injecting a Controller withbeforeEach beforeEach(inject(function(_$controller_) { $controller = _$controller_; })); A method from the angular- mocks.js file that allows you to inject services into your unit tests.
  • 38.
    Injecting a Controller withbeforeEach beforeEach(inject(function(_$controller_) { $controller = _$controller_; })); Angular knows to “unwrap”, the underscores, find corresponding provider, and give you a reference to the service. Q. But what’s the deal with those underscores on either side?
  • 39.
    Injecting a Controller withbeforeEach beforeEach(inject(function(_$controller_) { $controller = _$controller_; })); Angular knows to “unwrap”, the underscores, find corresponding provider, and give you a reference to the service. Suppose you didn’t use the underscores. You want to set a variable named $controller available inside of your “it’s” equal to the function’s argument, but the function argument must be named $controller in order to be injected properly. Doing this is not possible in JavaScript so the Angular team implemented the underscore notation to work around the issue.
  • 40.
    Injecting a Controller withbeforeEach beforeEach(inject(function(_$controller_) { $controller = _$controller_; })); You can then use this global reference anywhere in the test suite to instantiate controllers.
  • 41.
    Using the Injected Controller varmyController = $controller('MyController', {}) This var has all of the properties and methods you defined for the specified controller.
  • 42.
    Using the Injected Controller varmyController = $controller('MyController', {}) This is the global $controller variable that was set in the beforeEach.
  • 43.
    Using the Injected Controller varmyController = $controller('MyController', {}) Replace this with the name of the controller you want to instantiate.
  • 44.
    Pass in anyarguments to your controller with this object. var myController = $controller('MyController', {}) Using the Injected Controller
  • 45.
    The Complete Suite describe(‘MyController’,function() { }) it(‘Should do something…’, function() { }); expect(true).toEqual(true); beforeEach(module(‘YOUR_MODULE’)); var myController = $controller('MyController', {}) beforeEach(inject(function(_$controller_) { $controller = _$controller_; })); A good start to a nice looking test suite:
  • 46.
    Okay, so howdo I run these test suites? Q ) KarmaA )
  • 47.
    Fun Facts AboutKarma • Created at Google- now open source. • It’s a command line test runner. • Integrates with practically all CI tools. • Runs tests on all browsers (even PhantomJS).
  • 48.
    How Does KarmaWork? • It integrates nicely with Gulp and Grunt (gulp test) or runs on its own (karma start). • It’s installed from npm: npm install karma • The karma.conf.js file allows you to configure it to run with your desired settings. • It automatically sees *.spec.js files in your project folder as test suites.
  • 49.
    How do Iadd Karma to My Project?
  • 50.
    Easy Way Hard(er)Way Use a yeoman generator to scaffold a project that already has karma set up for you (such as the Gulp-Angular generator). Install and configure it manually. karma-runner.github.io Adding Karma to Your Project And then you’re ready to start testing!
  • 51.
    All together now! AJavaScript test suite is:
  • 52.
    A describe full of it’s withsome beforeEach’s
  • 53.
    Thanks! twitter.com/webWhizJim jim@wisdomofjim.com https://www.teepublic.com/t-shirt/468156- describes-full-of-its-white-text www.wisdomofjim.com The official “Describe’sFull of It’s” T-Shirt! Available now! Slides available here: http:// www.slideshare.net/JimLynch22/intro-to-unit- testing-in-angularjs