Create a simple calculator using Jotai, Tailwind CSS, and Vitest (Part 3)
What is Vitest?
Vitest is a testing library specifically designed for Vite and React applications. It aims to provide a simple and intuitive API for creating and running tests while being highly customizable and extensible.
Here are some key advantages of Vitest :
Component testing for Vue, React, Svelte, Lit, and more
Out-of-the-box TypeScript / JSX support
ESM first, top-level await
Multi-threading workers
Filtering, timeouts, concurrent for suite and tests
Jest-compatible Snapshot
Chai built-in for assertions + Jest expect compatible APIsDesigned with a Jest-compatible API
How to integrate Vitest in a Vite application
In a Vite project, integrating Vitest can be done by installing the Vitest package as a dev dependency.
npm install -D vitest
I used vite
in my current project, so It does not need extra configuration. For projects using Next Js
or React
, you can add vitest
by adding a file vitest.config.ts
. All the examples, you may find here.
// vitest.config.ts for Next Js
import { defineConfig } from 'vitest/config'
import react from '@vitejs/plugin-react'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
test: {
environment: 'jsdom',
},
})
// vitest.config.ts for Create-React-App
import { defineConfig } from 'vite'
export default defineConfig({
test: {
globals: true,
environment: 'happy-dom',
},
})
In the package.json
, I will add new lines to run testing.
...
"test": "vitest",
"coverage": "vitest run --coverage"
...
Write tests for my application
Here is an example of doing the unit testing of the utils function. it
, describe
, and expect
can be imported from vitest
. The describe
function is used to group related test cases together. In this case, the description of the test suite is "should doCalculating do calculate correctly". The it
function is used to define individual test cases. In this case, the test case is "should handle addition and routing". Inside the test case function, the doComputating
function is called with test data, and the result is compared to an expected value using the expect
function. The toEqual
matcher checks that the result1
value is equal to the expected1
value.
By running this test, we can ensure that the doComputating
function handles addition and rounding as expected. Writing test cases like this help to catch bugs and ensure that changes to the codebase do not introduce regressions.
import { it, describe, expect } from "vitest";
import { doComputating } from "../../src/utils/index";
describe.concurrent("should doCalculating do calculate correctly", () => {
it("should handle addition and rouding", () => {
const nums1 = [2, 3, 4];
const ops1 = ["+", "-"];
const expected1 = 1;
const result1 = doComputating(nums1, ops1);
expect(result1).toEqual(expected1);
});
...
}
If you use .concurrent
on a suite as the example, every test in it will be run in parallel. Or if you use .concurrent
consecutive tests to run them in parallel.
import { describe, it } from 'vitest'
// The two tests marked with concurrent will be run in parallel
describe('suite', () => {
it('serial test', async () => { /* ... */ })
it.concurrent('concurrent test 1', async ({ expect }) => { /* ... */ })
it.concurrent('concurrent test 2', async ({ expect }) => { /* ... */ })
})
The full code of this blog can be found here.
Thank you for your reading ๐๐๐