Simple tests assertions provide:

Better readability.

Less code.

Less maintenance.

These features trump all the bells and whistles in the world.

No contest.

Testing tools should be modular

Some test frameworks (Mocha, Jest, etc…) provide more services than a simple test runner. They want to format your tests so they’re easy to read, or they’ll do your mocking for you automagically. (Remember what I said about magic in test suites?)

They try to be end-to-end test solutions. Speaking from the experience of porting a Mocha driven test framework from client-only tests to universal JavaScript testing, believe me when I say: sometimes end-to-end can end badly.

Jest bills itself as a better end-to-end solution with automatic mocking of Node modules. You can probably imagine what I think of that.

Solutions like Mocha and Jasmine are harder to fit into your continuous integration pipeline than tape.

TAP

TAP is the Test Anything Protocol that has been around since 1987. Almost every important automated testing tool supports TAP output. There are TAP processors that produce colored console reports, processors that make pretty, styled HTML, processors that can branch on results and trigger various hooks, and on and on…

You could think of Tape as a pure CLI tool that takes unit tests as input and produces TAP as output. Using standard Unix tools available on every Node platform, you can integrate tape with literally any tooling that can read from stdin and understand TAP output.

Remember that bland test output above? Here’s what it looks like:

Your turn!

Copy and paste the test code above and run the following commands in your terminal:

npm install -g babel-cli tape faucet browserify browser-run

npm install --save-dev babel-preset-es2015 babelify tape

You’ll also need a `.babelrc` file:

{

"presets": ["es2015"]

}

Then give it a try:

babel-node test.js | faucet

Cool, huh?

But what if you want to run your tests in a browser? Try this:

browserify -t babelify test.js | browser-run -p 2222

Pop open your browser and navigate to:

http://localhost:2222

Don’t worry if you’re staring at a blank page. Switch back over to your console and take a look. You should see this:

TAP version 13

# A passing test

ok 1 This test will pass.

# Assertions with tape.

not ok 2 Given two mismatched values, .equal() should produce a nice bug report

---

operator: equal

expected: ‘something to test’

actual: ‘sonething to test’

at: Test.assert (http://localhost:2222/bundle.js?87789b09:5195:17)

... 1..2

# tests 2

# pass 1

# fail 1

Look familiar? You can even pipe it through `faucet`:

browserify -t babelify test.js | browser-run -p 2222 | faucet

Modularity > *

Mocha, Jasmine, Jest and the rest? Just say no to clutter. Simplify your life. Experience testing zen.

Do you really need an end-to-end solution that thinks its way is the only way, or do you want a solution that you can literally plug into any standard system workflow?

If you’re writing for close to 100% coverage (and you should be), your test suite is likely to be larger than your application. What if you decide you want to change your testing workflow tomorrow? How much of your test suite do you think you could port in a day?

I recently started using promises in my unit tests. I switched from Tape to Blue Tape, which is just a thin wrapper around tape to add promise support. I didn’t have to change a single unit test to make it work. I didn’t have to change anything in my testing and continuous delivery pipeline at all.

A few weeks ago I ported an entire app test suite from QUnit (jQuery test framework) to Tape. It took 5 minutes. On a recent job I moved a bunch of inline assertions from the live code into unit tests (which was a better place for these particular assertions). I literally copied, pasted and did one search & replace.

Parallel Testing

Think you’ll miss automagic test parallelization? I keep tests for different modules in different files. It takes about five minutes to write a little wrapper that will fire up workers across all your machine cores and zip through them in parallel.

Before/After/BeforeEach/AfterEach

You don’t need these. They’re bad for your test suite. Really. I have seen these abused to share global state far too often. Try this, instead:

Fewer features is the new feature-rich

Because tape is such a simple module with such simple features, it’s easy to extend it and fit it into many different workflows. For instance, take a look at the Cloverfield prod-module-boilerplate package.json.

`blue-tape` is just a simple wrapper around tape that adds promise support, so you can write tests like this:

It’s also a breeze to integrate all of this stuff with continuous integration services. We have the prod-module-boilerplate configured to validate our new package commits in both Travis CI and CircleCI.

P.S. If you’re unit testing React components, use the shallow renderer.

Do you want bells and whistles, or do you want flexibility? If you want your testing to just get out of your way and let you concentrate on building things…