> ## Documentation Index
> Fetch the complete documentation index at: https://docs.blacksmith.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Vitest Test Selection

> Blacksmith runs only the Vitest tests a change can affect

## Overview

Every CI run of a Vitest suite starts from zero and runs every test, even when a change only touches a few files. The `@useblacksmith/vitest` plugin uses dependency tracking to run only the tests affected since the last successful run. It is one plugin in `vitest.config.ts`, with no workflow change.

> [!NOTE]
>
> The plugin is in early beta. Options and the cache format may change between releases.

## How it works

Each run records the modules and files every test depends on, through `import`, `require`, and `fs`. The next run compares the checkout against that record and runs only the tests that reach a changed file. A test the last successful run did not cover always runs, and a lockfile change runs everything.

On Blacksmith runners, Blacksmith transparently stores this record from run to run, with no extra workflow steps.

## Install the plugin

The plugin requires Vitest 5.1 or newer.

```sh theme={"system"}
npm install --save-dev @useblacksmith/vitest
```

```ts theme={"system"}
// vitest.config.ts
import { defineConfig } from 'vitest/config'
import blacksmith from '@useblacksmith/vitest'

export default defineConfig({
  plugins: [blacksmith()],
})
```

`vitest run` now runs the affected selection. `--shard=i/n` works as before, and a file stays in its shard as others are added or removed.

Add the @useblacksmith/vitest plugin to the Vitest config in \<repository name> with shadow: true and open a PR. After a few CI runs, tell me how many tests the selection would have skipped.

You get back: A PR adding the plugin, and a report of the tests it would have skipped once a few CI runs are in.

Try it in \[code]smith

### Vite+

Vite+ runs Vitest under `vp test`, so the plugin is loaded from the shared `vite.config.ts`. It requires `vite-plus` 1.5.0 or newer, the first release that ships Vitest 5.1.

```ts theme={"system"}
// vite.config.ts
import 'vite-plus/test/config'
import { defineConfig } from 'vite-plus'
import blacksmith from '@useblacksmith/vitest'

export default defineConfig({
  plugins: [blacksmith()],
})
```

### Running locally

The same selection applies locally: a run reruns what changed on disk since the last successful run, committed or not. To run every test locally and select only in CI:

```ts theme={"system"}
plugins: [blacksmith({ runAllTests: !process.env.CI })],
```

## Evaluate before relying on it

`shadow` runs every test and logs what the selection would have run, and which failing test files it would have skipped. It needs a cached record, so it reports only on Blacksmith runners. Run it for a few days to see the savings and confirm the selection misses nothing before turning it on.

```ts theme={"system"}
plugins: [blacksmith({ shadow: true })],
```

## Options

| Option | Default | Effect |
| - | - | - |
| `runAllTests` | `false` | Run every test instead of the affected selection. |
| `shadow` | `false` | Run every test and log what the selection would have skipped. |
| `dependencies` | `{}` | Dependencies the tracking cannot see, as globs of test files mapped to the glob(s) of the files they depend on, relative to the config root: `{ 'tests/**/*.spec.ts': 'fixtures/**' }`. A change to a matching file reruns the mapped tests. |

## Limitations

Only dependencies in the test process are tracked. Files read from a child process, from `globalSetup`, or from outside Node are not; declare them with the `dependencies` option.

A custom sequencer that moves tests between shards across runs reruns each moved test once.

Under Turborepo's strict environment mode, `vitest` cannot see `ACTIONS_RESULTS_URL`, so the record is not shared between runs. Add it to the task's `passThroughEnv` in `turbo.json`.

## Verify the selection

The plugin logs every decision with a `[blacksmith]` prefix in the job output: whether a record was restored, how many files changed since the last successful run, and how many test files run as a result. The first run on a repository has no record and runs everything; compare the test step's duration across later runs.

A run after a change to one source file restores the record, runs only the test file that depends on it, and saves a new record:

```text theme={"system"}
[blacksmith] restored dependency cache blacksmith-vitest-v5-all-1of1-50284a30936f668205db594eb10ef1476f6a4ea3

 RUN  v5.1.0 /home/runner/work/app/app

[blacksmith] 1 files changed since 50284a30936f, 0 test files not covered by it
 ✓ test/pricing.test.js (1 test) 1ms

 Test Files  1 passed (1)
   Affected  1 of 3 test files (related to 1 changed file)
      Tests  1 passed (1)

[blacksmith] saved dependency cache blacksmith-vitest-v5-all-1of1-26520c57cc6a09f83c7c3e83716544c2b461d700 (653 bytes)
```

When no change affects any test, Vitest prints `No changed files found, exiting with code 0` and the step passes.
