Rstest Roadmap
Rstest now supports core testing scenarios including Node / DOM testing, mocking, multi-project testing, and coverage collection, and has been successfully implemented in Rstack projects (including Rsbuild, Rslib, Rspack, and others).
The project is currently in active development, and we will continue to refine functionality and enhance the user experience based on community feedback.
Rstest features track
Basic Features
- [x] Expect API (Jest Compatible)
- [x] Lifecycle hooks (beforeAll、beforeEach、afterAll, etc.)
- [x] Setup files
- [x] Snapshot testing (Jest Compatible)
- [x] Source map
- [x] Test API (describe、test、only、each, etc.)
- [x] In-source testing
- [x] Default Reporter
- [x] Out-of-the-box TypeScript / JSX support
- [x] CLI
- [x] rstest run
- [x] rstest watch
- [x] rstest list
- [x] Spy & Rstest utility (
rstest.spyOn、rstest.fn, etc.) - [x] Mocking
- [x] mock
- [x] doMock
- [x] unmock
- [x] importMock
- [x] importActual
- [x] resetModules
- [x] hoist
- [x] Config
- [x] Test configuration support, such as
include,pool,setupFiles, etc. - [x] Build configuration support, such as
resolve,transform,external, etc (based on rsbuild).
- [x] Test configuration support, such as
- [x] API Documentation
- [ ] Auto Mock
- [ ] Pool & isolated
- [x] forks
- [ ] vmForks
- [ ] threads
- [ ] vmThreads
- [ ] Environment
- [x] node
- [x] jsdom
- [x] happy-dom
- [ ] custom environment
- [ ] ESM support 🚧
- [x] Watch mode
- [x] CLI shortcuts
- [ ] Coverage
- [ ] v8
- [x] istanbul
- [ ] Integration
- [ ] Out-of-the-box Rsbuild testing support
- [ ] Out-of-the-box Rslib testing support
- [ ] Out-of-the-box Rspack testing support
Advanced Features
- [x] Projects
- [ ] Out-of-the-box Lynx testing support
- [ ] Rsdoctor integration
- [ ] More builtin reporters & Stablize Reporter API
- [ ] HTML Reporter
- [ ] JSON Reporter
- [x] GitHub Actions Reporter
- [ ] Summary Reporter
- [x] JUnit Reporter
- [ ] Custom Reporter
- [ ] Rstest UI (Provide UI to view and interact with tests)
- [ ] VS Code extension 🚧
- [ ] Test Sharding & merge reports
- [ ] Support filter tests via related source files
Further Features
- [ ] Browser Mode
- [ ] Benchmark testing
- [ ] Type testing
- [ ] AI Exploration
Hello there. One of the biggest issues of Jest is that it reads all the necessary modules for each test but does not cache them during runtime.
In front-end development most of these modules are the same. So you end up reading for each test thousands of files again and again.
A simple React component without 3rd party libs, need around 800 module files. However a React component that imports a component library, and icon library, a state management library etc can easily peak at more than 5k module files during tests because a lot of these 3rd party libraries are barreled. Now imagine you if you got 200 different React components where each needs about 5k files and you want to run all the tests you need to hit the disk 200 * 5_000 = 1_000_000 times.
On a decent personal laptop that's not really a problem.
However in a restricted enterprise environment where you have a cheap enterprise U series low powered laptop and you are forced to use windows with limited permissions, have bit-locker enabled which degrades SSD performance, security software monitoring the background and an aggressive windows defender that thinks that the node process is a ransomware because it reads thousands of files really fast it gets unbearable. Note that even requesting access for WSL can be denied since you aren't messing with docker and microsevices if your role is front-end dev only and having a folder scan exclusion and node process scan exclusion from the windows defender is a big no from the IT security guys for security reasons (I don't disagree with the window defender part).
I started experimenting with modifying Jest source code and added high precision timers in the function that did readFileSync from the disk. I observed that reading for example 5k node module files alone could take 135 secs which is insane to me and can lead to execution times of 3 minutes for a single test file since jest loads reads other files from the file system before that like jsdom related files, package json files and also it needs to spin up an isolated VM for running the test etc.
-
My proposal is to cache and share the node modules during runtime. This can avoid I/O bottleneck especially in the type of environment I described above.
-
My second proposal is a bit crazy but it can dramatically improve performance in I/O starved environments. Create a disk based module pool. Instead of reading a module file at a time, add it after the tests finish to a file pool in the disk.
module-pool.json
[
{
"file_path": "C:\\...\\file.js",
"content": "<<content_of_file>>",
"last_modified": "<<time_stamp>>",
"last_accessed": "<<time_stamp>>"
},
{
"file_path": "C:\\...\\file2.js",
"content": "<<content_of_file>>",
"last_modified": "<<time_stamp>>",
"last_accessed": "<<time_stamp>>"
}
// ... more entries
]
The last_modified contains the last time the file was modified in the file system. The last_accessed contains the last time a test needed the specific module.
The last_modified can help us invalidate the content of the file if it was updated and the last_accessed can help us determine if the file has to be requested for a long time (user could provide an option to discard modules from the pool if they haven't been used for example 2 months during the test runs).
Since CI/CD can be tricky to determine last_modified (node_modules dependencies are reinstalled on each CI/CD unless you can retain somehow the old modules after each pipeline execution, I am not sure if it is worth it and what kind of ) this second proposal could be under a config value like "localDevelopmentEnvironmentModulePool": true/false and only be used during local development.
I am looking forward to hear your feedback.
@Ghostblad3 Thank you for your suggestion. Currently, when rstest executes a test file, it has module caching to prevent redundant file loading.
However, between different test files, there is no caching for module loads due to test isolation. Fortunately, if a package is not marked as external, it will be bundled by rspack (also known as transform), and its file content will be loaded into memory, preventing redundant disk reads.
As for long-term caching optimizations, rspack's Persistent Cache may be supported in rstest in the future.
@9aoy Thank you! Could you elaborate why modules should not be shared between tests due to isolation? Modules are static, they never change. If X components uses a Material UI button I don't see a problem for the modules required by the button to be shared between the tests. Sharing them dramatically improved performance.
@Ghostblad3 Rstest runs every test file isolated by default. If your project has no side effects, you can set isolate: false to turn off isolation to optimize performance (There will be some errors that do not meet expectations, and we will fix them ASAP).
@9aoy Does isolate: true will cache all modules loaded for each test so that they are not re-read from disk after a test finish and another one start?
Does
isolate: truewill cache all modules loaded for each test so that they are not re-read from disk after a test finish and another one start?
When isolate: false is enabled and tests are within the same pool, module loading will be cached.
Loving the suite.
Assuming the vi.mock type apis haven't been implemented yet right? ie. no matter what variants I try, they take no effect...
rstest.mock("../src/import/remote", () => ({
getRemoteService: () => mockRemoteService,
}));
...
const module = { someExport: "value" };
rstest.mock("@module-federation/enhanced/runtime", () => ({
loadRemote: rstest.fn().mockResolvedValue(module),
}));
I just noticed a branch called fix_mock, with plugin tweaks... might explain it.
I just noticed a branch called fix_mock, with plugin tweaks... might explain it.
Oh, rstest as a alias of rs (or vice versa), is not merged into latest version now. You could use rs as of now.
Hi, I'm the author of CanyonJS, an end-to-end coverage collection platform designed for frameworks like Playwright. It works by using babel-plugin-istanbul to instrument code at the AST level and collects coverage data at runtime.
Internally, we've extended this plugin to support advanced features like hit/map separation, allowing us to reduce bundle size and make coverage collection more production-friendly.
I'd love to contribute to the rstest project, specifically around its coverage functionality. I'm particularly interested in building a custom coverage provider similar to @rstest/coverage-istanbul or @rstest/coverage-v8, with support for code instrumentation and coverage report generation during test execution.
I'm currently working on a minimal runnable demo and plan to share it before July 25.
Please let me know if you're open to contributions in this area—I'd be happy to help push coverage support forward in rstest. Thanks!
@travzhang Thanks for the sharing, Rstest's coverage ability is still under development, and the provider mechanism is not implemented as of now. We had planned to implementation it within this month or next.
Implementation coverage core functionality will be a rather bigger task, if you're interested in implementing it, please come up a RFC or issue to demonstrate the API design before start development.
Implementation CanyonJS' plugin after the coverage provider system implementing is sure feasible and welcomed. We'd love to help if you encounter any issue.
By the way, I'm interested in how you will integrate CanyouJS with Rstest? I only saw the recipes with Next/Vite/Lynx/RN, which are all app frameworks instead of testing framework.
https://github.com/web-infra-dev/rstest/issues/398
@fi3ework Regarding CanyonJS, its main focus is on large-scale UI automation testing scenarios — for example, Playwright or RN and Lynx, where there are massive JS bundles and a huge volume of test cases. In these cases, coverage collection uses a hit/map separation approach, and also separates these during the pipeline build stage. This effectively reduces the instrumentation size and the payload size during reporting. As for potential cooperation with Rstest, what we currently foresee is integration similar to the canyon-reporter — for instance, uploading the coverage-final.json file generated during Rstest's CI coverage phase to a platform like app.canyonjs.org, enabling coverage report browsing. Looking forward to further collaboration as rstest coverage features evolve.
Any plans to have built-in generic JUnit reporter? Or is that a subset of "GitHub Actions Reporter" task? Thanks!
Any plans to have built-in generic JUnit reporter? Or is that a subset of "GitHub Actions Reporter" task? Thanks!
@slobo it will be built-in. I have updated the roadmap to include it.
@fi3ework Do you have any plans to replace storybook vitest addon?
Hi! First of all, very excited for this. We have several requirements in our repos that leverage Jest-only features (specifically, isolateModules) that makes it impossible for us to easily switch to Vitest. For the ESM support, will that involve transpiling to CJS first automatically or will it use native mechanisms like Vitest uses?
Do you have any plans to replace storybook vitest addon?
@yf-yang Some features, such as browser mode, are not yet supported in Rstest. Once these functionalities are available, we would be happy to provide @storybook/addon-rstest.
We have several requirements in our repos that leverage Jest-only features (specifically, isolateModules) that makes it impossible for us to easily switch to Vitest.
@sgarfinkel isolateModules is not yet supported in Rstest, and there are still many features related to mocking modules that need to be implemented.
For the ESM support, will that involve transpiling to CJS first automatically or will it use native mechanisms like Vitest uses?
Currently, it involves transpiling to CJS. In the future, we will consider using ESM output directly.