UNPKG

8.09 kBMarkdownView Raw
1# zora
2Fast 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
31It is just Javascript, write your test program, bundle it (if needed) for the environment you want to test in and execute the script! No whatever.conf.js or specific test runner.
32
33### 🎯 No global
34There is no global, just a function providing a two methods API.
35
36### ⌛️ Async testing made easy
37Use 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
39plan.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"
46Each test run in "parallel", ie as
47
48```Javascript
49const tests = [test1,test2,test3];
50
51const results = Promise.all(tests.map(t=>t.run()));
52```
53(so do note, they run it the same process)
54
55It will likely be **faster** than other sequential test runner.
56It therefore enforces you to write your tests in isolation which is often a good practice.
57
58### 🚀 fast
59Zora does not do rocket science but seems to be the **fastest** among mocha, tape, ava, jest on my machine according to a simple test case.
60The 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.
61To generate the benchmark files run `npm run build:benchmark`
62Then you can run the tests with the framework of your choice.
63Ex:
64`npm run bench:zora`
65
66### 💄 tap (Test Anything Protocol) producer
67By 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)
68
69### 🌎 browser friendly
70No sophisticated or platform specific (nodejs) dependency in it. Just regular EcmaScript supported by all the major platforms and browsers.
71Moreover 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 and you don't need any specific test runner.
72
73## Usage
74### simple case one file
75```Javascript
76
77import zora from 'zora';
78
79// you create a test plan
80const plan = zora();
81
82plan
83 .test('a test',(assertion) => {
84 assertion.equal('foo','foo');
85 })
86 .test('another test',(assertion) => {
87 assertion.ok(true)
88 })
89 .run(); // you run it
90```
91### multiple files setup (recommended)
92You 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.
93You'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.
94```Javascript
95
96//./test/test1.js
97import zora from 'zora';
98
99const plan = zora();
100
101plan
102 .test('a test',(assertion) => {
103 assertion.equal('foo','foo');
104 })
105 .test('another test', (assertion) => {
106 assertion.ok(true)
107 })
108
109export default plan; // export the plan
110```
111
112Then in you entry point
113```Javascript
114//./test/index.js
115import zora from 'zora';
116import plan1 from './test1.js'; // import all your test plans
117import plan2 from './test2.js'; // import all your test plans
118// etc
119
120// you create a test plan
121const masterPlan = zora();
122
123masterPlan
124 .test(plan1)
125 .skip(plan2)
126 .run(); // and run your plans
127```
128
129## In the browser
130Zora itself does not depend on native nodejs modules (such file system, processes, etc) so the code you will get is regular Ecmascript
131
132You can find some recipes [here](https://github.com/lorenzofox3/zora-recipes)
133
134### drop in file
135You can simply drop the dist file in the browser and write your script below (or load it).
136You can for example play with this [codepen](http://codepen.io/lorenzofox3/pen/zoejxv?editors=1112)
137
138```Html
139<!-- some content -->
140<body>
141<script src="path/to/zora.js"></script>
142<!-- your test code -->
143<script>
144 Zora()
145 .test('some test', (assert) => {
146 assert.ok(true, 'hey there');
147 })
148 .test('some failing test', (assert) => {
149 assert.fail('it failed');
150 })
151 .run();
152</script>
153</body>
154<!-- some content -->
155```
156
157### As part of CI (example with rollup)
158I 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.
159
160assuming you have your entry point as follow :
161```Javascript
162//./test/index.js
163import zora from 'zora';
164import test1 from './test1.js'; // some tests here
165import test2 from './test2.js'; // some more tests there
166import test3 from './test3.js'; // another test plan
167
168const plan = zora()
169 .test(test1)
170 .test(test2)
171 .test(test3)
172
173plan.run();
174```
175
176where for example ./test/test1.js is
177```Javascript
178import zora from 'zora';
179
180const plan = zora()
181 .test('mytest',(assertions) => {
182 assertions.ok(true);
183 })
184 .test('mytest',(assertions) => {
185 assertions.ok(true);
186 });
187
188export default plan;
189```
190At 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.
191Using rollup, we would have the following configuration (for more info follow the [tutorial serie](https://code.lengstorf.com/learn-rollup-js/))
192
193```Javascript
194const node = require('rollup-plugin-node-resolve');
195const commonjs = require('rollup-plugin-commonjs');
196module.exports = {
197 entry: './test/index.js',
198 dest: './test/dist/index.js',
199 format: 'iife', //iife as the code will run in the browser
200 plugins: [node(), commonjs()], //you can add babel plugin if you need transpilation
201 moduleName:'test'
202};
203```
204
205and 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
206![tap output in the browser console](console-sc.png)
207
208Even 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.
209
210so all together, in your package.json you can have something like that
211```Javascript
212{
213// ...
214 "scripts": {
215 "test": "rollup -c ./test/test.js && cat ./test/dist/index.js | tape-run"
216 }
217// ...
218}
219```
220## Use output data not as a tap output
221
222// TODO add a different sink generator example
223
224## Assertions API
225
226The assertion api you can use within your test is pretty simple and highly inspired from [tape](https://github.com/substack/tape)
227* ok
228* notOk
229* equal
230* notEqual
231* deepEqual
232* notDeepEqual
233* throws
234* doesNotThrow
235* fail
236
237You can use any other assertion library as well but a failing assertion will likely throw an exception which won't be properly tap reported