1 | # zora
|
2 | Fast javascript test runner for **nodejs** and **browsers**
|
3 |
|
4 | [![CircleCI](https://circleci.com/gh/lorenzofox3/zora.svg?style=svg)](https://circleci.com/gh/lorenzofox3/zora)
|
5 |
|
6 | ## Table of Contents
|
7 |
|
8 | - [installation](#installation)
|
9 | - [features](#features)
|
10 | - [Zero config](#zero-config)
|
11 | - [No global](#no-global)
|
12 | - [Async testing made easy](#async-testing-made-easy)
|
13 | - [parallelism](#parallelism)
|
14 | - [fast](#fast)
|
15 | - [tap (Test Anything Protocol) producer](#tap-test-anything-protocol-producer)
|
16 | - [browser friendly](#browser-friendly)
|
17 | - [Usage](#usage)
|
18 | - [simple case one file](#simple-case-one-file)
|
19 | - [multiple files setup (recommended)](#multiple-files-setup-recommended)
|
20 | - [In the browser](#in-the-browser)
|
21 | - [drop in file](#drop-in-file)
|
22 | - [As part of CI (example with rollup)](#as-part-of-ci-example-with-rollup)
|
23 | - [Use output data not as a tap output](#use-output-data-not-as-a-tap-output)
|
24 | - [CLI](#cli)
|
25 |
|
26 | ## installation
|
27 | ``npm install --save-dev zora``
|
28 |
|
29 | ## features
|
30 | ### ⚡️ Zero config
|
31 | It is just Javascript, write your program, bundle it (if needed) for the environment you want to test in and execute the script! No whatever.conf.js
|
32 |
|
33 | ### 🎯 No global
|
34 | There is no global, just a function providing a two methods API.
|
35 |
|
36 | ### ⌛️ Async testing made easy
|
37 | Use the Javascript native [AsyncFunction](http://devdocs.io/javascript/statements/async_function) to write your asynchronous code as it was synchronous. No need for a callback or to plan ahead.
|
38 | ```Javascript
|
39 | plan.test('my async test',async (assert) => {
|
40 | const resolvedResult = await db.findUser('foo');
|
41 | assert.deepEqual(resolvedResult, {name:'foo'}, 'should have fetched mister foo');
|
42 | });
|
43 |
|
44 | ```
|
45 | ### 📐 parallelism
|
46 | Each test run in parallel. It will likely be **faster** than other sequential test runner.
|
47 | It therefore enforces you to write your tests in isolation which is often a good practice.
|
48 |
|
49 | ### 🚀 fast
|
50 | Zora does not do rocket science but seems to be the **fastest** (by at least 10 times) among mocha, tape, ava, jest on my machine according to [a simple test case](https://github.com/lorenzofox3/zora#benchmark)
|
51 | The test is pretty simple: a nodejs test suite split into N(=8) files with M(=8) tests lasting T(=60ms). Anyway you can simply fork the repo and sort it out yourself.
|
52 |
|
53 | ### 💄 tap (Test Anything Protocol) producer
|
54 | By default zora produces a tap report through the console, so you can pipe in with any [tap reporter](https://github.com/sindresorhus/awesome-tap#reporters). Alternatively you can use the reporter API to build any custom reporter... even a full [dashboard](https://github/lorenzofox3/zora-reporter)
|
55 |
|
56 | ### 🌎 browser friendly
|
57 | No sophisticated or platform specific (nodejs) dependency in it. Just regular EcmaScript supported by all the major platforms and browsers.
|
58 | Moreover Zora does not make any choice on transpilation, bundling, file serving, etc like most other test runners. You use what fits the best for your use cases.
|
59 |
|
60 | ## Usage
|
61 | ### simple case one file
|
62 | ```Javascript
|
63 |
|
64 | import zora from 'zora';
|
65 |
|
66 | // you create a test plan
|
67 | const plan = zora();
|
68 |
|
69 | plan
|
70 | .test('a test',(assertion) => {
|
71 | assertion.equal('foo','foo');
|
72 | })
|
73 | .test('another test',(assertion) => {
|
74 | assertion.ok(true)
|
75 | })
|
76 | .run(); // you run it
|
77 | ```
|
78 | ### multiple files setup (recommended)
|
79 | You might want to split your tests in various files. The recommended way is to make each file exports its own plan... and create a plan of plans.
|
80 | You'll have a single entry point which makes things easier if you want to use a module bundler for example or quickly skip a whole set of tests.
|
81 | ```Javascript
|
82 |
|
83 | //./test/test1.js
|
84 | import zora from 'zora';
|
85 |
|
86 | const plan = zora();
|
87 |
|
88 | plan
|
89 | .test('a test',(assertion) => {
|
90 | assertion.equal('foo','foo');
|
91 | })
|
92 | .test('another test', (assertion) => {
|
93 | assertion.ok(true)
|
94 | })
|
95 |
|
96 | export default plan; // export the plan
|
97 | ```
|
98 |
|
99 | Then in you entry point
|
100 | ```Javascript
|
101 | //./test/index.js
|
102 | import zora from 'zora';
|
103 | import plan from './test1.js'; // import all your test plans
|
104 |
|
105 | // you create a test plan
|
106 | const masterPlan = zora();
|
107 |
|
108 | masterPlan
|
109 | .test(plan)
|
110 | .run(); // and run your plans
|
111 | ```
|
112 |
|
113 | ## In the browser
|
114 | Zora itself does not depend on native nodejs modules (such file system, processes, etc) so the code you will get is regular Ecmascript
|
115 |
|
116 | You can find some recipes [here](https://github.com/lorenzofox3/zora-recipes)
|
117 |
|
118 | ### drop in file
|
119 | You can simply drop the dist file in the browser and write your script below (or load it).
|
120 | You can for example play with this [codepen](http://codepen.io/lorenzofox3/pen/zoejxv?editors=1112)
|
121 |
|
122 | ```Html
|
123 | <!-- some content -->
|
124 | <body>
|
125 | <script src="path/to/zora.js"></script>
|
126 | <!-- your test code -->
|
127 | <script>
|
128 | Zora()
|
129 | .test('some test', (assert) => {
|
130 | assert.ok(true, 'hey there');
|
131 | })
|
132 | .test('some failing test', (assert) => {
|
133 | assert.fail('it failed');
|
134 | })
|
135 | .run();
|
136 | </script>
|
137 | </body>
|
138 | <!-- some content -->
|
139 | ```
|
140 |
|
141 | ### As part of CI (example with rollup)
|
142 | I will use [rollup](http://rollupjs.org/) for this example, but you should not have any problem with [webpack](https://webpack.github.io/) or [browserify](http://browserify.org/). The idea is simply to create a test file your testing browsers will be able to run.
|
143 |
|
144 | assuming you have your entry point as follow :
|
145 | ```Javascript
|
146 | //./test/index.js
|
147 | import zora from 'zora';
|
148 | import test1 from './test1.js'; // some tests here
|
149 | import test2 from './test2.js'; // some more tests there
|
150 | import test3 from './test3.js'; // another test plan
|
151 |
|
152 | const plan = zora()
|
153 | .test(test1)
|
154 | .test(test2)
|
155 | .test(test3)
|
156 |
|
157 | plan.run();
|
158 | ```
|
159 |
|
160 | where for example ./test/test1.js is
|
161 | ```Javascript
|
162 | import zora from 'zora';
|
163 |
|
164 | const plan = zora()
|
165 | .test('mytest',(assertions) => {
|
166 | assertions.ok(true);
|
167 | })
|
168 | .test('mytest',(assertions) => {
|
169 | assertions.ok(true);
|
170 | });
|
171 |
|
172 | export default plan;
|
173 | ```
|
174 | At the time of writing the browsers probably won't understand the [ES module](http://www.2ality.com/2014/09/es6-modules-final.html) syntax so we need to bundle our test file.
|
175 | Using rollup, we would have the following configuration (for more info follow the [tutorial serie](https://code.lengstorf.com/learn-rollup-js/))
|
176 |
|
177 | ```Javascript
|
178 | const node = require('rollup-plugin-node-resolve');
|
179 | const commonjs = require('rollup-plugin-commonjs');
|
180 | module.exports = {
|
181 | entry: './test/index.js',
|
182 | dest: './test/dist/index.js',
|
183 | format: 'iife', //iife as the code will run in the browser
|
184 | plugins: [node(), commonjs()], //you can add babel plugin if you need transpilation
|
185 | moduleName:'test'
|
186 | };
|
187 | ```
|
188 |
|
189 | and that'is it. You can now drop you ./test/dist/index.js in a html document and open it in the browser. You should see something like this in the console
|
190 | ![tap output in the browser console](console-sc.png)
|
191 |
|
192 | Even better, you can use tap reporter browser friendly such [tape-run](https://www.npmjs.com/package/tape-run) so you'll have a proper exit code depending on the result of your tests.
|
193 |
|
194 | so all together, in your package.json you can have something like that
|
195 | ```Javascript
|
196 | {
|
197 | // ...
|
198 | "scripts": {
|
199 | "test": "rollup -c ./test/test.js && cat ./test/dist/index.js | tape-run"
|
200 | }
|
201 | // ...
|
202 | }
|
203 | ```
|
204 | ## Use output data not as a tap output
|
205 |
|
206 | // TODO add a different sink generator example
|
207 |
|
208 | ## Assertions API
|
209 |
|
210 | The assertion api you can use within your test is pretty simple and highly inspired from [tape](https://github.com/substack/tape)
|
211 | * ok
|
212 | * notOk
|
213 | * equal
|
214 | * notEqual
|
215 | * deepEqual
|
216 | * notDeepEqual
|
217 | * throws
|
218 | * doesNotThrow
|
219 | * fail
|
220 |
|
221 | You can use any other assertion library as well but a failing assertion will likely throw an exception which won't be properly tap reported
|