Testing javaScript with jsdom and Django in jenkins
Jsdom is an implementation of the DOM in javaScript. Here is how to set it up using python and Django for generating html fixtures, mocha for javaScript testing and sinonjs for stubs and mocks.
Install the packages from npm.
Setting up jsdom
I created a file called browser.js
that sets up jsdom and stubs out a few functions that are global in a real browser. This includes some ‘taming’ of sinons server mock which did not work for me right out of the box.
Running the tests
You can run single test suites this way by just requiring this file when you run the mocha command, for example;
You can create another file to run all of the tests at once. This file will just import all of your mocha test modules. For example, I created a file called run.js
. At the top of this file I imported the browser.js
file which any mocha module is dependent on in this setup. Then I simply run the file in mocha.
Generating html fixtures
Some of my javaScript uses html on the page, for example validating fields in a form. For me, these were in Django templates. I decided I would dynamically generate these templates using a Django management command. I could run this command before I run the mocha tests in jenkins. This way the tests will fail if anyone modifies the templates in such a way as to break the javaScript.
This is my base python class for creating a blank file, outputting a Django template into a string and then writing it into this blank file.
I pass my Django template to this base class to write these files.
Another function in this same python file creates the class and actually calls the function to write the file.
Running a Django management command
In order to generate these fixtures everytime I need them, I need to run a Django management command.
I called this file generate_mocha_fixtures.py
. Now I can build all my mocha fixtures by running this Django management command, ./manage.py generate_mocha_fixtures
.
Including fixtures in tests
Now that Django can generate my test fixture files, I can simply include these files in my tests using a javaScript template engine like lodash. For example, the setup and teardown of my mocha tests may include the following.
Debugging
You can include a debug
option when running mocha and the tests will stop at every point in your javaScript where you include debugger;
statements. Simply run;
Debugging in node is a bit different then in the browser. Maybe you have written a bit of python before and are familiar with pdb. It is a little bit like that.
There is some great documentation on the matter here.
To get started, run the debugger command with some debugger;
breakpoints in your code. Type cont
to go to the next breakpoint or type repl
, then type some variables, their values should be directly outputted back to you.
Using scripts
I like to add my mocha commands as scripts so that they are easy to remember. In my package.json
file they look like this,
Now I can simply run npm run test
to run all of my mocha tests. The timeout option just raises the limit of time a test has to finish before mocha shuts it down and fails with a ‘timeout error’.
Adding to jenkins
In jenkins, add a new build and call it something like “mocha-tests”. Within the build
section, add a build step to execute shell. Here you should add the script commands jenkins will need to run the tests.
The first command will install all the node_modules in package.json
using the --production
flag to indicate that scripts listed under devDependencies
in package.json
should not be installed. I’ve added two new script command to my package.json
.
Running npm run build:test:jenkins
will run my Django management command and generate my html fixtures from Django templates. Following that, I will compile my test files from webpack (this may be an unnecessary step for you).
Running npm run test:jenkins
will write the mocha test results to a test-reports.xml
file in jenkins. Jenkins will use this to properly inform you of failed tests.
Below the build section is a Post-build Actions
. I add an action to publish a JUnit test result report. In the test report XMLs, add test-reports.xml
.
Finishing up
So is it worth using jsdom for javaScript testing? Among the pros are that it is quite fast. It is easy to run hundreds of tests very often. Also, debugging in node is a nice change of pace from working in the browser.
However, it is worth remembering that jsdom is not a real browser. If your tests rely too much on the DOM, you may be opening yourself up to bugs you can’t catch. For me, this is a good challenge to do much less DOM manipulation.