by Edd Yerburgh
Write blazing fast Vue unit tests with Tape and Vue Test Utils
Tape is the fastest framework for unit testing Vue components.
In this article, we’ll see how to write Vue unit tests with Tape and Vue Test Utils.
This tutorial is for users familiar with unit testing. If you’re new to unit testing check out unit testing Vue components for beginners.
What is Tape?
Tape is a bare bones unit test framework that outputs the test report in TAP (Test Anything Protocol) format.
A couple weeks ago I ran some performance tests on different testing frameworks. I wanted to find out which framework was the fastest for testing Vue SFCs (Single File Components).
I added Tape for completeness sake, and was shocked to find it was the fastest performing framework.
To run tests in Tape, we need to do some setup. Let’s dive right in.
Bootstrapping the project
I’ve made a simple starter project to start with. Git clone the project into a directory:
git clone https://github.com/eddyerburgh/jest-vue-starter.git
cd into it and install the dependencies:
cd jest-vue-starter && npm install
Run the dev server as
npm run dev to check out the app.
It’s pretty simple. The the main point of this tutorial is to see how to set up Tape and Vue, not to write complex tests.
Setting up Tape and Vue Test Utils
First thing to do is install Tape and Vue Test Utils:
npm install --save-dev tape @vue/test-utils
Vue Test Utils is in beta, so we need to request the version explicitly
Vue Test Utils needs a browser environment to run. This doesn’t mean we need to run the tests in a browser (thank fully!).
We can use jsdom to set up a browser environment in Node. It adds global variables like
window to Node.
jsdom is a bit of a pain to setup. Luckily some enterprising node developer made a wrapper library called
npm install --save-dev browser-env
We need to run
browser-env before the tests. Tape lets us define files to run before the tests, we’ll do that in a sec.
Vue SFCs need to be compiled before they’re tested. We can use
require-hooks to run WebPack on files when they’re required in Node. It’s a simple setup.
require-extension-hooks and its variants:
npm install --save-dev require-extension-hooks require-extension-hooks-babel require-extension-hooks-vue
Let’s make that setup file I spoke about earlier. Create a
test directory, and add a
setup.js file. The final path will be
We’re nearly there. Crazy stuff.
Let’s write a smoke test in Tape. Create a new file called
List.spec.js in the test directory. Full path
test/List.spec.js. Copy the test below into the file:
What’s going on there? We define a
test, and get a
t object in the callback. The
t object contains assertion methods. It also has a
plan method . We need to tell Tape how many tests it should expect.
Now we need a script to run the tests. Open the
package.json and add this script:
"unit": "tape ./test/specs/*.spec.js -r ./test/setup.js"
This tells tape to run all
.spec files in
-r tells Tape to
require or run
test/setup before running our tests.
npm run unit
Yay, we have a passing test. But hoo boy—that’s some ugly test output ☹️
Remember I mentioned TAP earlier? This is TAP in it’s naked glory. Pretty ugly right? Don’t worry, we can prettify it.
npm install --save-dev tap-spec
We can pipe our TAP output from Tape. Edit the
unit script to pipe the output to
"unit": "tape ./test/specs/*.spec.js -r ./test/setup.js | tap-spec"
And run the tests again:
npm run unit
Much better ?
Writing tests with Tape and Vue Test Utils
Let’s write some tests then. Since we’re using Vue Test Utils, the tests are pretty readable.
List.spec.js, we’re going to write a
test that passes an
items array to
List. We’ll use the
shallow method from Vue Test Utils to shallow mount the component.
shallow returns a
wrapper containing the mounted component. We can use
findAll to search the render tree for
<li> tags, and check how many there are.
Copy the test from below into
Watch the tests pass with
npm run unit. Notice we have a custom error message for out
t.equals assertion. The default messages aren’t very readable, so it’s better to add our own.
Now add a new file
test/specs/MessageToggle.spec.js. In here we’ll write a test for, you guessed it,
We’re going to write two tests now. One will check the
<;p> tag renders a default message. We’l
l use shallow again to get a wrapper containing the mounted component, and us
e the text method to return the text insid
e the <p> tag.
The second test is similar. We’ll assert that the message changes when the
toggle-message button is pressed. To do that, we can use the
Copy the code below into
Run the tests again with
npm run unit. Woop—green tests ?
Pros and cons of Tape
Now we’ve added some tests, let’s look at the pros and cons of using Tape.
- It’s fast
Like really fast ?
- It’s simple
You can read the source code to
- It uses TAP.
Because TAP is a standard, there are lots of programs that work directly with TAP
Like the tap-spec module, we just piped some TAP text into it and it prettified it for us
- Limited assertions
Limited assertions keep your assertions easy to understand
- Limited assertions
This is a con too
You can get useful error messages with assertions like
hasBeenCalledWith, this is difficult to replicate with
- It breaks
When you run more than 10000 tests
You probably won’t hit that. But it might be a deal breaker for a large Vue project
- It’s basic
You’ll need to use other libraries for mocking, stubbing and faking
The pros and cons are pretty similar. Tape is basic, and that can be a good thing or a bad thing depending on who you ask.
Most importantly though, it’s blazing fast!
Fast unit tests are good unit tests.
Call to action
The best way to work out a new test framework is to use it.
On the next Vue project you start, try Tape. You can find a list of assertions on the Tape README.
You can find the finished repo on GitHub.