I prefer using bun:test [1] where possible, super fast to run, all built-in no need to install any packages, supports watch mode, also TypeScript tests just works out of the box without additional deps or steps. You'll also get all the benefits of bun which is a breath of fresh air over npm.
If your JS tests are dependent on specifics in JavaScriptCore or V8 are you really writing unit tests?
If you want the extra confidence, run it with bun:test and node:test to cover JSC and V8. But JS should be JS and for unit tests feeling a need to test on multiple JS engines is a possible code smell.
It's my preferred js runtime for developing/testing *any* new TypeScript/JS libs since I prefer writing JS libraries with TypeScript and Bun had the best UX for running TS out of the box (also big fan of their built-in SQLite and $ shell support). It only doesn't make sense if you're testing a library requiring node, otherwise it's my preferred choice for testing my js libs.
Even when testing libraries requiring node in which case I'll run the tests with node:test but still use bun's built-in bundler [1] to build & bundle the typescript code base.
Basically Bun's my first choice, but will still use node if I have to.
We switched from Jest to Vitest this summer as part of the effort to migrate a large node repository to ESM. Jest presented a lot of issues after switching to ESM. Vitest was compatible with our existing jest code, minus a couple altered method signatures. It was also compatible with custom matchers we had implemented with jest-extend.
Most of the migration effort was spent on configuration for our needs. Vitest is quite flexible so it was just a matter of nailing down what worked for us.
Im interested if anyone has experience using node's native test runner in a non-trivial project?
We are not using the module mocks from Jest in our project and a quick PoC showed significant (3x) speed improvement, but i am worried about the battle-tested:ness.
I've been very happy with node:test (and deno:test), but also I migrated from mostly mocha as jest I found difficult to configure, especially without unnecessary bundling configurations as the ESM support among other things was broken for far too long (but mocha delivered it well). Most of my successful uses of jest were out-of-the-box configs in create-react-app and the Angular tools to strip uses of karma and replace them with jest. (Side rant: Seriously whoever thought that karma was a good idea for a test runner? "I love V8 so much I'm using Node's V8 to spin up another headless Chromium's V8 so I can V8 from inside V8." lolsob)
Yes we're using the built-in test runner and it's much better than jest.
Jest is full of unneeded magic (= complexity), whereas node:test is straightforward and has a better design. Highly recommended. You can turn off process isolation for extra speedup!
Without process isolation we got 6x speedup vs. jest! But it is difficult to ensure a clean slate between our test suites (~40 suites which all use a test DB)
And while Vitest' coverage is stable, I had to add an indirection layer to change how I mock out calls to GitHub's API (@github/octokit).
Oh, side note: vite-node's --watch functionality does not restart the process. It does hot reloading which is different enough that it requires some rework at how you set up your app structure and callbacks.
The problem is jest is run by megacorp Meta, so it won't be fixed in any reasonable timeframe because they're all about new features to make "impact". Its FOSS contributors are typically slow and working primarily to keep their jobs. Also, with node > 20.9.0 being broken and node = 20.9.0 not being a viable option by being insecure, so it's worth having a look at alternatives like bun or deno because it does seem to have lost its way too. I'm currently pinned to 20.9.0 for system dependencies, but use bun for new dev.
What is meant by “interactive snapshot testing”? If this is the ability to generate and update snapshots in watch mode, Vitest supports this, even though the feature matrix in the article indicates that it does not. I know because I used this feature last month.
I prefer using bun:test [1] where possible, super fast to run, all built-in no need to install any packages, supports watch mode, also TypeScript tests just works out of the box without additional deps or steps. You'll also get all the benefits of bun which is a breath of fresh air over npm.
[1] https://bun.sh/docs/cli/test
Yes, same with node:test https://nodejs.org/api/test.html
It's an excellent test runner and much, much faster than the others, especially if you set the "isolation" flag to "none".
Testing with Bun would only make sense if you're running it with Bun (or targeting Safari), right?
If your JS tests are dependent on specifics in JavaScriptCore or V8 are you really writing unit tests?
If you want the extra confidence, run it with bun:test and node:test to cover JSC and V8. But JS should be JS and for unit tests feeling a need to test on multiple JS engines is a possible code smell.
It's my preferred js runtime for developing/testing *any* new TypeScript/JS libs since I prefer writing JS libraries with TypeScript and Bun had the best UX for running TS out of the box (also big fan of their built-in SQLite and $ shell support). It only doesn't make sense if you're testing a library requiring node, otherwise it's my preferred choice for testing my js libs.
Even when testing libraries requiring node in which case I'll run the tests with node:test but still use bun's built-in bundler [1] to build & bundle the typescript code base.
Basically Bun's my first choice, but will still use node if I have to.
[1] https://bun.sh/docs/bundler
We switched from Jest to Vitest this summer as part of the effort to migrate a large node repository to ESM. Jest presented a lot of issues after switching to ESM. Vitest was compatible with our existing jest code, minus a couple altered method signatures. It was also compatible with custom matchers we had implemented with jest-extend.
Most of the migration effort was spent on configuration for our needs. Vitest is quite flexible so it was just a matter of nailing down what worked for us.
Im interested if anyone has experience using node's native test runner in a non-trivial project?
We are not using the module mocks from Jest in our project and a quick PoC showed significant (3x) speed improvement, but i am worried about the battle-tested:ness.
I've been very happy with node:test (and deno:test), but also I migrated from mostly mocha as jest I found difficult to configure, especially without unnecessary bundling configurations as the ESM support among other things was broken for far too long (but mocha delivered it well). Most of my successful uses of jest were out-of-the-box configs in create-react-app and the Angular tools to strip uses of karma and replace them with jest. (Side rant: Seriously whoever thought that karma was a good idea for a test runner? "I love V8 so much I'm using Node's V8 to spin up another headless Chromium's V8 so I can V8 from inside V8." lolsob)
I just started to use nodejs test runner in a new project. All configuration is basically:
node --experimental-transform-types --experimental-test-module-mocks --env-file test/test.env --test
It then automatically runs all my test/*.tests.ts files.
So nice to get rid of all that extra config. As this is still a tiny project, I can tolerate some API changes in these experimental features.
Yes we're using the built-in test runner and it's much better than jest.
Jest is full of unneeded magic (= complexity), whereas node:test is straightforward and has a better design. Highly recommended. You can turn off process isolation for extra speedup!
How large is your project?
Without process isolation we got 6x speedup vs. jest! But it is difficult to ensure a clean slate between our test suites (~40 suites which all use a test DB)
We are also using some helpers to mock, e.g https://github.com/marchaos/jest-mock-extended - its such helper libraries im concerned about.
Vitest does not support CommonJS mocking as of today.
I switched to Vitest because Jest was giving me flaky coverage results: https://github.com/nodejs/node/issues/51251
And while Vitest' coverage is stable, I had to add an indirection layer to change how I mock out calls to GitHub's API (@github/octokit).
Oh, side note: vite-node's --watch functionality does not restart the process. It does hot reloading which is different enough that it requires some rework at how you set up your app structure and callbacks.
The problem is jest is run by megacorp Meta, so it won't be fixed in any reasonable timeframe because they're all about new features to make "impact". Its FOSS contributors are typically slow and working primarily to keep their jobs. Also, with node > 20.9.0 being broken and node = 20.9.0 not being a viable option by being insecure, so it's worth having a look at alternatives like bun or deno because it does seem to have lost its way too. I'm currently pinned to 20.9.0 for system dependencies, but use bun for new dev.
As described in the article, Jest is no longer run by Meta and its primary maintainers don’t work there.
I also would argue Jest development slowed down after Meta transferred the project to OpenJS, so…
I just recently did a website conversion that used vite and took a look at both vitest and playwright.
Ended up going with playwright for the “batteries included” browser support and because we use .Net Core for the backend.
dotnet doesn’t always get the best support from pure JS/TS projects, so it seemed like a reasonable hedge.
What is meant by “interactive snapshot testing”? If this is the ability to generate and update snapshots in watch mode, Vitest supports this, even though the feature matrix in the article indicates that it does not. I know because I used this feature last month.
Hi, I work at Speakeasy. Thanks for this. I'll look into this and correct the post. Thanks :)
Good write up that helps you get started if you haven't used either lib.
It’s fair to say I will never use Jest again where possible, instead preferring vitest