Writing Gaia Unit Tests

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');
    });
  });
});

Document Tags and Contributors

 Contributors to this page: chrisdavidmills, freddyb, GiovanniC, teoli, kscarfone, espressive
 Last updated by: chrisdavidmills,