Table of Contents
- Installation
- Basic Usage
- Reporters
- mocha.setup()
- mocha.run()
- Using should.js with ti-mocha
- Titanium + mocha + should example
- Tips
- Caveats
- Links
Installation
Easy Way
cd /path/to/Titanium/project && npm install ti-mocha --prefix ./node_modules
If executed in your project's root folder, this will put ti-mocha.js in Resources
for traditional Titanium apps, or app/lib
for Alloy apps.
Less Easy Way
- Download ti-mocha.js.
- Copy
ti-mocha.js
into your project'sResources
folder (orapp/lib
if you're using alloy).
Basic Usage
// creates the "mocha" global necessary to run a test suite anywhere in your app
require('ti-mocha');
// create the test suite
describe('ti-mocha', function() {
describe('suite 1', function() {
it('shows passing tests (fast)', function(){});
it('shows passing tests (slow)', function(done){
setTimeout(done, 1500);
});
});
describe('suite 2', function() {
it('shows pending tests');
it('fails a test', function() {
throw new Error('this shoud fail');
});
});
});
// run the tests
mocha.run();
Reporters
- ti-spec - Titanium-compatible version of the original mocha spec reporter
- ti-spec-studio - Same as ti-spec, but this one is optimized for use in Titanium Studio
- ti-json - Titanium-compatible version of the original mocha json reporter
The ti-spec reporter is chosen by default. To switch to a different reporter, use mocha's setup()
function before run your test suites. Original mocha reporters upon which these reporters are based can be found here.
mocha.setup()
There's few new properties you can add via mocha.setup()
to configure your test runs.
var outputFile = Ti.Filesystem.getFile(Ti.Filesystem.tempDirectory, 'results.json');
outputFile.createFile();
mocha.setup({
reporter: 'ti-json', // the reporter to use with your tests
outputFile: outputFile, // write results to the given Ti.Filesystem.File file
quiet: true // if true, suppress all console logging
});
mocha.run()
This will kick off your tests. Additionally, you can give it a callback argument to be executed once the tests complete.
var runner = mocha.run(function() {
// print the stats from the runner after the test completes
console.log(JSON.stringify(runner.stats));
});
Note for reporter developers
Giving your reporter the suffix "-studio" will automatically modify ti-mocha's underlying console.log()
implementation to exclude ANSI code sequences (covered in Caveats). This helps to automatically optimize your test output for the Titanium Studio console.
Using should.js with ti-mocha
While mocha doesn't care what you use as your assertion library, it works particularly well with should.js, not coincidentally due to them having the same author. To install should.js:
- Download should.js.
- Copy
should.js
into your project'sResources
folder.
For full documentation on what should.js can do for your tests, check out the documentation.
Titanium + mocha + should example
app.js
require('ti-mocha');
// create a basic UI
var win = Ti.UI.createWindow({
backgroundColor: '#fff',
fullscreen: false,
exitOnClose: true,
id: 'myWindow'
});
var view = Ti.UI.createView({
height: Ti.UI.FILL,
width: Ti.UI.FILL,
backgroundColor: '#a00',
id: 'myView'
});
win.add(view);
// run tests after window opens to ensure UI is initialized
win.addEventListener('open', function() {
require('test/app_test')(win, view);
});
// show the UI
win.open();
test/app_test.js
var should = require('should');
module.exports = function(win, view) {
describe('app.js', function() {
describe('#myWindow', function() {
it('exists', function() {
should.exist(win);
win.id.should.equal('myWindow');
});
it('has Ti.UI.Window functions', function() {
should(win.open).be.a.Function;
should(win.close).be.a.Function;
if (Ti.Platform.name === 'iPhone OS') {
should(win.hideTabBar).be.a.Function;
}
});
it('has dimensions equal to the device', function() {
win.size.height.should.equal(Ti.Platform.displayCaps.platformHeight);
win.size.width.should.equal(Ti.Platform.displayCaps.platformWidth);
});
});
describe('#myView', function() {
it('exists', function(){
should.exist(view);
view.id.should.equal('myView');
});
it('has Ti.UI.View functions', function() {
should(view.add).be.a.Function;
});
it('is a child of window', function() {
win.children.length.should.equal(1);
should.exist(win.children[0]);
win.children[0].id.should.equal('myView');
});
it('view has same dimensions as window', function(){
view.size.height.should.equal(win.size.height);
view.size.width.should.equal(win.size.width);
});
});
});
// run the tests
mocha.run();
};
output
Tips
- Set your log level to
info
to get the best looking test results. - .jshintrc for Titanium + mocha + should
- If you're going to test Titanium UI state (like size and position), be sure to wait until the UI is ready. The easiest way to do this in most cases is to wait for the containing Ti.UI.Window to be open.
var win = Ti.UI.createWindow();
// assemble the rest of "win" UI
win.addEventListener('open', function() {
// run tests against "win" or its children
});
win.open();
Caveats
These caveats include tips for usage, as well as for development of your own Titanium-compatible reporters.
Titanium proxies don't play well with should.js
should.js works by extending Object.prototype
with the should
object. While this works for all pure Javascript objects and most Titanium proxy properties, it does not update the proxies themselves, or their functions. When attempting to use should
directly on Titanium proxies or their functions, you must wrap the proxy or function in a should
call to avoid a runtime undefined
error.
var should = require('should');
var win = Ti.UI.createWindow();
win.open.should.be.a.Function; // will throw a runtime error
should(win.open).be.a.Function; // will work as expected
Ti.API calls and Studio Console don't like ANSI codes
Much of the reporters in mocha, including ti-spec
which is optimized for the terminal, make use of ANSI codes for the test reporting output. These are integral to coloring, as well as controlling the cursor in mocha's reporters. Unfortunately, Titanium Studio's console does not handle ANSI codes, either ignoring them or printing them as literals. On top of this, the Ti.API calls will often mangle commonly used ANSI characters, like ✓ or ✖. For this reason, when constructing your own reporters, it's wise to use standard characters or test heavily for compatibility before using any ANSI codes.
Ti.API calls trim leading whitespace
For example, this:
Ti.API.info(' this should have 4 leading spaces');
will print as this (notice the lack of leading spaces):
this should have 4 leading spaces
In order to workaround this, we can take advantage of the previously mentioned caveat. If you wrap your whitespace in an ignored ANSI code, the whitespace will be preserved. So the above code would print with the 4 leading spaces if you modified it to look like this:
// color() helper from Base reporter class
var color = require('./base').color;
Ti.API.info(color('suite', ' ') + 'this should have 4 leading spaces');
// or you can simply include the whitespace in the coloring of the whole line
Ti.API.info(color('suite', ' this should have 4 leading spaces'));