Writing unit tests
The unit test runner is mocha using the TDD interface. Mocha doesn't ship with an assertion library (there is no ok
or assert_equals
), so we use chai to provide assertions.
It's highly recommended that you read though the mocha site, since all tests are really mocha tests. The documentation here is focused on getting you started, and about our special integrations with test-agent and Gaia.
It's also important to note that we add special functions (like require()
and requireApp()
) to make writing tests easier. All test helper scripts can be found in the /common/test
directory.
File naming
Tests are usually one to one. One implementation lives in the js/
directory, and one test lives in the test/
directory.
Examples
Implementation | Test |
apps/app/js/file.js | apps/app/test/unit/file_test.js |
apps/app/js/nested/thing/file.js | apps/app/test/unit/nested/thing/file_test.js |
Example Implementation (gist):
//apps/example/js/example.js var Example = (function(){ return { math: function() { }, complexMethod: function() { }, asyncMethod: function(callback) { } } }());
Example Test (gist):
//apps/example/test/unit/example_test.js requireApp('example/js/example.js'); //suite/setup/test/done are standard mocha functionality. suite('Example', function() { var subject; //will be called before each "test" block. setup(function() { subject = Example(); }); //for a simple method test('#math', function() { var result = subject.math('1', '+', '1'); //assert functionality is provided by chai assert.equal(result, 2, 'addition should work'); }); //there is full support for async tests using done //when you set an argument to your test function it is //assumed that the given test is async and will only //complete once done is called. test('#asyncMethod', function(done) { subject.asyncMethod(function(err, value) { done(function() { assert.ok(value, 'sending message failed'); }); }); }); //when you have a method that will //require complex setup/teardown logic suite('#complexMethod', function() { var result; setup(function() { //complex setup stuff result = subject.complexMethod(); }); test('stuff works', function() { assert.typeOf(result, 'string'); //it is good practice to add the third argument which is //a description of why a test failed. assert.equal(result, 'real value', 'should output real value'); }); }); });