--- layout: home ---
Hopefully these docs help you out, but if they don't then please file a bug. Documentation bugs will be treated with high priority.
describe, it, before, after, expect, mockThere's another class of foounit keywords for asynchronous testing, but these are explained in the async awesomeness section.
waitFor, run, waitForTimeout
In BDD-speak an it block is an example that defines usage of a feature. So let's say we want to test that a string is less than 10 characters. You might create an it block that looks like this:
it('returns true', function (){ var str = "sml_string"; // expect is assertion... don't worry about this for now, but this test will pass expect(str.length < 10).to(beTrue); });
You might think that an it block is overkill for a test like this, but this is a contrived example. The nice thing about using an it block is that you can provide documentation for the next developer working on the code.
If you want to experiment, you can try this example. Create a file called test.js with this code:
var foounit = require('foounit').globalize(); it('fails the test', function (){ expect(true).to(beFalse); }); foounit.run();Then run the file with this command:
$ node test.js
This test will fail, but it will give you an idea of what happens when you run an example.
Internally, describe creates a group of examples. describes describe a group of related behavior.
Let's say you have a signup form widget that lets you submit a form when you have a password that is 8 or more characters, but it shows an error message if you have password that is less than 8 characters. You'll have a test that looks like this:
describe('when the password is 8 or more characters', function (){ it('allows you to submit the form', function (){ ... }); }); describe('when the password is less than 8 characters', function (){ it('displays an error message', function (){ ... }); });
You can nest describes if your code has nested behaviors (or nested if statements). Nested describes look something like this:
describe('when foo is not falsy', function (){ describe('when foo is an integer', function (){ it('returns true', function (){ ... }); }); describe('when foo is a boolean', function (){ it('returns false', function (){ ... }); }); }); describe('when foo is falsy', function (){ it('returns false', function (){ ... }); });
Creates a pending group. All groups and examples nested within a pending group will be marked as pending. This can be used to mark an entire set of tests as pending.
xdescribe('example group', function (){ it('runs some test', function (){ // This example will be marked as pending and will not run ... }); });
The expect keyword creates an assertion. An assertion tests that a value is the value you expect it to be. Here is a breakdown of how expect works:
expect( foo // actual value ).to( be // this is a === matcher... more on this later , 100 // expected value );
Here are some additional example expectations:
expect(1).to(beLt, 2); // passes expect(true).to(beFalse); // fails expect([1,2,3]).to(include, 2); // passes
Here are some examples of expectations that assert actual and expected do not match:
expect(1).toNot(be, 2); // passes expect(function (){ throw new Error('errar!'); }).toNot(throwError); // fails
A before block is a function that sets up a test. A before block is run once for each group, and it can exist within nested groups. before blocks are great for asserting that a test is setup properly before an example runs, and they remove clutter from your tests. Nested groups will run before blocks in the order in which the groups are nested.
describe('when foo is 1', function (){ var foo; before(function (){ // runs first foo = 1; }); it('does something', function (){ ... }); describe(when foo is 2', function (){ before(function (){ // runs second foo++; expect(foo).to(be, 2); }); it('does another thing', function (){ ... }); }); });
after runs after each test. It should be used for cleaning up the previous test and it runs regardless of whether the example passes or fails.
Here is how to use before and after in conjunction to cleanup global variables:
describe('when the current user is bob', function (){ var origUser; before(function (){ origUser = global.currentUser; // save off currentUser global.currentUser = 'bob'; }); after(function (){ global.currentUser = origUser; // reset currentUser after the test runs }); it('does something', function (){ ... }); });
These keywords are 90% of what you need to write tests in BDD-style using foounit. There is a lot more to foounit than just these keywords but you can get by without learning about additional matchers and asynchronous testing if you are just experimenting.
var successCallback; before(function (){ successCallback = mock(function (data){}); $.ajax('http://localhost:5057/data.json', { success: successCallback }); }); it('gets the data', function (){ waitFor(function (){ expect(successCallback).to(haveBeenCalled); }); });
In this example, an xhr request is made to get the JSON data at http://localhost:5057/data.json. We have mocked the success callback and we wait for the response to succeed and call our callback. If the request succeeds then the test will pass, but if the request is unsuccessful then the test will fail. The waitFor keyword waits for the function it is passed to run without failing. If the waitFor block fails, then it is retried until a timeout is reached. If the timeout is reached then the test fails and a kitten dies.
There's more to asynchronous testing than just waitFor but waitFor will generally get you pretty far. Another common use-case is to wait for an expectation to be met, then do something else and wait for another expectation. In this case you can use run to insert a block into foounit's asynchronous execution queue. Here is an example:
it('does a lot of async stuff', function (){ var foo = ''; setTimeout(function (){ foo = 'bar'; }, 200); // Waits for foo to become 'bar' waitFor(function (){ expect(foo).to(be, 'bar'); }); // Runs after the waitFor above run(function (){ setTimeout(function (){ foo = 'baz'; }, 200); }); // Waits for foo to become 'baz' waitFor(function (){ expect(foo).to(be, 'baz'); }); });
foounit can assert that something never happens with the use of waitForTimeout. These kinds of tests are generally frowned upon because they slow down a test suite, but sometimes they are valuable enough to offset the downside of slowing down the test suite.
waitForTimeout will run a function until a timeout is reached. The first time the function passes without error, waitForTimeout fails. Consider this example:
it('doesnt get to 1000 fast enough', function (){ var foo = 0 , inc = function (){ foo++; setTimeout(inc, 200); } setTimeout(inc, 200); waitForTimeout(function (){ expect(foo).to(beGt, 999); }); });
This example will fail because foo will not reach 1000 in the time that it takes for waitForTimeout to timeout.
Asserts that actual === expected.
expect(1).to(be, 1); // passes expect(undefined).to(be, null); // fails
Assert that actual is greater than expected.
expect(5).to(beGt, 4); // passes expect(1).to(beGt, 2); // fails
Assert that actual is === false.
expect(false).to(beFalse); // passes expect(null).to(beFalse); // fails
Assert that actual is falsy.
expect(false).to(beFalsy); // passes expect(null).to(beFalsy); // passes expect("test").to(beFalsy); // fails
Assert that actual is less than expected.
expect(1).to(beLt, 2); // passes expect(5).to(beLt, 4); // fails
Asserts that actual === null.
expect(null).to(beNull); // passes expect(undefined).to(beNull); // fails
Asserts that actual is truthy.
expect(1).to(beTruthy); // passes expect('').to(beTruthy); // fails expect(true).to(beTruthy); // passes
Asserts that actual === undefined.
expect(null).to(beUndefined); // fails expect(undefined).to(beUndefined); // passes
Assert that actual is deeply equal to expected. This is useful for saying that one object is the same as another but they are referencing different objects.
expect({ foo: ['bar'] }).to(equal, { foo: ['bar'] }); // passes expect({ baz: 1 }).to(equal, { baz: 2 }); // fails
Assert that an array has an element that matches type and object equality of expected.
expect([1, 2, 3]).to(include, 2); // passes expect([1, 2, 3]).to(include, 10); // fails
Assert that actual matches a regex.
expect('foo bar baz').to(match, /bar/); // passes expect('foo bar baz').to(match, /qux/); // fails
Asserts that the a function throws an error. The error message can be matched with a regex to assert that the correct error message was thrown.
expect(function (){ throw new Error(); }).to(throwError); // passes expect(function (){ throw new Error('HEY NOW'); }).to(throwError, /Fuuuuuu/); // fails expect(function (){ /** I don't throw **/ }).to(throwError); // fails
TODOC
TODOC