Skip to content
DocsWhich tests run, and why

Graphide CI

Which tests run, and why

How Graphide CI decides which tests a change can reach, when it runs them all, and where each run says why a test was left out.

Each change runs the tests that can reach it. Every test left out is listed with its reason, so you can check the reasoning on any run.

How a change is bounded

The test step runs through gr ci run, Graphide’s test runner, in front of the test command you already use:

gr ci run -- go test ./...

For each change it answers in this order:

  1. From the changed paths alone. When no changed file can affect a test, no test needs to run. When a changed file decides how every test runs, every test runs.
  2. From the graph. Otherwise it asks Graphide’s graph of your code at the change’s base which tests call into what changed, directly or through other code, and runs those. The job signs in with its GitHub Actions token. It sends the changed files’ paths, where in them the changes are, and your tests’ names; no line of your diff leaves the runner.
  3. When the graph cannot be sure, it runs every package whose tests import a changed package, directly or not. A fixture, a lockfile or a change outside any function runs the tests it could touch, whole.
  4. When anything goes wrong, it runs every test and says why.

So when it cannot tell, it runs more, never less.

Which test commands it narrows

gr ci run narrows go test, and vitest, jest and node --test called directly or through npx, pnpm, yarn, npm exec or bunx. Any other command runs as it is, except that the go test, pytest, jest and vitest runs it starts are narrowed too. Tests of any other runner run whole.

A failing test fails the step, as it would in your own CI.

Why a test did not run

Each run lists the tests Graphide left out, and each one’s reason:

Reason Means
Nothing you changed reaches it Nothing that changed reaches the test in the graph.
Its job did not need to run The change reaches none of the job’s tests, so the whole job was turned off for it.
Unchanged since it last passed Nothing the test ran has changed since it last passed.
Already passed on this code A passing result of the same code was reused.

A test that skipped itself, through t.Skip or its runner’s equivalent, is listed apart, in its own words. That was the test’s choice, not Graphide’s.

To see why one test ran or not, in this run and the ones before it:

gr ci why <test>

Read a run has the rest of what a run shows.

How we know it keeps the verdict

On our own CI, over 295,411 test runs our selection left out, 0 would have failed (one-sided 95% bound: 0.001%). Before your jobs move, we check that our run catches every failure your own run catches.

Something wrong or missing? Tell us on Discord or at hello@graphide.com.