UNPKG

7.69 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 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
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. It will likely be **faster** than other sequential test runner.
47It therefore enforces you to write your tests in isolation which is often a good practice.
48
49### 🚀 fast
50Zora 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)
51The 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
54By 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
57No sophisticated or platform specific (nodejs) dependency in it. Just regular EcmaScript supported by all the major platforms and browsers.
58Moreover 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
64import zora from 'zora';
65
66// you create a test plan
67const plan = zora();
68
69plan
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)
79You 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.
80You'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
84import zora from 'zora';
85
86const plan = zora();
87
88plan
89 .test('a test',(assertion) => {
90 assertion.equal('foo','foo');
91 })
92 .test('another test', (assertion) => {
93 assertion.ok(true)
94 })
95
96export default plan; // export the plan
97```
98
99Then in you entry point
100```Javascript
101//./test/index.js
102import zora from 'zora';
103import plan from './test1.js'; // import all your test plans
104
105// you create a test plan
106const masterPlan = zora();
107
108masterPlan
109 .test(plan)
110 .run(); // and run your plans
111```
112
113## In the browser
114Zora itself does not depend on native nodejs modules (such file system, processes, etc) so the code you will get is regular Ecmascript
115
116You can find some recipes [here](https://github.com/lorenzofox3/zora-recipes)
117
118### drop in file
119You can simply drop the dist file in the browser and write your script below (or load it).
120You 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)
142I 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
144assuming you have your entry point as follow :
145```Javascript
146//./test/index.js
147import zora from 'zora';
148import test1 from './test1.js'; // some tests here
149import test2 from './test2.js'; // some more tests there
150import test3 from './test3.js'; // another test plan
151
152const plan = zora()
153 .test(test1)
154 .test(test2)
155 .test(test3)
156
157plan.run();
158```
159
160where for example ./test/test1.js is
161```Javascript
162import zora from 'zora';
163
164const plan = zora()
165 .test('mytest',(assertions) => {
166 assertions.ok(true);
167 })
168 .test('mytest',(assertions) => {
169 assertions.ok(true);
170 });
171
172export default plan;
173```
174At 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.
175Using rollup, we would have the following configuration (for more info follow the [tutorial serie](https://code.lengstorf.com/learn-rollup-js/))
176
177```Javascript
178const node = require('rollup-plugin-node-resolve');
179const commonjs = require('rollup-plugin-commonjs');
180module.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
189and 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
192Even 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
194so 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
210The 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
221You can use any other assertion library as well but a failing assertion will likely throw an exception which won't be properly tap reported