plovr: a Closure build tool

JsUnit Testing

The Closure Testing Framework makes it possible to run JsUnit-style tests. plovr aims to facilitate testing by autogenerating the boilerplate HTML needed to run a JsUnit-style test, as well as by generating a goog.testing.MultiTestRunner so that all of your tests can be run from one page.

This page is intended to provide the minimum amount of information that you need to get started with the Closure Test Framework. For more information, please see Closure: The Definitive Guide.

Writing a Test

The convention for unit testing a file of JavaScript code is to create the test case in a file of the same name, except with a _test.js suffix. For example, to create a unit test for goog.string, which is defined in string.js, the test code should be written in string_test.js. Here is a code sample from such a string_test.js file:
goog.require('goog.string');
goog.require('goog.testing.jsunit');

var testStartsWith = function() {
  assertTrue('Should start with \'\'', goog.string.startsWith('abcd', ''));
  assertTrue('Should start with \'ab\'', goog.string.startsWith('abcd', 'ab'));
};

One might wonder why plovr deviates from the standard of the Closure Library, which is to include both the JavaScript and the HTML needed for a test in one file with a _test.html suffix. plovr does things differently because in the future, plovr will make it possible to run tests in either raw or compiled modes. (There is an internal option in the Closure Compiler named exportTestFunctions that will help make this possible.) Keeping the JavaScript separate from the HTML will make this easier to implement.

Running a Test

Start plovr in server mode and navigate to http://localhost:9810/ as you normally would to see the list of configs that plovr is serving. Under each config, you should see a link to list of tests. Follow that link and you will see the list of the HTML files that plovr has created so you can run your tests. There should be one page for each of your test cases.

To run a test case, simply load the _test.html file that plovr has generated for you. On this page, you can set breakpoints and do all sorts of things that you would normally do to debug your JavaScript code. As you might expect, passing tests are displayed in green while failing tests are displayed in red.

Running All Tests

Often, you want to run not just one test, but all of your tests. To do so, follow the same steps for running an individual test, but instead of clicking on list of tests, click on Test runner. This will bring up a goog.testing.MultiTestRunner that runs all of your tests.

The "list of tests" page and MultiTestRunner page link to one another so that you can easily switch between running one or all of your tests.

Customizing the HTML for a Test Case

plovr generates the HTML for your test case from a Soy template. The default template that plovr uses can be found in test.soy and is named org.plovr.test. You can specify your own template by using the test-template option in your plovr config. Note that your template must be defined in its own Soy file, and must also be named org.plovr.test.

Tip: Use setUpPage() to Avoid Initialization Errors

Often, you will goog.require() a library that will not be loaded until the test is running. That means that you cannot use that library outside of test code. For example, the following will not work:
goog.require('goog.Uri');
goog.require('goog.testing.jsunit');

// This will throw an exception because goog.Uri is not defined yet.
var plovrUri = new goog.Uri('http://plovr.com/');

var testGetScheme = function() {
  assertEquals('http', plovrUri.getScheme());
};

var testGetDomain = function() {
  assertEquals('plovr.com', plovrUri.getDomain());
};
The solution is to use setUpPage(), which is a special function that is run once before any of the tests in the test case are run:
goog.require('goog.Uri');
goog.require('goog.testing.jsunit');

var plovrUri;

var setUpTest = function() {
  plovrUri = new goog.Uri('http://plovr.com/');
};

var testGetScheme = function() {
  assertEquals('http', plovrUri.getScheme());
};

var testGetDomain = function() {
  assertEquals('plovr.com', plovrUri.getDomain());
};
To run the same code before each of the tests in the test case is run, define a function named setUp() with the code you want to run. There are also analogous tearDown() and tearDownPage() functions that you can define to run code after each test, or after all tests, respectively.