In-Source Testing with Vite and Vitest
Aron Schüler Published
Intro
Testing your code is an essential part of any software development process. In the frontend world, Vite has become the default tooling framework for running your development server, building and bundling. It also supports the extension via many tools. Vitest is a popular tool for testing, known for its simplicity and performance as well as being Jest compatible. A lesser-known feature is the ability to write In-Source tests through automatic test discovery. This approach keeps your code and tests in one place, making it easier to maintain and understand.
In this post, we’ll explore how to write In-Source tests for TypeScript functions using Vitest’s import.meta.vitest. We’ll walk through two function examples, demonstrating how to set up, write tests, and run them.
Step-by-Step Guide
Step 1: Install Vitest
Before we dive into In-Source testing, you’ll of course need Vite and Vitest installed in your project. If you don’t have it yet, run the following command:
npm install vitest --save-devOnce installed, Vitest can be used for both your regular test files. To actually discover In-Source test files, we need to adapt the Vitest configuration in vitest.config.ts for including our source code in test discovery and adapt our tsconfig.json to allow the usage of import.meta.vitest.
Step 2: Configuring Vitest and TypeScript
Vitest (vitest.config.json)
As Vitest only discovers files with .spec. or .test. in their name per default, we need to tell it to check our “normal” source code as well. This is done with the following configuration:
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
includeSource: ["src/**/*.{js,ts}"],
},
define: {
"import.meta.vitest": "undefined",
},
});We added the includeSource configuration, which tells Vitest to include all .js and .ts files in the src directory for test discovery. Additionally, we defined the import.meta.vitest variable as undefined to set up the typing for TypeScript.
TypeScript (tsconfig.json)
Now, for the tsconfig.json part we need to add the typing of vitest/importMeta so the compiler knows that import.meta.vitest will be defined:
{
"compilerOptions": {
// ...
"types": ["node", "jsdom", "vitest/importMeta"]
}
// ...
}Here, we added "vitest/importMeta" to the types array to include the necessary typings for import.meta.vitest. This ensures that TypeScript recognizes the import.meta.vitest syntax in your code.
With this in place, we can now write In-Source tests in our source files.
Step 3: Write a Simple Function with In-Source Tests
Let’s start with a simple function that adds two numbers. We’ll write this function in TypeScript and add an In-Source test using the if (import.meta.vitest) block.
export function sum(a: number, b: number): number {
return a + b;
}
if (import.meta.vitest) {
const { it, expect } = import.meta.vitest;
it("sum", () => {
expect(sum(2, 3)).toBe(5);
expect(sum(-1, 1)).toBe(0);
});
}Running vitest will now automatically discover this In-Source test and execute it.
Step 3: Write a More Complex Function with In-Source Tests
Now let’s create a more complex example: a function that filters an array of numbers, returning only the even numbers.
export function filterEvenNumbers(numbers: number[]): number[] {
return numbers.filter((n) => n % 2 === 0);
}
if (import.meta.vitest) {
const { it, expect } = import.meta.vitest;
it("filterEvenNumbers", () => {
expect(filterEvenNumbers([1, 2, 3, 4, 5])).toEqual([2, 4]);
expect(filterEvenNumbers([10, 15, 20])).toEqual([10, 20]);
expect(filterEvenNumbers([])).toEqual([]);
});
}- The
filterEvenNumbersfunction returns only even numbers from the input array. - In-Source tests ensure the function behaves as expected in different scenarios: with mixed numbers, all even numbers, and an empty array.
Step 4: Run Your In-Source Tests
Once you have written your functions and In-Source tests, it’s time to run them. To execute Vitest, just run npx vitest:
❯ npx vitest
DEV v2.1.1 /home/projects/vitejs-vite-prrkah
✓ src/filterEvenNumbers.ts (1)
✓ src/sum.ts (1)
Test Files 2 passed (2)
Tests 2 passed (2)
Start at 20:04:34
Duration 1.35s (transform 82ms, setup 0ms, ...)
PASS Waiting for file changes...
press h to show help, press q to quitVitest will automatically pick up the In-Source tests embedded within your files, thanks to the import.meta.vitest syntax.
Example Sandbox
You can find the example code in this StackBlitz Repo.
Have a look at the filterEvenNumbers.ts file, the vitest.config.ts and the tsconfig.json to see how the setup works.
Conclusion
Using if (import.meta.vitest) is a powerful and convenient way to write In-Source tests in your frontend projects, keeping your code and tests in the same file. This approach simplifies the development process, especially for isolated functions where you don’t want to create yet another file. In this post, we covered how to set up Vitest, write In-Source tests for two functions, and run them.
By following these best practices, you can ensure that your code is thoroughly tested and maintainable. Feel free to leave comments if you have questions or if you’d like to share your experience with In-Source testing!