- 3.1 xUnit Test Frameworks
- 3.2 In-Browser Test Frameworks
- 3.3 Headless Testing Frameworks
- 3.4 One Test Runner to Rule Them All
- 3.5 Summary
3.2 In-Browser Test Frameworks
The original JavaScript port of the JUnit framework was JsUnit, first released in 2001. Not surprisingly, it has in many ways set the standard for a lot of testing frameworks following it. JsUnit runs tests in a browser: The test runner prompts for the URL to a test file to execute. The test file may be an HTML test suite which links to several test cases to execute. The tests are then run in sandboxed frames, and a green progress bar is displayed while tests are running. Obviously, the bar turns red whenever a test fails. JsUnit still sees the occasional update, but it has not been significantly updated for a long time, and it's starting to lag behind. JsUnit has served many developers well, including myself, but there are more mature and up-to-date alternatives available today.
Common for the in-browser testing frameworks is how they require an HTML fixture file to load the files to test, the testing library (usually a JavaScript and a CSS file), as well as the tests to run. Usually, the fixture can be simply copy-pasted for each new test case. The HTML fixture also serves the purpose of hosting dummy markup needed for the unit tests. If tests don't require such markup, we can lessen the burden of keeping a separate HTML file for each test case by writing a script that scans the URL for parameters naming library and test files to load, and then load them dynamically. This way we can run several test cases from the same HTML fixture simply by modifying the URL query string. The fixture could of course also be generated by a server-side application, but be careful down this route. I advise you to keep things simple—complicated test runners greatly decreases the likelihood of developers running tests.
3.2.1 YUI Test
Most of the major JavaScript libraries available today have their own unit testing framework. YUI from Yahoo! is no exception. YUI Test 3 can be safely used to test arbitrary JavaScript code (i.e., it has no obtrusive dependencies). YUI Test is, in its own words, "not a direct port from any specific xUnit framework," but it "does derive some characteristics from nUnit and JUnit," with nUnit being the .NET interpretation of the xUnit family of frameworks, written in C#. YUI Test is a mature testing framework with a rich feature set. It supports a rich set of assertions, test suites, a mocking library (as of YUI 3), and asynchronous tests.
3.2.1.1 Setup
Setup is very easy thanks to YUI's loader utility. To get quickly started, we can link directly to the YUI seed file on the YUI server, and use YUI.use to fetch the necessary dependencies. We will revisit the strftime example from Chapter 1, Automated Testing, in order to compare YUI Test to the testCase function introduced in that chapter. Listing 3.1 shows the HTML fixture file, which can be saved in, e.g., strftime_yui_test.html.
Listing 3.1. YUI Test HTML fixture file
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Testing Date.prototype.strftime with YUI</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> </head> <body class="yui-skin-sam"> <div id="yui-main"><div id="testReport"></div></div> <script type="text/javascript" src="https://yui.yahooapis.com/3.0.0/build/yui/yui-min.js"> </script> <script type="text/javascript" src="strftime.js"> </script> <script type="text/javascript" src="strftime_test.js"> </script> </body> </html>
The strftime.js file contains the Date.prototype.strftime implementation presented in Listing 1.2 in Chapter 1, Automated Testing. Listing 3.2 shows the test script, save it in strftime_test.js.
Listing 3.2. Date.prototype.strftime YUI test case
YUI({ combine: true, timeout: 10000 }).use("node", "console", "test", function (Y) { var assert = Y.Assert; var strftimeTestCase = new Y.Test.Case({ // test case name - if not provided, one is generated name: "Date.prototype.strftime Tests", setUp: function () { this.date = new Date(2009, 9, 2, 22, 14, 45); }, tearDown: function () { delete this.date; }, "test %Y should return full year": function () { var year = Date.formats.Y(this.date); assert.isNumber(year); assert.areEqual(2009, year); }, "test %m should return month": function () { var month = Date.formats.m(this.date); assert.isString(month); assert.areEqual("10", month); }, "test %d should return date": function () { assert.areEqual("02", Date.formats.d(this.date)); }, "test %y should return year as two digits": function () { assert.areEqual("09", Date.formats.y(this.date)); }, "test %F should act as %Y-%m-%d": function () { assert.areEqual("2009-10-02", this.date.strftime("%F")); } }); //create the console var r = new Y.Console({ newestOnTop : false, style: 'block' }); r.render("#testReport"); Y.Test.Runner.add(strftimeTestCase); Y.Test.Runner.run(); });
When using YUI Test for production code, the required sources should be downloaded locally. Although the loader is a convenient way to get started, relying on an internet connection to run tests is bad practice because it means we cannot run tests while offline.
3.2.1.2 Running Tests
Running tests with YUI Test is as simple as loading up the HTML fixture in a browser (preferably several browsers) and watching the output in the console, as seen in Figure 3.1.
Figure 3.1 Running tests with YUI Test.
3.2.2 Other In-Browser Testing Frameworks
When choosing an in-browser testing framework, options are vast. YUI Test is among the most popular choices along with JsUnit and QUnit. As mentioned, JsUnit is long overdue for an upgrade, and I suggest you not start new projects with it at this point. QUnit is the testing framework developed and used by the jQuery team. Like YUI Test it is an in-browser test framework, but follows the traditional xUnit design less rigidly. The Dojo and Prototype.js libraries both have their test frameworks as well.
One might get the impression that there are almost as many testing frameworks out there as there are developers unit testing their scripts—there is no defacto standard way to test JavaScript. In fact, this is true for most programming tasks that are not directly related to browser scripting, because JavaScript has no general purpose standard library. CommonJS is an initiative to rectify this situation, originally motivated to standardize server-side JavaScript. CommonJS also includes a unit testing spec, which we will look into when testing a Node.js application in Chapter 14, Server-Side JavaScript with Node.js.