DEV Community

Cover image for Testing w/ Vitest w/o Vite
colin-williams-dev
colin-williams-dev

Posted on

Testing w/ Vitest w/o Vite

Vitest is an ultra fast and lightweight Unit Test Framework that extends the Jest API. Because of this, it is has a super intuitive set up and familiar syntax. In the following blog I will show you how to get it up and running in a project that isn't even using the Vite bundler! I know a lot of us know and love webpack, so if you're like me (and have already dedicated a hundred hours to learning how to use webpack...) and you don't necessarily want to jump ships to a different bundler, but, you do want to use something more modern than Jest for your testing; than this blog should be helpful in explaining how to do so. Let's get started:

Along with the qualities I mentioned above, the fast and lightweight aspects of Vitest, there are other reasons we will enjoy using Vitest. A couple of these reasons are the following: The first, and my favorite, is its out-of-the-box compatibility with ES6, JSX and TypeScript; and it's easily configurable reporting and watching. I will touch on the latter of those two a bit later.

SETUP

If you are using Vite, this part will truly be a breeze. If you are using npm simply run this command in your terminal:



npm install -D vitest


Enter fullscreen mode Exit fullscreen mode

If you are using Vite then you will already have a vite.config.ts file and Vitest will use that configuration file to execute alias configuration, as well as, whatever plugins are needed. This will happen automatically with installation. However, and this is what we will mostly focus on, if you are using a different bundler than you will want to create a vitest.config.ts file that we will configure if we need specific changes to be made to our testing framework. If you happen to be using Vite and you create a vitest.config.ts file it will take priority over the vite.config.ts file. Either way, for developers using webpack or rollup or something other than Vite we will be creating a file that looks like this:



// vitest.config.ts
import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    globals: true, // <-- **
    coverage: {
      reporter: ['text', 'html'], // <-- ***
  },
});


Enter fullscreen mode Exit fullscreen mode

** --> This line will allow us to use the methods from the Vitest library without specifically importing which ones we need (for those who are familiar with Jest if will behave similarly this way).
*** --> This coverage object and the reporter array is where we can pass values to influence how the tests display their responses. In this case, I have set the reporter to return and html file which we can access with our method of choice in our browser. This will make a very human readably interface that is good for teams or collaborator who want to share testing.

Next, we head over to our package.json to add our script:



// package.json
/*...*/
"scripts": {
   "start": ...,
   "build": ...,
   "test": "vitest --coverage" // <-- **
   },
/*...*/


Enter fullscreen mode Exit fullscreen mode

** --> This --coverage flag enables our modifications from our config file to be applied.

With that script created we can simply enter npm run test to fire our tests. The --watch flag you may be familiar with is applied to Vitest by default so we don't have to include it in our script.

TESTING

With that simple set up complete we can now write and execute some tests! I will include a couple example tests and you will notice how familiar they look. But, first, we need some code to test. Here is an example file called: sum.ts



// sum.ts
export default function sum(...numbers: number[]) {
  return numbers.reduce((acc, cur) => acc + cur, 0);
};


Enter fullscreen mode Exit fullscreen mode

It is a extremely simple function that is just a reducer. It will work for our purposes as I can pass 1 in instead of 0 to make the test behave differently than our tests would expect if I want to see a what a failing test looks like.

Now that we have some code, let's write some tests!



import sum from './sum';
import { describe, expect, it } from 'vitest'; // <-- **

describe('#sum', () => {
  it('returns 0 with no numbers input', () => {
    expect(sum()).toBe(0);
  });

  it('returns same number with one number input', () => {
    expect(sum(2)).toBe(2);
  });

  it('returns sum with nultiple numbers input', () => {
    expect(sum(1, 2, 3)).toBe(6);
  });
});


Enter fullscreen mode Exit fullscreen mode

** --> we do not need this line if we pass the globals: true property to our vitest.config.ts file like we did above, but this is the best practice as it exposes intention and explicit usage.

You probably recognize this syntax as it is largely the same as Jest and designed to be human-readable. The test-naming convention is to put a hasthag # in front of the string that represents the name of the function we are testing, in this case: '#sum'. Following that, we pass a callback as our second argument. This callback will contain the it invocation which takes a string which describes what we will expect and another callback. Inside the it callback we invoke our imported expect method and the toBe method which is available without explicit importing. expect takes what we want to test as an argument, in this case an invocation of our sum() function with a given argument. Then, toBe() gets invoked and is passed what we want to see as the result of our tested function. We can then run our test script and see if our function behaves appropriately!

Passing Vitest Tests

If you don't already have c8 installed running our Vitest script with the coverage options we added will prompt you to do so. Once you have it installed we will see these results (the bottom added by the "text" value added and coverage directory added to our root containing the aforementioned index.html coverage file for serving.

As I mentioned above, if I change the 0 to a 1 in my sum function my tests will fail and this is what it will look like:

Vitest Failing Tests

As you can see, the results are clear and easy to comprehend and with a blistering fast response of 21ms and 30ms it is really a clear successor to its ancient testing framework associates. So, with this information under your belt, go give Vitest a try! I have found it very intuitive and rewarding to integrate into my projects. Happy coding!

Top comments (0)