A Couple of Words about Coverage
Today we talk about a new coverage tool 🎩ESCover and much more!
Hi guys!
I think you know that code transformer 🐊Putout
has 100%
test coverage. Why so? The thing is writing parsers is a very hard task, but worry not! There is a helper 😏!
Mock the import!
Mock-import
exists for about a year and used to mock things when you using EcmaScript Modules
. It uses 🐊Putout
and changes ImportDeclarations
to VariableDeclaration
when you need it the most. So such code:
import {readFile} from 'fs/promises';
Becomes:
const {readFile} = global.__mockImportCache.get('fs/promises');
It works amazing! But there is a problem with coverage
:
nyc
doesn't supportESM
;c8
shows wrong coverage information when loaders used;
Taking into accord these two factors.
🧨 New players in the game get you covered!
One more coverage tool comes into the wild: 🎩 ESCover
. It's also based on 🐊Putout
. It sets markers that will be called later, changing this code:
export const sum = (a, b) => {
return a + b;
};
Into this:
export const sum = (a, b) => {
return __c4['🧨'](5, 4), a + b;
};
__c4
is a variable with a special meaning: it provides a function that gives information about line and number of current instruction.
Here is what the report looks like when everything is fine:
# CAP version 131..3
# files: 3
# covered: 3# 🌴 ok
When something isn’t right:
# CAP version 13# /Users/coderaiser/escover/example/example.js
🧨 should be covered
---
lines:
️- 1 at file:///Users/coderaiser/escover/example/example.js:11..3
# files: 3
# covered: 2# 🧨 fail: 1
Or like this:
You can choose what you prefer 😏.
🎩ESCover
is ready to be used on a regular basis 🎉!
The only thing is: it works with EcmaScript Modules
only. And this is for a reason: for CommonJS
you can use c8
and nyc
. But there is no tool that shows coverage for files changed with node loaders
.
Results of 🎩ESCover
are saved to coverage/lcov.info
and it reads them when done. A couple of things about coverage:
-☝️ lcov
was created in 2002
, almost twenty years ago.
-☝️ Linux kernel developers created it to know what is going on with the coverage.
-☝️ lcov originally was written in PERL
and has text-based format.
-☝️ This is most popular coverage format of all times supported by a lot of tools (like coveralls, c8 and nyc).
So if we run our ESM
application with:
escover npm test
We will receive coverage/lconf.info
with something similar to:
SF:/Users/coderaiser/escover/lib/transform.js
DA:1,1
DA:3,1
DA:7,1
DA:9,1
DA:10,1
DA:12,1
DA:24,1
DA:25,1
DA:27,1
DA:28,1
DA:29,1
DA:32,1
end_of_record
Where:
SF
- is the path to source;DA
- is line number, and count of running;end_of_record
latest record for current file entry;
As for me, this is really human readable, and very compact form. The only thing I don’t get for now is: counters, I see no reason why do I need them 🤷♂️, if you have a reason create an issue. It can be added in one line of code.
🎩ESCover
on early stages of development, so a lot of things can change, but it is already used on a couple of projects, and everything is fine 🎈.
🤷♂️ What more can I do with 🐊Putout
?
You can trace the execution of functions with the help of ESTrace
. It provides such information:
coderaiser@cloudcmd:~/estrace$ node --loader estrace example/lint.js
..💣 lint([]) 16.05mb file:///Users/coderaiser/estrace/example/lint.js:5
....💣 getFiles([]) 16.05mb file:///Users/coderaiser/estrace/example/lint.js:12
....💥 getFiles 16.06mb file:///Users/coderaiser/estrace/example/lint.js:12
....💣 lintFiles([]) 16.06mb file:///Users/coderaiser/estrace/example/lint.js:22
....💥 lintFiles 16.06mb file:///Users/coderaiser/estrace/example/lint.js:22
..💥 lint 16.06mb file:///Users/coderaiser/estrace/example/lint.js:5
And does the next transformations. Let’s suppose that you have a function:
const fn = (a) => a
EStrace
will replace it with:
const fn = (a) => {
try {
var __estrace_context = __estrace.enter('<anonymous:2>', 'file://hello.js:2', arguments);
return a;
} finally {
__estrace.exit('<anonymous:2>', 'file://hello.js:2', __estrace_context);
}
};
🤷♂️ What with new rules?
@putout/plugin-convert-commonjs-to-esm
doesn't require you to usesimport
anymore. Only built-in modules 💪 (Thanks to @putout/plugin-declare-undefined-variables
which supports native node.js
modules, and will declare it, when you use it 😉).
@putout/plugin-nodejs
got a new rule: convert-dirname-to-url
. What does it do?
Changes:
import {readFile} from 'fs/promises';
const file1 = join(__dirname, '../../package.json');
To:
import {readFile} from 'fs/promises';
const file1 = new URL('../../package.json', import.meta.url).pathname;
This will help to get rid of __dirname
in EcmaScript Modules
. Here is the fast draft and results.
🦔 Real world uses
I just found out (I knew that they were going to, but who knows 😅…) that folks from Stylelint
used 🐊 Putout
to convert their codebase to ESM
🎉.
And got a little problem with jest
: it doesn't recognize import.meta.url
🤷♂️. Well, that’s sad 😕, but hey!
This is why 📼 Supertape
exists: simplest high-speed testing.
Thanks a lot to the Stylelint team! That's awesome what you are doing and very inspiring!
That’s all for today! Have a nice coding 🎮!
More content at plainenglish.io. Sign up for our free weekly newsletter. Get exclusive access to writing opportunities and advice in our community Discord.