Continuous Integration for QUnit tests

Posted: January 09, 2009

In my last blog entry I wrote about how to unit test Javascript using QUnit. I this entry I'll explain how to run those tests on your continuous integration server using JUnit and HTMLUnit.

Technologies

In this example I'll be using the following technologies:

  • QUnit - I used the current trunk version as of 1/9/2008
  • JUnit
  • HTMLUnit 2.4

Test Runner

To automate my QUnit tests I wrote a simple JUnit class that scans a directory for .html files and runs them using HTMLUnit.

public class QUnitTest extends TestCase {

    private List<String> failures;

    public void testAll() throws Exception {
        failures = new ArrayList<String>();

        File qunitDir = new File("src/test/qunit");
        if (!qunitDir.exists() || !qunitDir.isDirectory()) {
            fail("Test dir does not exist or is not a directory: " + qunitDir);
        }

        for (File file : qunitDir.listFiles()) {
            if (file.getName().endsWith(".html")) {
                runTest(file);
            }
        }

        if (failures.size() > 0) {
            StringBuffer sb = new StringBuffer();
            for (String failMsg : failures) {
                if (sb.length() > 0)
                    sb.append("\n");
                sb.append(failMsg);
            }

            fail("Tests failed: " + sb.toString());
        }
    }

    private void runTest(File file) throws Exception {
        WebClient client = new WebClient();
        client.setJavaScriptEnabled(true);
        HtmlPage page = client.getPage("file:///" + file.getAbsolutePath());
        HtmlElement element = page.getHtmlElementById("testresult");

        if (element.getTextContent().indexOf("0 tests of 0") != -1)
            failures.add(file.getName() + " - No tests were run - " + 
              element.getTextContent());
        else if (element.getTextContent().indexOf("0 tests of ") == -1)
            failures.add(file.getName() + " - " + element.getTextContent());
    }

}

Assumptions:

This class assumes:

  • Your tests are all in a single directory: src/test/qunit
  • You place your testrunner.js file immediately before the terminating body tag. If you don't do this, HTMLUnit will run the test harness before the page loads and your tests have initialized.

Try it out

Try putting this class into your project and automatically run your JS tests during your builds!