$npx -y skills add rstackjs/agent-skills --skill rstest-debuggingDebug Rstest issues systematically, including performance regressions. First determine whether the slowdown is in build startup or test execution, then run controlled config or code experiments and compare before/after timings.
| 1 | # Rstest Debugging Workflow |
| 2 | |
| 3 | Use this skill when Rstest is slower than expected, slower than Jest or Vitest, slower than a previous Rstest baseline, or when users report that tests spend a long time before starting. |
| 4 | |
| 5 | The goal is not to guess a root cause from config names alone. First identify where time is being spent, then change one variable at a time and compare the result. |
| 6 | |
| 7 | ## 1. Establish a reproducible baseline |
| 8 | |
| 9 | Before changing config or code: |
| 10 | |
| 11 | - Pick the narrowest representative command. Prefer a single file, package, or fixture over the whole workspace. |
| 12 | - Record the exact command, working directory, test environment (`node`, `jsdom`, `happy-dom`, browser mode), and relevant worker settings. |
| 13 | - Measure at least one cold run and one warm run with the same command. |
| 14 | - Do not change multiple config fields before the first measurement. |
| 15 | |
| 16 | Common baseline commands: |
| 17 | |
| 18 | ```bash |
| 19 | npx rstest run path/to/test-file.test.ts |
| 20 | npx rstest --reporter=verbose path/to/test-file.test.ts |
| 21 | pnpm rstest path/to/test-file.test.ts |
| 22 | ``` |
| 23 | |
| 24 | If the problem is reported as “there is a long pause before tests even start”, treat that as a build or startup hypothesis until measurements prove otherwise. |
| 25 | |
| 26 | ## 2. Classify the slowdown before optimizing |
| 27 | |
| 28 | Split the investigation into one of these buckets: |
| 29 | |
| 30 | - **Build or startup slow**: there is a long delay before test cases begin, or small reruns still spend most time preparing the graph. |
| 31 | - **Execution slow**: tests start quickly, but one or more files or cases take a long time to finish. |
| 32 | - **Unclear**: a single `Duration` value is not enough to decide. |
| 33 | |
| 34 | Use these tools in order: |
| 35 | |
| 36 | ### Use `--trace` when the time distribution is unclear |
| 37 | |
| 38 | ```bash |
| 39 | npx rstest run --trace |
| 40 | ``` |
| 41 | |
| 42 | `--trace` produces a Perfetto-compatible trace with per-phase, per-suite, and per-case slices. Use it to answer: is the time concentrated in prepare or build phases, or inside test execution? |
| 43 | |
| 44 | ### Use `DEBUG=rstest` for build-stage clues |
| 45 | |
| 46 | ```bash |
| 47 | DEBUG=rstest npx rstest run |
| 48 | ``` |
| 49 | |
| 50 | Focus on: |
| 51 | |
| 52 | - Long build-related log phases |
| 53 | - Large temporary outputs under `dist/.rstest-temp` |
| 54 | - Whether a heavy dependency chain or entry causes most of the startup cost |
| 55 | |
| 56 | ### Use the verbose reporter for execution-stage clues |
| 57 | |
| 58 | ```bash |
| 59 | npx rstest --reporter=verbose |
| 60 | ``` |
| 61 | |
| 62 | Use this to find the slow file, suite, or case before reaching for a profiler. |
| 63 | |
| 64 | ## 3. If build or startup is slow |
| 65 | |
| 66 | For `jsdom` and `happy-dom`, Rstest bundles third-party dependencies by default. That often explains reports like “Rstest is slow before tests even start”. |
| 67 | |
| 68 | Check these first: |
| 69 | |
| 70 | - Whether a test entry pulls in a large UI, editor, charting, or data-processing package |
| 71 | - Whether style imports or asset imports are causing extra graph traversal |
| 72 | - Whether the test only needs a tiny API surface while bundling a much larger dependency tree |
| 73 | |
| 74 | Run one experiment at a time, and rerun the exact same baseline command after each change. |
| 75 | |
| 76 | ### Experiment A: externalize bundled dependencies |
| 77 | |
| 78 | For non-browser mode, try: |
| 79 | |
| 80 | ```ts |
| 81 | import { defineConfig } from '@rstest/core'; |
| 82 | |
| 83 | export default defineConfig({ |
| 84 | testEnvironment: 'jsdom', |
| 85 | output: { |
| 86 | bundleDependencies: false, |
| 87 | }, |
| 88 | }); |
| 89 | ``` |
| 90 | |
| 91 | Compare: |
| 92 | |
| 93 | - Build or startup duration |
| 94 | - `dist/.rstest-temp` size |
| 95 | - Whether the test still behaves correctly |
| 96 | |
| 97 | ### Experiment B: externalize only the heavy packages |
| 98 | |
| 99 | If only a few dependencies dominate the graph, prefer a smaller change: |
| 100 | |
| 101 | ```ts |
| 102 | import { defineConfig } from '@rstest/core'; |
| 103 | |
| 104 | export default defineConfig({ |
| 105 | output: { |
| 106 | externals: ['react', 'lodash'], |
| 107 | }, |
| 108 | }); |
| 109 | ``` |
| 110 | |
| 111 | ### Experiment C: restore explicit style stubs when the test does not need real style processing |
| 112 | |
| 113 | If a previous Jest setup used `moduleNameMapper` to stub CSS or SCSS with `identity-obj-proxy`, compare that behavior explicitly instead of assuming the native Rstest path is equivalent: |
| 114 | |
| 115 | ```ts |
| 116 | import { defineConfig } from '@rstest/core'; |
| 117 | |
| 118 | export default defineConfig({ |
| 119 | tools: { |
| 120 | rspack: (config, { rspack }) => { |
| 121 | config.plugins ??= []; |
| 122 | config.plugins.push( |
| 123 | new rspack.NormalModuleReplacementPlugin( |
| 124 | /\.(css|less|scss)$/, |
| 125 | 'identity-obj-proxy', |
| 126 | ), |
| 127 | ); |
| 128 | }, |
| 129 | }, |
| 130 | }); |
| 131 | ``` |
| 132 | |
| 133 | Only keep this if the tests do not depend on real style behavior and the timing improvement is measurable. |
| 134 | |
| 135 | ### Experiment D: inspect build-time distribution with Rsdoctor |
| 136 | |
| 137 | If startup is still slow and the expensive part is unclear, use Rsdoctor to see whether time is dominated by entries, loaders, plugins, or dependency chains. |
| 138 | |
| 139 | ## 4. If test execution is slow |
| 140 | |
| 141 | Once startup is acceptable and execution remains slow, stop tuning bundling first. Focus on the runtime path. |
| 142 | |
| 143 | Investigate in this order: |
| 144 | |
| 145 | 1. Use the verbose reporter to identify the slow file and slow c |