On the last couple of projects I’ve worked on, the need for JavaScript testing has grown as client behaviour has increased. Recent improvements in JavaScript components and libraries have made it easier to move more display behaviour to the client and create richer and more responsive UIs. In order to write tests to cover this code I evaluated the QUnit and Jasmine test frameworks. Jasmine better matched the BDD way I wanted to structure my tests (particularly nesting tests into specs and sub-specs).
We currently run all our unit and integration tests as part of our TeamCity build process, but how do we integrate JavaScript tests, which ideally need to run in an instance of one or more target browsers? The solution is reasonably straightforward but with one limitation (which I hope is temporary).
Enter JsTestDriver. This awesome project allows us to load and execute JavaScript files into a browser that is ‘captured’ by the server process. Full details of how this is done can be found at the project site. Basically for a CI build this captured browser and server process exists on a remote server. The limitation is that this needs to be an interactive session and currently I’ve only managed to get this working under my session, which I leave active and which causes many failed builds when the servers ‘accidently’ restart. A problem for another day.
Once this remote server is configured, it’s really just a matter of setting up the yaml configuration file (jsTestDriver.conf here):
server: http://server-name:9876 load: - jasmine/jasmine.js - JasmineAdapter.js - fileundertest.js - fileundertest.specs.js
And executing something like the following script:
if not exist Out\JsTestDriverResults mkdir Out\JsTestDriverResults java -jar JsTestDriver-1.3.2.jar --config jsTestDriver.conf --testOutput Out\JsTestDriverResults --reset --verbose --tests all
The server value is the endpoint that is configured on the remote server. The load values are the javascript files that will be loaded and executed. jasmine.js is the Jasmine framework file and JasmineAdapter.js is a great JsTestDriver adapter to support Jasmine. Once these are loaded, any Jasmine tests in subsequent files will be executed.
In the example above, fileundertest.js contains the code we want to test and fileundertest.specs.js contains the Jasmine tests. Obviously you can add as many files as required and even include dependencies such as jQuery, though that starts to get a little ropey. There is a Jasmine plugin that supports jQuery and DOM manipulation for the interested reader.
The results are output to Out\JsTestDriverResults in an JUnit compatible format which can be read by TeamCity when this script is executed as part of a build. These results then show up in TeamCity and any failing tests will be easy to spot.
Thanks for this post Ben - I've currently finalizing our jasmine test suite into the ci server. We have a .NET stack and are working on removing some of our ruby tools (due to slowness on windows)
ReplyDeleteThis post will help me flush out some of the final pieces I need to get everything up and running.