Why use JsTestDriver (JSTD), anyway?

For a couple of years JSTD was the best option in town for running JS unit tests. The best thing about it: it is just a jar file, so it runs everywhere - all the more modern alternatives require node.js, which is not always feasible. So JSTD remains my Plan B in those cases. And it is very nifty, it does pretty much everything all the shinier hipster tools do.

Why give up on JsTestDriver?

JSTD is not dead, but it may as well be so. It was made by Google, and it’s maintained by a single guy who apparently doesn’t have a Windows machine. As a result, the code coverage plugin hasn’t worked for Windows for at least two years. And we all know what happens at Google when only one guy is assigned part time on a project, right? Besides, it’s much slower than its node competitors, and it often time outs when you have too many tests. In other words, it is getting old and creaky.

Folder structure

The folder structure I use for JSTD is not dissimilar to that of any unit test framework:

+--/bin              # jar files and executables
+--/coverage         # svn:ignore, for coverage reports
+--/fixtures         # static html and json files
+--/lib              # javascript libraries which are not part of the app
+--/mocks           # mocking application's classes
+--/tests           # the actual tests
jstd.conf           # configuration file
jstd-runner.sh      # runner

The bin folder may or may not be under subversion, this depends on the team’s philosophy (many object to the idea in principle, but it’s only a couple of rarely changing jars).

I use JSTD with Jasmine, partly because of the useful jasmine-jquery plugin, which, among other things, allow fixtures to be served easily. I also like sinon for extra mocking power. Also, decoupling the runner from the test library allows me to switch from JSTD to, say, Karma easily.

The JSTD configuration file, jstd.conf

The config file jstd.cong is written in YAML, which is much nicer than XML. Nothing exciting here - load is for the under test files, test is for test libraries and the tests itself, and serve is for fixtures. Note that the coverage plugin is commented out because broken.

The JSTD runner script

Normally one runs two instances of JSTD in two terminal tabs - one as a server, and one as a test runner against the server. To make that easier, I wrapped the JSTD command (java -jar … etc) with a Bash script, js-test-driver.sh (sorry Windows users) which allows everything to be controlled from one place. And that includes running the tests both against a “physical” browser, and a headless one (i.e., PhantomJS)

After making the script executable with chmod 775 jstd-runner.sh, you run in one of the following ways

./jstd-runner.sh local start  # will start the server then quit
                              # (no need to start another tab)
./jstd-runner.sh local run    # will run the tests
./jstd-runner.sh local stop   # will stop the server when finished for
                              # the day
./jstd-runner.sh headless     # will start the server, run the tests with
                              # PhantomJS, and stop the server

The script is improved a little bit with every project - the next improvement would be to run start automatically if there is no server running and you type run, and also to allow to pass extra arguments in the command to the jar.

Code to be tested

The source code is a single JS file with a minimalistic object, example.js.

HTML and JSON Fixtures

In the fixtures directory there is an HTML fixture, example.html and a JSON one, example.json. They can be used to mimic server response, different config files, and HTML fragments. Again, nothing too exciting

The Jasmine test file

example-test.js is where the fun happens - this has the Jasmine tests. I have included a vanilla test (“version”), a test for HTML (“removeHeader”) and JSON (“loadData”) fixtures, the former using the jasmine-jquery plugin, and the simplest usage of a sinon spy and the jasmine-sinon plugin,


So the boilerplate is on github, all documented in case I ever need it again, but so far I am much happier with karma.