Testing

Unit testing helps maintain clean code, as such I included some of my recommendations for unit testing foundations with links for more information.

Write Tests with Stories

[Style Y190]
  • Write a set of tests for every story. Start with an empty test and fill them in as you write the code for the story.

    Why?: Writing the test descriptions helps clearly define what your story will do, will not do, and how you can measure success.

    it('should have Avengers controller', function() {
        // TODO
    });
    
    
    it('should find 1 Avenger when filtered by name', function() {
        // TODO
    });
    
    
    it('should have 10 Avengers', function() {
        // TODO (mock data?)
    });
    
    
    it('should return Avengers via XHR', function() {
        // TODO ($httpBackend?)
    });
    
    
    // and so on
    

Testing Library

[Style Y191]
  • Use Jasmine or Mocha for unit testing.

    Why?: Both Jasmine and Mocha are widely used in the AngularJS community. Both are stable, well maintained, and provide robust testing features.

    Note: When using Mocha, also consider choosing an assert library such as Chai.

Test Runner

[Style Y192]
  • Use Karma as a test runner.

    Why?: Karma is easy to configure to run once or automatically when you change your code.

    Why?: Karma hooks into your Continuous Integration process easily on its own or through Grunt or Gulp.

    Why?: Some IDE’s are beginning to integrate with Karma, such as WebStorm and Visual Studio.

    Why?: Karma works well with task automation leaders such as Grunt (with grunt-karma) and Gulp (with gulp-karma).

Stubbing and Spying

[Style Y193]
  • Use Sinon for stubbing and spying.

    Why?: Sinon works well with both Jasmine and Mocha and extends the stubbing and spying features they offer.

    Why?: Sinon makes it easier to toggle between Jasmine and Mocha, if you want to try both.

Headless Browser

[Style Y194]
  • Use PhantomJS to run your tests on a server.

    Why?: PhantomJS is a headless browser that helps run your tests without needing a “visual” browser. So you do not have to install Chrome, Safari, IE, or other browsers on your server.

    Note: You should still test on all browsers in your environment, as appropriate for your target audience.

Code Analysis

[Style Y195]
  • Run JSHint on your tests.

    Why?: Tests are code. JSHint can help identify code quality issues that may cause the test to work improperly.

Alleviate Globals for JSHint Rules on Tests

[Style Y196]
  • Relax the rules on your test code to allow for common globals such as describe and expect.

    Why?: Your tests are code and require the same attention and code quality rules as all of your production code. However, global variables used by the testing framework, for example, can be relaxed by including this in your test specs.

    /* global sinon, describe, it, afterEach, beforeEach, expect, inject */
    

Testing Tools

Organizing Tests

[Style Y197]
  • Place unit test files (specs) side-by-side with your client code. Place specs that cover server integration or test multiple components in a separate tests folder.

    Why?: Unit tests have a direct correlation to a specific component and file in source code.

    Why?: It is easier to keep them up to date since they are always in sight. When coding whether you do TDD or test during development or test after development, the specs are side-by-side and never out of sight nor mind, and thus more likely to be maintained which also helps maintain code coverage.

    Why?: When you update source code it is easier to go update the tests at the same time.

    Why?: Placing them side-by-side makes it easy to find them and easy to move them with the source code if you move the source.

    Why?: Having the spec nearby makes it easier for the source code reader to learn how the component is supposed to be used and to discover its known limitations.

    Why?: Separating specs so they are not in a distributed build is easy with grunt or gulp.

    /src/client/app/customers/customer-detail.controller.js
                             /customer-detail.controller.spec.js
                             /customers.controller.spec.js
                             /customers.controller-detail.spec.js
                             /customers.module.js
                             /customers.route.js
                             /customers.route.spec.js