Testing is an important part of application development that helps you catch bugs early on instead of you meeting them when your app is already in production. I never really did tests for my web applications but while working on a project with a friend, I saw how he had done tests for the back end side (Laravel) and how he was able to catch bugs and errors early on. The way the project is implemented, if there is a pull request opened onto the production branch, there is a workflow for running tests. If any test fails, the pull request is not merge.
Once the existing bugs and errors are fixed and changes are pushed, the workflow runs again and if all tests pass, the changes are merged to the production branch and the production build workflow is run. My point for this little story is that having tests helps you to be certain that your appliction will not fail in production due to unforeseen bugs and errors.
I know sometimes you can tell yourself the front end side of things doesn't really need tests but that's not true. Testing on the front end can help you catch errors and bugs such as some CSS styles not being applied to some browsers or not all form inputs are being validated before sending data to the API or even not handling events such as receiving a number when you expected an array/object.
Some of the testing libraries you can use with Vue are:
Some of the types of testing you can perform on the front end side are:
Please note Vitest requires Vite >=v3.0.0 and Node >=v14.18
Component testing involves running tests for your components and checking that the components are being mounted and renderred properly. They also check if your components behave the way you expect them to behave. The first step for component testing using Vitest is to install Vitest and configure the vitest.config.ts
/vite.config.js
file. Run the following commands in a terminal when you open your Vue app:
npm install -D vitest #or 'yarn add -D vitest'
npm install -D @vue/test-utils #or 'yarn add -D @vue/test-utils'
Once installed, modify your vite.config.js
file (you can use a vitest.config.ts
file if you prefer doing that) to look like this:
/// <reference types="vitest" />
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
test: {
globals: true,
environment: "jsdom",
},
});
If you are importing defineConfig
from vitest/config
you do not need the very first line with the triple slash:
import { defineConfig } from "vitest/config";
import vue from "@vitejs/plugin-vue";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
test: {
globals: true,
environment: "jsdom",
},
});
Inside the test
option, the globals:true
allows us to use methods like expect
and describe
without having to do it explicitly in every test file. The environment: "jsdom"
specifies which DOM environment we are using.
Run the following to install the jsdom
dependency:
npm install -D jsdom #or 'yarn add -D jsdom'
Next we need to add the following lines inside our package.json
file inside the "scripts"
:
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook",
// Add these lines
"test": "vitest",
"coverage": "vitest run --coverage"
},
These two lines allow us to run tests and coverage commands using npm
. e.g: npm run test
.
I will be using the vue-components
project I used for this tutorial to demonstrate creating a test file for a component and running it. You can find the repository here.
We will start with a simple test to make sure that we can import the Button
and Input
components (my components exist inside components
inside src
). Add the following code in a file named imports.test.js
which should exist in a folder called tests
inside your src
folder:
describe("Import vue components", () => {
test("Importing the button component", async () => {
const cmp = await import("../components/Button.vue");
expect(cmp).toBeDefined();
});
test("Importing the input component", async () => {
const cmp = await import("../components/Input.vue");
expect(cmp).toBeDefined();
});
});
We can create a file (Button.test.js
) for testing the Button
component and test whether we can pass props to it well. I'll demonstrate a test for checking whether we are able to pass a label prop to it:
import { mount } from "@vue/test-utils";
import Button from "../components/Button.vue";
describe("Testing the button component", () => {
test("Passing props to the button", async () => {
expect(Button).toBeTruthy();
const wrapper = mount(Button, {
props: {
label: "Hello there",
},
});
expect(wrapper.text()).toContain("Hello there");
});
});
Note: You can use
*.test.ts
files too
The final step is running the tests. This is simple, all you do is run the following command and your tests will either pass or fail. If it fails it will show you which particular test has failed and you can fix the error or bug:
npm run test
Below is a sample pass result for the above tests:
✓ src/tests/imports.test.js (2) 783ms
✓ src/tests/Button.test.js (1)
Test Files 2 passed (2)
Tests 3 passed (3)
Start at 15:17:00
Duration 1.92s (transform 817ms, setup 0ms, collect 749ms, tests 815ms, environment 1.01s, prepare 339ms)
PASS Waiting for file changes...
press h to show help, press q to quit
Tests are a great way of detecting if your components, functions or web app in general is working as expected. The only down side with tests is that if your app is big you will have a lot of tests and they may take sometime to execute when many but you are assured that your app works well if all the tests pass.
If you would like me to include more test examples in this tutorial, let me know in the comments and I will update the article. If you are wondering how my Button.vue
component looks like, you can have a look at this tutorial or find the repository here. You can have a look at an article on Component testing using Cypress in Vue here.