Unit Test
Introduction
JSX has a built-in test runner invoked by --test
option and has an unit test framework test-case.jsx
. The unit test framework is an xUnit style, running _Test#test*():void
of the given file.
Here is a simple test file, which is typically placed in t/
of a project.
import "test-case.jsx";
class _Test extends TestCase {
function testAdd() : void {
this.expect(1 + 2).toBe(3);
this.expect(1 + 3).toBe(4);
}
}
To run the test file, invoke jsx --test test.jsx
, and you will see a TAP output like:
1..1 ok 1 ok 2 1..2 ok 1 - testAdd
NOTE: it is recommended to use prove(1) to run tests and parse TAP, which can run test files in parallel. See .proverc and and Makefile in the mizuki project.
Synchronous Test
Synchronous testing is really simple, where you just define test methods, which are invoked in serial.
For example, the folowing test class callstestFirst()
, testSecond()
, testThird()
in this order.
import "test-case.jsx";
class _Test extends TestCase {
function testFirst() : void {
this.expect(1 + 2).toBe(3);
}
function testSecond() : void {
this.expect(1 + 3).toBe(4);
}
function testThird() : void {
this.expect(1 + 4).toBe(5);
}
}
Asynchronous Test
test-case.jsx
supports asynchronous tests to test callback-based methods, such as Timer.setTimeout()
.
An asynchronous test starts with this.async()
method, taking a block with an AsyncContext instance, and telling it that the test is done.
import "test-case.jsx";
class _Test extends TestCase {
function testSetTimeout() : void {
this.async(function(async : AsyncContext) : void {
var to = 200;
var t0 = Date.now();
Timer.setTimeout(function() : void {
var t1 = Date.now();
this.expect(t1 - t0, "setTimeout 200 ms.").toBeGE(to - 50);
async.done(); // to tell this test is finished
}, to);
}, 1000 /* timeout in milliseconds */);
}
}
Set Up / Tear Down
You can define setUp()
/ tearDown()
which are called for each test method to manage test environments.
These methods take no arguments for synchronous test methods, while take an AsyncContext for asynchronous test methods.
import "test-case.jsx";
// for synchronous test
class _Test extends TestCase {
override function setUp() : void {
this.diag("setUp");
}
override function tearDown() : void {
this.diag("tearDown");
}
function testFoo() : void {
this.pass("foo");
}
function testBar() : void {
this.pass("bar");
}
}
import "test-case.jsx";
import "timer.jsx";
// for asynchronous test
class _Test extends TestCase {
override function setUp(async : AsyncContext) : void {
this.diag("setUp for " + async.name());
}
override function tearDown(async : AsyncContext) : void {
this.diag("tearDown for " + async.name());
}
function testFooAsync() : void {
this.async((async) -> {
Timer.setTimeout(() -> {
this.pass("foo");
async.done();
}, 1);
}, 1000);
}
function testBarAsync() : void {
this.async((async) -> {
Timer.setTimeout(() -> {
this.pass("bar");
async.done();
}, 1);
}, 1000);
}
}
Misc.
jsx --test can takes test method names to run specific tests in a file. When you use jsx.vim you can run the currently editing test method by \t
.
See Also
- test-case.jsx reference
- JSX/t/lib/*.jsx for example