UNPKG

17.7 kBMarkdownView Raw
1Nodeunit
2========
3
4[![Build Status](https://travis-ci.org/caolan/nodeunit.svg?branch=master)](https://travis-ci.org/caolan/nodeunit)
5
6Simple syntax, powerful tools. Nodeunit provides easy async unit testing for
7node.js and the browser.
8
9
10DEPRECATED PROJECT
11-----
12
13The 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
15Nodeunit was the arguably first testing framework developed for node. It was very useful at the time, but there's an overwhelming number
16of other worthwhile testing solutions out there that are actively maintained. tap, ava, tape, mocha, jasmine, jest, ... the list goes on and on.
17
18If 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,
19but 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
20choosing a testing solution. *You are strongly encouraged to check out other more modern testing options.*
21
22
23Features
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
34Contributors
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
52Also, check out gerad's [nodeunit-dsl](https://github.com/gerad/nodeunit-dsl)
53project, which implements a 'pretty dsl on top of nodeunit'.
54
55More contributor information can be found in the
56[CONTRIBUTORS.md](https://github.com/caolan/nodeunit/blob/master/CONTRIBUTORS.md)
57file.
58
59Usage
60-----
61
62Here 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
75When 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
79Installation
80------------
81
82There are two options for installing nodeunit:
83
841. Clone / download nodeunit from [github](https://github.com/caolan/nodeunit),
85 then:
86
87 make && sudo make install
88
892. Install via npm:
90
91 npm install nodeunit -g
92
93API Documentation
94-----------------
95
96Nodeunit 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
117Nodeunit 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
125Nodeunit aims to be simple and easy to learn. This is achieved through using
126existing structures (such as node.js modules) to maximum effect, and reducing
127the API where possible, to make it easier to digest.
128
129Tests are simply exported from a module, but they are still run in the order
130they 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
134functions still exist for backwards compatibility, and are simply aliases to
135their assert module counterparts.
136
137
138Asynchronous Testing
139--------------------
140
141When testing asynchronous code, there are a number of sharp edges to watch out
142for. Thankfully, nodeunit is designed to help you avoid as many of these
143pitfalls as possible. For the most part, testing asynchronous code in nodeunit
144_just works_.
145
146
147### Tests run in series
148
149While running tests in parallel seems like a good idea for speeding up your
150test suite, in practice I've found it means writing much more complicated
151tests. Because of node's module cache, running tests in parallel means mocking
152and stubbing is pretty much impossible. One of the nicest things about testing
153in 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
164You cannot do this when running tests in parallel. In order to keep testing as
165simple as possible, nodeunit avoids it. Thankfully, most unit-test suites run
166fast anyway.
167
168
169### Explicit ending of tests
170
171When testing async code it's important that tests end at the correct point, not
172just after a given number of assertions. Otherwise your tests can run short,
173ending before all assertions have completed. It's important to detect too
174many assertions as well as too few. Combining explicit ending of tests with
175an expected number of assertions helps to avoid false test passes, so be sure
176to use the `test.expect()` method at the start of your test functions, and
177`test.done()` when finished.
178
179
180Groups, setUp and tearDown
181--------------------------
182
183Nodeunit 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
198This would be run as:
199
200 test1
201 group - test2
202 group - test3
203
204Using these groups, Nodeunit allows you to define a `setUp` function, which is
205run before each test, and a `tearDown` function, which is run after each test
206calls `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
223In this way, it's possible to have multiple groups of tests in a module, each
224group with its own setUp and tearDown functions.
225
226
227Running Tests
228-------------
229
230Nodeunit comes with a basic command-line test runner, which can be installed
231using `sudo make install`. Example usage:
232
233 nodeunit testmodule1.js testfolder [...]
234
235If no entry file specified, `test` defaults.
236
237The default test reporter uses color output, because I think that's more fun :) I
238intend to add a no-color option in future. To give you a feeling of the fun you'll
239be 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
243Ahhh, Doesn't that feel better?
244
245When using the included test runner, it will exit using the failed number of
246assertions 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
252on of the modules in nodeunit/lib/reporters, when omitted, the default test runner
253is used.
254* __--list-reporters__ - list available built-in reporters.
255* __--config FILE__ - load config options from a JSON file, allows
256the customisation of color schemes for the default test reporter etc. See
257bin/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
264Running tests in the browser
265----------------------------
266
267Nodeunit tests can also be run inside the browser. For example usage, see
268the 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
291Here, `suite1` and `suite2` are just object literals containing test functions
292or 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
303If you wish to use a commonjs format for your test suites (using exports), it is
304up to you to define the commonjs tools for the browser. There are a number of
305alternatives and it's important it fits with your existing code, which is
306why nodeunit does not currently provide this out of the box.
307
308In the example above, the tests will run when the page is loaded.
309
310The browser-version of nodeunit.js is created in dist/browser when you do, `make
311browser`. You'll need [UglifyJS](https://github.com/mishoo/UglifyJS) installed in
312order for it to automatically create nodeunit.min.js.
313
314
315Adding nodeunit to Your Projects
316--------------------------------
317
318If you don't want people to have to install the nodeunit command-line tool,
319you'll want to create a script that runs the tests for your project with the
320correct require paths set up. Here's an example test script, that assumes you
321have 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
327If you're using git, you might find it useful to include nodeunit as a
328submodule. Using submodules makes it easy for developers to download nodeunit
329and run your test suite, without cluttering up your repository with
330the 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
334This will add nodeunit to the node_modules folder of your project. Now, when
335cloning the repository, nodeunit can be downloaded by doing the following:
336
337 git submodule init
338 git submodule update
339
340Let's update the test script above with a helpful hint on how to get nodeunit,
341if 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
360Now if someone attempts to run your test suite without nodeunit installed they
361will be prompted to download the submodules for your project.
362
363
364Built-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
376Writing a Test Reporter
377---------------------
378
379Nodeunit exports runTest(fn, options), runModule(mod, options) and
380runFiles(paths, options). You'll most likely want to run test suites from
381files, which can be done using the latter function. The _options_ argument can
382contain callbacks which run during testing. Nodeunit provides the following
383callbacks:
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
397The __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
405The __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
411For a reference implementation of a test reporter, see lib/reporters/default.js in
412the nodeunit project directory.
413
414
415Sandbox utility
416---------------
417
418This is a function which evaluates JavaScript files in a sandbox and returns the
419context. The sandbox function can be used for testing client-side code or private
420un-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
426the context. The first argument can either be a single filename or an array of
427filenames. If multiple filenames are given their contents are concatenated before
428evaluation. The second argument is an optional context to use for the sandbox.
429
430Note: 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
432context 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
448Running the nodeunit Tests
449--------------------------
450
451The tests for nodeunit are written using nodeunit itself as the test framework.
452However, the module test-base.js first does some basic tests using the assert
453module to ensure that test functions are actually run, and a basic level of
454nodeunit functionality is available.
455
456To 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
461to v0.2.1 fixes this.
462
463
464__machineout__ reporter
465----------------------------------------------
466
467The default reporter is readable for human but not for machine analysis.
468When 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
473nodeunit with vim
474----------------------------------
475There is [nodeunit.vim](https://github.com/lambdalisue/nodeunit.vim) so you can use
476nodeunit with VIM.
477
478That compiler uses __machineout__ reporter and it is useful to use
479with [vim-makegreen](https://github.com/reinh/vim-makegreen).
480
481
482
483Contributing
484------------
485
486Contributions to the project are most welcome, so feel free to fork and improve.
487When submitting a pull request, please run `make lint` first to ensure
488we're following a consistent coding style.