1 | Nodeunit
|
2 | ========
|
3 |
|
4 | [![Build Status](https://travis-ci.org/caolan/nodeunit.svg?branch=master)](https://travis-ci.org/caolan/nodeunit)
|
5 |
|
6 | Simple syntax, powerful tools. Nodeunit provides easy async unit testing for
|
7 | node.js and the browser.
|
8 |
|
9 |
|
10 | DEPRECATED PROJECT
|
11 | -----
|
12 |
|
13 | The project is very stale. We've kept it working on new versions of node, and sometimes merged small PRs that help teams relying on nodeunit.
|
14 |
|
15 | Nodeunit was the arguably first testing framework developed for node. It was very useful at the time, but there's an overwhelming number
|
16 | of other worthwhile testing solutions out there that are actively maintained. tap, ava, tape, mocha, jasmine, jest, ... the list goes on and on.
|
17 |
|
18 | If Nodeunit were truly bringing some different philosophy to the testing scene I'd say yes effort should be made to shore up it's development,
|
19 | but given how many other great options there are out there, a benefit of letting it atrophy is it's one less choice people have to make when
|
20 | choosing a testing solution. *You are strongly encouraged to check out other more modern testing options.*
|
21 |
|
22 |
|
23 | Features
|
24 | --------
|
25 |
|
26 | * Simple to use
|
27 | * Just export the tests from a module
|
28 | * Works with node.js and in the browser
|
29 | * Helps you avoid common pitfalls when testing asynchronous code
|
30 | * Easy to add test cases with setUp and tearDown functions if you wish
|
31 | * Flexible reporters for custom output, built-in support for HTML and jUnit XML
|
32 | * Allows the use of mocks and stubs
|
33 |
|
34 | Contributors
|
35 | ------------
|
36 |
|
37 | * [alexgorbatchev](https://github.com/alexgorbatchev)
|
38 | * [alexkwolfe](https://github.com/alexkwolfe)
|
39 | * [azatoth](https://github.com/azatoth)
|
40 | * [kadirpekel](https://github.com/kadirpekel)
|
41 | * [lambdalisue](https://github.com/lambdalisue)
|
42 | * [luebken](https://github.com/luebken)
|
43 | * [orlandov](https://github.com/orlandov)
|
44 | * [Sannis](https://github.com/Sannis)
|
45 | * [sstephenson](https://github.com/sstephenson)
|
46 | * [thegreatape](https://github.com/thegreatape)
|
47 | * [mmalecki](https://github.com/mmalecki)
|
48 | * and thanks to [cjohansen](https://github.com/cjohansen) for input and advice
|
49 | on implementing setUp and tearDown functions. See
|
50 | [cjohansen's fork](https://github.com/cjohansen/nodeunit).
|
51 |
|
52 | Also, check out gerad's [nodeunit-dsl](https://github.com/gerad/nodeunit-dsl)
|
53 | project, which implements a 'pretty dsl on top of nodeunit'.
|
54 |
|
55 | More contributor information can be found in the
|
56 | [CONTRIBUTORS.md](https://github.com/caolan/nodeunit/blob/master/CONTRIBUTORS.md)
|
57 | file.
|
58 |
|
59 | Usage
|
60 | -----
|
61 |
|
62 | Here is an example unit test module:
|
63 |
|
64 | exports.testSomething = function(test) {
|
65 | test.expect(1);
|
66 | test.ok(true, "this assertion should pass");
|
67 | test.done();
|
68 | };
|
69 |
|
70 | exports.testSomethingElse = function(test) {
|
71 | test.ok(false, "this assertion should fail");
|
72 | test.done();
|
73 | };
|
74 |
|
75 | When run using the included test runner, this will output the following:
|
76 |
|
77 | <img src="https://github.com/caolan/nodeunit/raw/master/img/example_fail.png" />
|
78 |
|
79 | Installation
|
80 | ------------
|
81 |
|
82 | There are two options for installing nodeunit:
|
83 |
|
84 | 1. Clone / download nodeunit from [github](https://github.com/caolan/nodeunit),
|
85 | then:
|
86 |
|
87 | make && sudo make install
|
88 |
|
89 | 2. Install via npm:
|
90 |
|
91 | npm install nodeunit -g
|
92 |
|
93 | API Documentation
|
94 | -----------------
|
95 |
|
96 | Nodeunit uses the functions available in the node.js
|
97 | [assert module](http://nodejs.org/docs/v0.4.2/api/assert.html):
|
98 |
|
99 | * __ok(value, [message])__ - Tests if value is a true value.
|
100 | * __equal(actual, expected, [message])__ - Tests shallow, coercive equality
|
101 | with the equal comparison operator ( == ).
|
102 | * __notEqual(actual, expected, [message])__ - Tests shallow, coercive
|
103 | non-equality with the not equal comparison operator ( != ).
|
104 | * __deepEqual(actual, expected, [message])__ - Tests for deep equality.
|
105 | * __notDeepEqual(actual, expected, [message])__ - Tests for any deep
|
106 | inequality.
|
107 | * __strictEqual(actual, expected, [message])__ - Tests strict equality, as
|
108 | determined by the strict equality operator ( === )
|
109 | * __notStrictEqual(actual, expected, [message])__ - Tests strict non-equality,
|
110 | as determined by the strict not equal operator ( !== )
|
111 | * __throws(block, [error], [message])__ - Expects block to throw an error.
|
112 | * __doesNotThrow(block, [error], [message])__ - Expects block not to throw an
|
113 | error.
|
114 | * __ifError(value)__ - Tests if value is not a false value, throws if it is a
|
115 | true value. Useful when testing the first argument, error in callbacks.
|
116 |
|
117 | Nodeunit also provides the following functions within tests:
|
118 |
|
119 | * __expect(amount)__ - Specify how many assertions are expected to run within a
|
120 | test. Very useful for ensuring that all your callbacks and assertions are
|
121 | run.
|
122 | * __done()__ - Finish the current test function, and move on to the next. ALL
|
123 | tests should call this!
|
124 |
|
125 | Nodeunit aims to be simple and easy to learn. This is achieved through using
|
126 | existing structures (such as node.js modules) to maximum effect, and reducing
|
127 | the API where possible, to make it easier to digest.
|
128 |
|
129 | Tests are simply exported from a module, but they are still run in the order
|
130 | they are defined.
|
131 |
|
132 | __Note:__ Users of old nodeunit versions may remember using `ok`, `equals` and
|
133 | `same` in the style of qunit, instead of the assert functions above. These
|
134 | functions still exist for backwards compatibility, and are simply aliases to
|
135 | their assert module counterparts.
|
136 |
|
137 |
|
138 | Asynchronous Testing
|
139 | --------------------
|
140 |
|
141 | When testing asynchronous code, there are a number of sharp edges to watch out
|
142 | for. Thankfully, nodeunit is designed to help you avoid as many of these
|
143 | pitfalls as possible. For the most part, testing asynchronous code in nodeunit
|
144 | _just works_.
|
145 |
|
146 |
|
147 | ### Tests run in series
|
148 |
|
149 | While running tests in parallel seems like a good idea for speeding up your
|
150 | test suite, in practice I've found it means writing much more complicated
|
151 | tests. Because of node's module cache, running tests in parallel means mocking
|
152 | and stubbing is pretty much impossible. One of the nicest things about testing
|
153 | in javascript is the ease of doing stubs:
|
154 |
|
155 | var _readFile = fs.readFile;
|
156 | fs.readFile = function(path, callback) {
|
157 | // it's a stub!
|
158 | };
|
159 | // test function that uses fs.readFile
|
160 |
|
161 | // we're done
|
162 | fs.readFile = _readFile;
|
163 |
|
164 | You cannot do this when running tests in parallel. In order to keep testing as
|
165 | simple as possible, nodeunit avoids it. Thankfully, most unit-test suites run
|
166 | fast anyway.
|
167 |
|
168 |
|
169 | ### Explicit ending of tests
|
170 |
|
171 | When testing async code it's important that tests end at the correct point, not
|
172 | just after a given number of assertions. Otherwise your tests can run short,
|
173 | ending before all assertions have completed. It's important to detect too
|
174 | many assertions as well as too few. Combining explicit ending of tests with
|
175 | an expected number of assertions helps to avoid false test passes, so be sure
|
176 | to use the `test.expect()` method at the start of your test functions, and
|
177 | `test.done()` when finished.
|
178 |
|
179 |
|
180 | Groups, setUp and tearDown
|
181 | --------------------------
|
182 |
|
183 | Nodeunit allows the nesting of test functions:
|
184 |
|
185 | exports.test1 = function (test) {
|
186 | ...
|
187 | }
|
188 |
|
189 | exports.group = {
|
190 | test2: function (test) {
|
191 | ...
|
192 | },
|
193 | test3: function (test) {
|
194 | ...
|
195 | }
|
196 | }
|
197 |
|
198 | This would be run as:
|
199 |
|
200 | test1
|
201 | group - test2
|
202 | group - test3
|
203 |
|
204 | Using these groups, Nodeunit allows you to define a `setUp` function, which is
|
205 | run before each test, and a `tearDown` function, which is run after each test
|
206 | calls `test.done()`:
|
207 |
|
208 | module.exports = {
|
209 | setUp: function (callback) {
|
210 | this.foo = 'bar';
|
211 | callback();
|
212 | },
|
213 | tearDown: function (callback) {
|
214 | // clean up
|
215 | callback();
|
216 | },
|
217 | test1: function (test) {
|
218 | test.equals(this.foo, 'bar');
|
219 | test.done();
|
220 | }
|
221 | };
|
222 |
|
223 | In this way, it's possible to have multiple groups of tests in a module, each
|
224 | group with its own setUp and tearDown functions.
|
225 |
|
226 |
|
227 | Running Tests
|
228 | -------------
|
229 |
|
230 | Nodeunit comes with a basic command-line test runner, which can be installed
|
231 | using `sudo make install`. Example usage:
|
232 |
|
233 | nodeunit testmodule1.js testfolder [...]
|
234 |
|
235 | If no entry file specified, `test` defaults.
|
236 |
|
237 | The default test reporter uses color output, because I think that's more fun :) I
|
238 | intend to add a no-color option in future. To give you a feeling of the fun you'll
|
239 | be having writing tests, lets fix the example at the start of the README:
|
240 |
|
241 | <img src="https://github.com/caolan/nodeunit/raw/master/img/example_pass.png" />
|
242 |
|
243 | Ahhh, Doesn't that feel better?
|
244 |
|
245 | When using the included test runner, it will exit using the failed number of
|
246 | assertions as the exit code. This means it exits with 0 when all tests pass.
|
247 |
|
248 |
|
249 | ### Command-line Options
|
250 |
|
251 | * __--reporter FILE__ - you can set the test reporter to a custom module or
|
252 | on of the modules in nodeunit/lib/reporters, when omitted, the default test runner
|
253 | is used.
|
254 | * __--list-reporters__ - list available built-in reporters.
|
255 | * __--config FILE__ - load config options from a JSON file, allows
|
256 | the customisation of color schemes for the default test reporter etc. See
|
257 | bin/nodeunit.json for current available options.
|
258 | * __-t testName__ - run specific test only.
|
259 | * __-f fullTestName__ - run specific test only. fullTestName is built so: "outerGroup - .. - innerGroup - testName".
|
260 | * __--version__ or __-v__ - report nodeunit version
|
261 | * __--help__ - show nodeunit help
|
262 |
|
263 |
|
264 | Running tests in the browser
|
265 | ----------------------------
|
266 |
|
267 | Nodeunit tests can also be run inside the browser. For example usage, see
|
268 | the examples/browser folder. The basic syntax is as follows:
|
269 |
|
270 | __test.html__
|
271 |
|
272 | <html>
|
273 | <head>
|
274 | <title>Example Test Suite</title>
|
275 | <link rel="stylesheet" href="nodeunit.css" type="text/css" />
|
276 | <script src="nodeunit.js"></script>
|
277 | <script src="suite1.js"></script>
|
278 | <script src="suite2.js"></script>
|
279 | </head>
|
280 | <body>
|
281 | <h1 id="nodeunit-header">Example Test Suite</h1>
|
282 | <script>
|
283 | nodeunit.run({
|
284 | 'Suite One': suite1,
|
285 | 'Suite Two': suite2
|
286 | });
|
287 | </script>
|
288 | </body>
|
289 | </html>
|
290 |
|
291 | Here, `suite1` and `suite2` are just object literals containing test functions
|
292 | or groups, as would be returned if you did `require('test-suite')` in node.js:
|
293 |
|
294 | __suite1.js__
|
295 |
|
296 | this.suite1 = {
|
297 | 'example test': function (test) {
|
298 | test.ok(true, 'everything is ok');
|
299 | test.done();
|
300 | }
|
301 | };
|
302 |
|
303 | If you wish to use a commonjs format for your test suites (using exports), it is
|
304 | up to you to define the commonjs tools for the browser. There are a number of
|
305 | alternatives and it's important it fits with your existing code, which is
|
306 | why nodeunit does not currently provide this out of the box.
|
307 |
|
308 | In the example above, the tests will run when the page is loaded.
|
309 |
|
310 | The browser-version of nodeunit.js is created in dist/browser when you do, `make
|
311 | browser`. You'll need [UglifyJS](https://github.com/mishoo/UglifyJS) installed in
|
312 | order for it to automatically create nodeunit.min.js.
|
313 |
|
314 |
|
315 | Adding nodeunit to Your Projects
|
316 | --------------------------------
|
317 |
|
318 | If you don't want people to have to install the nodeunit command-line tool,
|
319 | you'll want to create a script that runs the tests for your project with the
|
320 | correct require paths set up. Here's an example test script, that assumes you
|
321 | have nodeunit in a suitably located node_modules directory.
|
322 |
|
323 | #!/usr/bin/env node
|
324 | var reporter = require('nodeunit').reporters.default;
|
325 | reporter.run(['test']);
|
326 |
|
327 | If you're using git, you might find it useful to include nodeunit as a
|
328 | submodule. Using submodules makes it easy for developers to download nodeunit
|
329 | and run your test suite, without cluttering up your repository with
|
330 | the source code. To add nodeunit as a git submodule do the following:
|
331 |
|
332 | git submodule add git://github.com/caolan/nodeunit.git node_modules/nodeunit
|
333 |
|
334 | This will add nodeunit to the node_modules folder of your project. Now, when
|
335 | cloning the repository, nodeunit can be downloaded by doing the following:
|
336 |
|
337 | git submodule init
|
338 | git submodule update
|
339 |
|
340 | Let's update the test script above with a helpful hint on how to get nodeunit,
|
341 | if it's missing:
|
342 |
|
343 | #!/usr/bin/env node
|
344 | try {
|
345 | var reporter = require('nodeunit').reporters.default;
|
346 | }
|
347 | catch(e) {
|
348 | console.log("Cannot find nodeunit module.");
|
349 | console.log("You can download submodules for this project by doing:");
|
350 | console.log("");
|
351 | console.log(" git submodule init");
|
352 | console.log(" git submodule update");
|
353 | console.log("");
|
354 | process.exit();
|
355 | }
|
356 |
|
357 | process.chdir(__dirname);
|
358 | reporter.run(['test']);
|
359 |
|
360 | Now if someone attempts to run your test suite without nodeunit installed they
|
361 | will be prompted to download the submodules for your project.
|
362 |
|
363 |
|
364 | Built-in Test Reporters
|
365 | -----------------------
|
366 |
|
367 | * __default__ - The standard reporter seen in the nodeunit screenshots
|
368 | * __minimal__ - Pretty, minimal output, shows errors and progress only
|
369 | * __html__ - Outputs a HTML report to stdout
|
370 | * __junit__ - Creates jUnit compatible XML reports, which can be used with
|
371 | continuous integration tools such as [Hudson](http://hudson-ci.org/).
|
372 | * __machineout__ - Simple reporter for machine analysis. There is
|
373 | [nodeunit.vim](https://github.com/lambdalisue/nodeunit.vim) which is useful for TDD on VIM.
|
374 |
|
375 |
|
376 | Writing a Test Reporter
|
377 | ---------------------
|
378 |
|
379 | Nodeunit exports runTest(fn, options), runModule(mod, options) and
|
380 | runFiles(paths, options). You'll most likely want to run test suites from
|
381 | files, which can be done using the latter function. The _options_ argument can
|
382 | contain callbacks which run during testing. Nodeunit provides the following
|
383 | callbacks:
|
384 |
|
385 | * __moduleStart(name)__ - called before a module is tested
|
386 | * __moduleDone(name, assertions)__ - called once all test functions within the
|
387 | module have completed (see assertions object reference below)
|
388 | ALL tests within the module
|
389 | * __testStart(name)__ - called before a test function is run
|
390 | * __testReady(test)__ - called before a test function is run with the test object that will be passed to the test function
|
391 | * __testDone(name, assertions)__ - called once a test function has completed
|
392 | (by calling test.done())
|
393 | * __log(assertion)__ - called whenever an assertion is made (see assertion
|
394 | object reference below)
|
395 | * __done(assertions)__ - called after all tests/modules are complete
|
396 |
|
397 | The __assertion__ object:
|
398 |
|
399 | * __passed()__ - did the assertion pass?
|
400 | * __failed()__ - did the assertion fail?
|
401 | * __error__ - the AssertionError if the assertion failed
|
402 | * __method__ - the nodeunit assertion method used (ok, same, equals...)
|
403 | * __message__ - the message the assertion method was called with (optional)
|
404 |
|
405 | The __assertionList__ object:
|
406 |
|
407 | * An array-like object with the following new attributes:
|
408 | * __failures()__ - the number of assertions which failed
|
409 | * __duration__ - the time taken for the test to complete in msecs
|
410 |
|
411 | For a reference implementation of a test reporter, see lib/reporters/default.js in
|
412 | the nodeunit project directory.
|
413 |
|
414 |
|
415 | Sandbox utility
|
416 | ---------------
|
417 |
|
418 | This is a function which evaluates JavaScript files in a sandbox and returns the
|
419 | context. The sandbox function can be used for testing client-side code or private
|
420 | un-exported functions within a module.
|
421 |
|
422 | var sandbox = require('nodeunit').utils.sandbox;
|
423 | var example = sandbox('example.js');
|
424 |
|
425 | __sandbox(files, sandbox)__ - Evaluates JavaScript files in a sandbox, returning
|
426 | the context. The first argument can either be a single filename or an array of
|
427 | filenames. If multiple filenames are given their contents are concatenated before
|
428 | evaluation. The second argument is an optional context to use for the sandbox.
|
429 |
|
430 | Note: When working with the sandbox if your script depends on outside sources
|
431 | (i.e. using `require`) then you will want to pass that into the optional
|
432 | context when setting up the sandbox.
|
433 |
|
434 | var sandbox = require('nodeunit').utils.sandbox;
|
435 | // pass in some node globals
|
436 | var box_globals = {
|
437 | // Passing module.exports into the sandbox will give your code access to it.
|
438 | module: {exports: exports},
|
439 | // Passing require into the sandbox will give your code access to use it AND
|
440 | // will share the cache with modules already required from outside the sandbox.
|
441 | require: require,
|
442 | // Passing console into the sandbox will give your code access to it
|
443 | console: console
|
444 | };
|
445 | var example = sandbox('example.js', box_globals);
|
446 |
|
447 |
|
448 | Running the nodeunit Tests
|
449 | --------------------------
|
450 |
|
451 | The tests for nodeunit are written using nodeunit itself as the test framework.
|
452 | However, the module test-base.js first does some basic tests using the assert
|
453 | module to ensure that test functions are actually run, and a basic level of
|
454 | nodeunit functionality is available.
|
455 |
|
456 | To run the nodeunit tests do:
|
457 |
|
458 | make test
|
459 |
|
460 | __Note:__ There was a bug in node v0.2.0 causing the tests to hang, upgrading
|
461 | to v0.2.1 fixes this.
|
462 |
|
463 |
|
464 | __machineout__ reporter
|
465 | ----------------------------------------------
|
466 |
|
467 | The default reporter is readable for human but not for machine analysis.
|
468 | When you want to analyze the output of nodeunit, use __machineout__ reporter and you will get
|
469 |
|
470 | <img src="https://github.com/caolan/nodeunit/raw/master/img/example_machineout.png" />
|
471 |
|
472 |
|
473 | nodeunit with vim
|
474 | ----------------------------------
|
475 | There is [nodeunit.vim](https://github.com/lambdalisue/nodeunit.vim) so you can use
|
476 | nodeunit with VIM.
|
477 |
|
478 | That compiler uses __machineout__ reporter and it is useful to use
|
479 | with [vim-makegreen](https://github.com/reinh/vim-makegreen).
|
480 |
|
481 |
|
482 |
|
483 | Contributing
|
484 | ------------
|
485 |
|
486 | Contributions to the project are most welcome, so feel free to fork and improve.
|
487 | When submitting a pull request, please run `make lint` first to ensure
|
488 | we're following a consistent coding style.
|