An app for demonstrating unit testing Nodejs using Tape.
Because testing's fun!
Using Nodejs and Tape. Linting with semi-standard.
First clone the repo and run npm install
.
-
Install tape:
npm install --save-dev tape
/npm i -D tape
-
Create a file:
test/my_first_test.js
-
Open the file and include tape:
var test = require('tape');
-
Write your first test (just to check everything is working):
test('Check tape is working with a simple passing test', function (t) {
t.pass('a message to print out on success');
t.end();
});
- Run your test
node test/my_first_test.js
and you should see:
TAP version 13
# Check tape is working with a simple passing test
ok 1 a message to print out on success
1..1
# tests 1
# pass 1
# ok
- Compare simple values (numbers, strings and booleans):
test('Comparing simple values (numbers, strings and booleans)', function (t) {
t.plan(3); // Assert how many assertions in test
t.equal(1, 1, 'Compare simple values');
t.equal('abc', 'abc'); // Messages are optional
t.equal(true, true);
t.end();
});
- Compare arrays and objects:
test('Comparing arrays and objects', function (t) {
t.deepEqual([1, 2, 3], [1, 2, 3]);
t.deepEqual({ a: 1, b: 2 }, { a: 1, b: 2 });
t.end();
});
- You can (and should) still use equal if you're comparing the same object:
test('Comparing the same array/object you can still use equal', function (t) {
var arr = [1, 2, 3];
var obj = { a: 1, b: 2 };
var identity = function (x) { return x; };
t.equal(arr, identity(arr));
t.equal(obj, identity(obj));
t.end();
});
- Assert truthy / falsy values:
test('Check values are truthy', function (t) {
t.ok(true);
t.ok(1);
t.ok('string');
t.ok({});
t.ok([]);
t.end();
});
test('Check values are falsy', function (t) {
t.notOk(false);
t.notOk(0);
t.notOk('');
t.end();
});
- Declare a callback function to test:
function asyncDouble (n, cb) {
setTimeout(function () {
if (typeof n !== 'number') {
cb(new TypeError('Expected number'));
} else {
cb(null, n * 2);
}
}, 10);
}
- Test success:
test('Handle callbacks: success', function (t) {
t.plan(2); // With t.plan(), no need for t.end()
asyncDouble(10, function (error, result) {
t.error(error);
t.equal(result, 20);
});
});
- Test failure:
test('Handle callbacks: error', function (t) {
asyncDouble('10', function (error, result) {
t.ok(error instanceof TypeError);
t.end();
});
});
- Declare an error throwing function to test:
function checkWin (score) {
if (score < 20) {
throw new Error('Too low');
} else {
return 'You win!';
}
}
- Handle success:
test('Handle success', function (t) {
t.equals(checkWin(20), 'You win!');
t.end();
});
- Handle errors:
test('Handle errors', function (t) {
t.throws(function () { return checkWin(19); });
t.end();
});
-
If you only want to run one test use
test.only(...)
-
If you want to skip a test use
test.skip(...)
-
If you want to add a comment (or log something) use
test.comment('your comment')
-
Create a file
src/my_functions.js
-
Move
asyncDouble
andcheckWin
frommy_first_test.js
tosrc/my_functions.js
-
Then export the functions:
module.exports = {
asyncDouble,
checkWin
};
- At the top of the file add the following:
var myFunctions = require('../src/my_functions');
var asyncDouble = myFunctions.asyncDouble;
var checkWin = myFunctions.checkWin;
- Or for a more succinct syntax, use destructuring:
var { asyncDouble, checkWin } = require('../src/my_functions');
- Add a test script to
package.json
to test all files in the test directory:
...
"scripts": {
"test": "tape 'test/**/*.js'"
}
...
-
Run your tests with
npm test
-
Add a reporter for nicer output:
- install faucet:
npm i D faucet
- update the test script:
tape 'test/**/*.js' | faucet
- install faucet:
-
Add a watch script to run test on change of file (requires
nodemon
to be installed globally):
...
"scripts": {
"test": "tape 'test/**/*.js' | faucet",
"watch": "nodemon -q -x 'npm test'"
}
...
- Run your watch command:
npm run watch
and then change your test files to check it re-runs on file save.
-
See the example server at
src/server.js
which serves static files from the/static
directory as/public
. -
What makes this code difficult to test?
-
Which bits of the code are particularly hard to test and why?
-
How could the code be refactored to make it more testable?
-
Tape repo: https://github.com/substack/tape
-
Articles:
-
AVA (Tape-inspired ES6+ testing framework)- https://github.com/avajs/ava