$npx -y skills add rstackjs/agent-skills --skill rstest-best-practicesRstest best practices for config, CLI workflow, test writing, mocking, snapshot testing, DOM testing, coverage, multi-project setup, CI integration, performance and debugging. Use when writing, reviewing, or troubleshooting Rstest test projects.
| 1 | # Rstest Best Practices |
| 2 | |
| 3 | Apply these rules when writing or reviewing Rstest test projects. |
| 4 | |
| 5 | ## Configuration |
| 6 | |
| 7 | - Use `rstest.config.ts` and `defineConfig` from `@rstest/core` |
| 8 | - Prefer explicit imports `import { test, expect, describe } from '@rstest/core'` over `globals: true` |
| 9 | - For Rsbuild projects, use `@rstest/adapter-rsbuild` with `extends: withRsbuildConfig()` to reuse build config |
| 10 | - For Rslib projects, use `@rstest/adapter-rslib` with `extends: withRslibConfig()` to reuse build config |
| 11 | - Use `setupFiles` for shared test setup (e.g., custom matchers, cleanup hooks) |
| 12 | - When using Rsbuild plugins (e.g., `@rsbuild/plugin-react`), add them via the `plugins` field |
| 13 | - For deep-level or advanced build configuration needs, use `tools.rspack` or `tools.bundlerChain` |
| 14 | |
| 15 | ## CLI |
| 16 | |
| 17 | - Use `rstest` or `rstest run` to run tests (`run` disables watch mode, suitable for CI) |
| 18 | - Use `rstest --watch` or `rstest watch` for local development with file watching |
| 19 | - Use `rstest list` to list all test files and test names |
| 20 | - Use `rstest -u` to update snapshots |
| 21 | - Use `--reporter=verbose` when debugging test failures for detailed output |
| 22 | - Use `--config` (`-c`) to specify a custom config file path |
| 23 | |
| 24 | ## Test writing |
| 25 | |
| 26 | - Import test APIs from `@rstest/core`: `test`, `describe`, `expect`, `beforeEach`, `afterEach`, etc. |
| 27 | - Use `test` or `it` for test cases; use `describe` for grouping related tests |
| 28 | - Use `.only` to focus on specific tests during development, but never commit `.only` to the codebase |
| 29 | - Use `.skip` or `.todo` to mark incomplete or temporarily skipped tests |
| 30 | - Prefer small, focused test cases that test a single behavior |
| 31 | - For async error paths, prefer `await expect(fn()).rejects.toThrow(ErrorClass)` (or `.rejects.toMatchObject({ ... })`) over `try/catch` with `expect.fail` or `.catch(e => e)` patterns — the matcher form fails clearly if the promise unexpectedly resolves, keeps the assertion in one chain, and avoids forgetting to assert the throw at all |
| 32 | - For async happy paths, use `await expect(fn()).resolves.toEqual(...)` for the same reason |
| 33 | - Use `includeSource` for in-source testing of small utility functions (Rust-style `import.meta.rstest`) |
| 34 | - For in-source tests, wrap test code in `if (import.meta.rstest) { ... }` and define `import.meta.rstest` as `false` in production build config |
| 35 | |
| 36 | ## Test environment |
| 37 | |
| 38 | - Use `testEnvironment: 'node'` (default) for Node.js / server-side code |
| 39 | - Use `testEnvironment: 'jsdom'` or `testEnvironment: 'happy-dom'` for DOM / browser API testing |
| 40 | - Install `jsdom` or `happy-dom` as a dev dependency when using DOM environments |
| 41 | - Prefer `happy-dom` for faster DOM testing; use `jsdom` when better browser API compatibility is needed |
| 42 | - For real browser testing, use `@rstest/browser` with Playwright |
| 43 | - Use inline project configs to run different test environments within one project (e.g., `node` and `jsdom` projects) |
| 44 | |
| 45 | ## React / Vue testing |
| 46 | |
| 47 | - For React: use `@rsbuild/plugin-react` plugin and `@testing-library/react` for component testing |
| 48 | - For Vue: use `@rsbuild/plugin-vue` plugin and `@testing-library/vue` for component testing |
| 49 | - Create a `rstest.setup.ts` with `expect.extend(jestDomMatchers)` and `afterEach(() => cleanup())` for Testing Library |
| 50 | - Add the setup file to `setupFiles` in config |
| 51 | - For SSR testing, use `testEnvironment: 'node'` and test with `react-dom/server` or framework-specific SSR APIs |
| 52 | |
| 53 | ## Mocking |
| 54 | |
| 55 | - Use `rs.mock('./module')` to mock modules |
| 56 | - Use `rs.fn()` to create mock functions |
| 57 | - Use `rs.spyOn(object, 'method')` to spy on methods |
| 58 | - Prefer `clearMocks`, `resetMocks`, or `restoreMocks` config options to automatically clean up mocks between tests |
| 59 | - Use factory functions in `rs.mock('./module', () => ({ ... }))` to provide mock implementations |
| 60 | |
| 61 | ## Snapshot testing |
| 62 | |
| 63 | - Use `toMatchSnapshot()` for general snapshot testing |
| 64 | - Use `toMatchInlineSnapshot()` for small, readable inline snapshots |
| 65 | - Use `toMatchFileSnapshot()` for large or structured outputs (e.g., HTML, generated code) |
| 66 | - Keep snapshots concise — only include relevant data, avoid timestamps and session IDs |
| 67 | - Use `expect.addSnapshotSerializer()` to mask paths or sensitive data in snapshots |
| 68 | - Use `path-serializer` to normalize file paths across platforms |
| 69 | - Review snapshot changes carefully in code review |
| 70 | |
| 71 | ## Coverage |
| 72 | |
| 73 | - Enable coverage with `--coverage` CLI flag or `coverage.enabled: true` in config |
| 74 | - Install `@rstest/coverage-istanbul` for the Istanbul coverage provider |
| 75 | - Use `coverage.include` to specify source files for coverage (e.g., `['src/**/*.{js,ts,tsx}']`) |
| 76 | - Use `coverage.thresholds` to enforce minimum coverage requirements |
| 77 | - Use `coverage.reporters` to generate reports in different formats (e.g., `text`, `lcov`, `html`) |
| 78 | |
| 79 | ## Multi-project t |