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-dev

Once 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:

vitest.config.ts
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:

tsconfig.json
{
  "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.

sum.ts
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.

filterEvenNumbers.ts
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 filterEvenNumbers function 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 quit

Vitest 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!


Related Posts

Find posts on similar topics:


Support me via buymeacoffee

If I helped you solve a problem or you just like my content, consider supporting me by buying me a coffee.

Buy me a coffee

Comments