visionmedia/mocha — pull request #278 by jeffbski (2012-02-23 23:11:07+00:00)
Title: Allow async tests to optionally pass a verify fn to done() to improve error reporting

## Summary

Allow async tests to optionally pass done() a verify fn
(as alternative to just passing an Error object). This verify
function is executed and if any exceptions occur they are
caught and reported rather than only getting a generic timeout
error. Without this fix we have no output about what assert
failed nor do we have any of the details of the failure.
This is an alternate way to use done(), it can also just
receive an Error object as before.

## Details of problem

If an assertion exception is thrown in the callback
of an async test, currently mocha only reports a timeout
rather than which assertion failed (and the details of the
failure).

For example with the following code, mocha will not report
the assert failure but the error will just be a timeout.
The details of which assert failed or what throw an error
is not known.

```javascript
test('foo', function (done) {
myAsyncFn(function (err, result) {
assert.ok(true);
assert.equal(result, 'bar'); // mocha does not report this
done();
});
});
```

One can work around this by wrapping your test assertions in a
try/catch and then calling done with the err, but this is
cumbersome and redundant for such a common pattern.

```javascript
test('foo', function (done) {
myAsyncFn(function (err, result) {
try { // boilerplate to be able to get the assert failures
assert.ok(true);
assert.equal(result, 'bar');
done();
} catch (x) {
done(x);
}
});
});
```

## Solution - allow done() to optionally take a verify function

This commit allows done() to optionally be passed a verify function
which is executed and if any exceptions or assertions are
thrown then done will be automatically called with the error.
This cleans up the pattern and eliminates most of the
boilerplate, and provides full details to mocha reporter.
If done is passed an Error object it works as it did before,
so this is simply an alternate way of using done().

```javascript
test('foo', function (done) {
myAsyncFn(function (err, result) {
done(function () { // verify fn
assert.ok(true);
assert.equal(result, 'bar'); // mocha now reports the assert failure
});
});
});
```