I wanted to make an update to my Bingo Card Generator. Previously I’d added automated tests for JSHint via TravisCI to test for code formatting, but now I wanted to actually test code functionality. I decided to add a simple unit test using QUnit.
I made a lot of mistakes trying to get this to work (probably because I didn’t read the documentation!), so I’ve included all my steps and missteps below in case they are useful to someone else:
I installed qunit
in my development environment:
npm --global install qunit
I created a test
folder in my project:
mkdir test
I added a simple test:
removeEmptyElements = function (arr) {
"use strict";
var newArray = [], i = 0;
for (i = 0; i < arr.length; i += 1) {
if (arr[i]) {
newArray.push(arr[i]);
}
}
return newArray;
}
QUnit.test("RemoveEmptyElements", function(assert) {
"use strict";
var testInput = ",,,A,,B,,,C,";
var testArray = testInput.split(",")
var cleanedArray = removeEmptyElements(testArray);
assert.equal(cleanedArray.length, 3, "Array has 3 elements")
assert.ok(cleanedArray[0] === "A", "First element is A");
assert.ok(cleanedArray[1] === "B", "Second element is B");
assert.ok(cleanedArray[2] === "C", "Third element is C");
});
The test runs in my development environment:
$ qunit
TAP version 13
ok 1 RemoveEmptyElements
1..1
# pass 1
# skip 0
# todo 0
# fail 0
Now, how do I integrate this new test with TravisCI?
First, I added qunit
to devDependencies
in package.json
:
"devDependencies": {
"jshint": "^2.6.0",
"quinit": "^2.6.1"
},
Then I tried adding qunit
to scripts
in package.json
:
"scripts": {
"jshint": "./node_modules/jshint/bin/jshint images.js",
"qunit": "./node_modules/qunit/bin/qunit"
}
I committed the changes to my local git repo and pushed them to GitHub. This triggered TravisCI to run tests, which failed:
npm ERR! code E404
npm ERR! 404 Not Found: quinit@^2.6.1
OK, maybe I’m not the greatest typist. That should be qunit
, not quinit
.
After that fix I received a different message from TravisCI:
> BingoCardGenerator@0.0.2 test /home/travis/build/cherdt/BingoCardGenerator
> echo 'Error: no test specified'
Error: no test specified
TravisCI says it passed, but no tests were run. It turns out the scripts
object in package.json
needs to contain a test
element (I thought I was being more descriptive by calling the elements jshint
and qunit
):
"scripts": {
"test": "./node_modules/jshint/bin/jshint images.js",
"test": "./node_modules/qunit/bin/qunit"
}
This led to a new problem. I had anticipated that two key-value pairs with identical keys (test
) might be an issue. Only the qunit
test ran, no sign of jshint
in the TravisCI output.
This is when I finally decided to read some documentation. If you want to run multiple test engines, you need a script to trigger each of them. See the section Implementing Complex Build Steps in the TravisCI documentation.
I created a bash script to run both jshint
and qunit
:
#!/bin/bash
IS_FAILED=0
echo "Running jshint..."
if jshint images.js simulation.js
then
echo "jshint passed!"
else
echo "jshint failed!"
IS_FAILED=1
fi
echo
echo "Running qunit tests..."
if qunit
then
echo "qunit tests passed"
else
echo "qunit tests failed"
IS_FAILED=1
fi
echo
exit $IS_FAILED
I added that script as the test in packages.json
:
"scripts": {
"test": "sh ./test.sh"
}
Note that TravisCI uses the exit code of this script to determine if you have a passing or failing build. The TravisCI example uses set -ev
in the bash script; the -e
option will cause the script to exit on any error. (If the error occurred in the first test, though, you might not see the results of subsequent tests, so I decided to run the qunit
tests even if jshint
failed.)
That worked — both tests ran and everything passed!
I decided to make one more change. I moved test.sh
to scripts/run-tests.sh
(to match the TravisCI example). I also updated packages.json
accordingly:
"scripts": {
"test": "sh .scripts/run-tests.sh"
}
This time it failed! TravisCI displayed the following error:
sh: 0: Can't open .scripts/run-tests.sh
Of course! That’s a bad path. I updated it to:
"scripts": {
"test": "sh ./scripts/run-tests.sh"
}
Everything works! Now I just need to write more unit tests.