We code the web

Effortless unit testing with AVA

There are a lot of test runners out there. Mocha, Jasmine, tape and more. I hear you thinking: “another framework?”. But Ava is a worthy alternative for the existing solutions.

Simplicity

First of all AVA is simple. It’s really easy to set up. First install ava: npm install ava -g, then run ava by running ava. AVA will by default detect tests using common patterns. Let’s make one:

1
2
3
4
5
6
// test.js
import test from 'ava'
test('one plus one is two', t => {
t.is(1 + 1, 2)
})

This is it, simple as that. Maybe you are thinking, ES6 code? Don’t you have to transpile that? No, AVA supports ES6 by default, awesome!

Efficiency

Tests run in parallel by default, this means that in general they will run faster. You’re able to run them in serial if needed. However, having your tests run in parallel also forces you to make sure all your tests are completely independent of each other, which is always a good practice.

Asynchronous

AVA supports asynchronous testing by default:

1
2
3
4
5
6
7
test('async test', t => {
t.plan(1)
setTimeout(() => {
t.is(3, 1 + 2)
}, 1000)
})

We let AVA know that one assertion is coming up, so AVA will wait for the timeout to finish. If you return a promise you don’t have to wait at all.

1
2
3
4
5
6
test('async test', t => {
return Promise.resolve('wecodetheweb')
.then(text => {
t.is(text, 'wecodetheweb');
});
})

Only one

Another nifty feature that you can only run the test that you are working on. This can be handy if you have a lot of tests and you want to focus one fixing one at a time:

1
2
3
4
5
6
7
test('one plus one is two', t => {
t.is(1 + 1, 2)
})
test.only('two plus one is three', t => {
t.is(1 + 2, 3)
})

It will now only run the second test.

Mocking

AVA has no mocking built in, to mock functions just use Sinon.js. Install sinon by running npm install sinon --save-dev. Then use it in your tests:

1
2
3
4
5
6
7
8
9
import sinon from 'sinon'
const myFunction = sinon.spy()
test('my function is running!', t => {
myFunction()
t.true(myFunction.called)
})

Running AVA locally

Installing AVA globally is okay to play around with it. But in a “real” project you want your dependencies to be local. To setup AVA for your project simply run npm install ava --save-dev. Then add the following script to your package.json:

1
2
3
4
5
6
{
"scripts": {
"test": "ava",
"test:watch": "ava --watch"
}
}

You can now run your tests using npm run test or npm run test:watch if you want to let them automatically run on change.

Code coverage

Getting code coverage reports is also really easy. AVA runs tests using so called “subprocesses”, this is why just using istanbul for code coverage will not work. Luckily there is a wrapper around istanbul that supports subprocesses called nyc. Install nyc using npm install nyc --save-dev, then run it with nyc ava.

Conclusion

AVA is really worth a try, it combines the ease of use of Jasmine with the simplicity of tape. It works for both front- and back-end Javascript applications. I can start summing up all the features in this article, but that’s what the documentation is for.

Reference

Related posts

Unit testing asynchronous Angular services

Angular is built to be testable. But when I tried to test an Angular service that had a dependency on another service ánd communicated asynchronously with it, I faced a bit of a challenge.

Improving code quality using ESLint

ESLint the Javascript linter of choice today. But it can do more than just checking semicolons and quotes. In this article we’ll go over how to configure ESLint to really help improve your code.

ES6 Destructuring

Destructuring must be my favorite feature of ECMAScript 6. I don’t exactly know why, I guess I just like the simplicity. It makes your code more clean and declarative.