UNPKG

4.86 kBMarkdownView Raw
1# babel-plugin-transform-adana
2
3Minimal, complete code-coverage tool for [babel] 6+.
4
5![build status](http://img.shields.io/travis/izaakschroeder/babel-plugin-transform-adana/master.svg?style=flat)
6![coverage](http://img.shields.io/coveralls/izaakschroeder/babel-plugin-transform-adana/master.svg?style=flat)
7![license](http://img.shields.io/npm/l/babel-plugin-transform-adana.svg?style=flat)
8![version](http://img.shields.io/npm/v/babel-plugin-transform-adana.svg?style=flat)
9![downloads](http://img.shields.io/npm/dm/babel-plugin-transform-adana.svg?style=flat)
10
11Has all the features (and more) of [istanbul] including line, function and branch coverage, but works as a [babel] plugin instead of relying on `esparse` and `escodegen`. Works great with [west], [mocha], [jasmine] and probably more.
12
13Features:
14
15 * First-class babel support,
16 * Per-line/function/branch coverage,
17 * Tagged instrumentation,
18 * Smart branch detection.
19
20TODO:
21 * User-defined tags,
22 * More test cases,
23 * Split out bins/reporters into other modules.
24
25## FAQ
26
27 * Why is a line marked not covered when it clearly is? - The `line` algorithm is conservative; if you have any part of a line with 0 hits, then that whole line is frozen at 0.
28 * Why is `let i;`, `function foo() {}`, etc. not marked at all? – Some things are not executable code per se (i.e. declarations). They do nothing to effect program state and are therefore not instrumented.
29
30## Usage
31
32Install `adana`:
33
34```sh
35npm install --save-dev babel-plugin-transform-adana adana-cli
36```
37
38Setup [babel] to use it:
39
40```json
41{
42 "env": {
43 "test": {
44 "plugins": [[
45 "transform-adana", {
46 "test": "src/**/*.js"
47 }
48 ]]
49 }
50 }
51}
52```
53
54**IMPORTANT**: This plugin works best when it runs as the _first_ plugin in the babel transform list, since its purpose is to instrument your _original code_, not whatever other transformations happen to get made.
55
56Extract the coverage data from node:
57
58```sh
59NODE_ENV="test" mocha \
60 -r babel-plugin-transform-adana/dump \
61 --compilers js:babel-core/register \
62 test/*.spec.js
63```
64
65### Tags
66
67There is no `ignore` flag, but you can tag functions, branches or statements to which can be used to determine relevant coverage information. This allows you to categorize blocks of code and ask things like "Have I covered all the code that pertains to authentication in the file?". Existing `ignore` comments simply tag a function with the `ignore` tag.
68
69 * Tags above a block (if/function/etc.) to apply to all code in that block.
70 * Tags above or on a line apply to all statements in that line.
71
72```javascript
73
74
75/* adana: +ie +firefox -chrome */
76function foo() {
77 console.log('foo'); // adana: +test
78}
79
80/* adana: +chrome */
81if () {
82
83}
84```
85
86### API
87
88`adana` is simply a [babel] transformer that injects markers to determine if specific parts of the code have been run. To inject these markers simply add `transform-adana` as a plugin and use [babel] normally:
89
90```javascript
91import { transform } from 'babel-core';
92
93const result = transform('some code', {
94 plugins: [ 'transform-adana' ]
95});
96
97// Access result.code, result.map and result.metadata.coverage
98```
99
100To collect information about code that has been instrumented, simply access the configured global variable, e.g. `__coverage__`.
101
102```javascript
103import vm from 'vm';
104const sandbox = vm.createContext({});
105sandbox.global = sandbox;
106vm.runInContext(result.code, sandbox);
107console.log(sandbox.__coverage__);
108```
109
110The `__coverage__` object has the following shape:
111
112```javascript
113{
114 // Array of counters; the index in this list maps to the same index in the
115 // locations array.
116 counters: [ 0, 0, ... ],
117 // Detailed information about every location that's been instrumented.
118 locations: [{
119 loc: { start: { line: 0, column 0 }, end: { line: 0, column: 0 } },
120 type: 'function|statement|branch',
121 name: 'foo',
122 group: 'bar',
123 tags: [ 'tagA', 'tagB' ]
124 }, {
125 ...
126 }, ...]
127}
128```
129
130```javascript
131/* global __coverage__ */
132import { writeFileSync } from 'fs';
133
134// Dump that data to disk after tests have finished.
135process.on('exit', () => {
136 writeFileSync('coverage/coverage.json', JSON.stringify(__coverage__));
137});
138
139```
140
141### HMR Spec Coverage
142
143foo.spec.js -> foo.js: overwrite coverage info only for foo.js
144
145On HMR:
146- clear coverage counters for reloaded modules
147- run reloaded code
148- replace coverage counters for reloaded modules
149
150### Other Notes
151
152```js
153// TODO: Allow "merging" of same-hash coverage where the counters are
154// incremented. This could be for someone who has to run a program
155// several times for the same files to cover everything.
156```
157
158
159[babel]: http://babeljs.io
160[istanbul]: https://github.com/gotwarlost/istanbul
161[mocha]: http://mochajs.org/
162[jasmine]: http://jasmine.github.io/
163[west]: https://www.github.com/izaakschroeder/west
164[lcov]: http://ltp.sourceforge.net/coverage/lcov/geninfo.1.php