Time saved

Every run says how much test time it saved. The numbers stay in your CI, so adding them up over a month is a few lines of script, not a dashboard you have to trust.

On every run

A coverage map records how long each test class took. Before running anything, TestDetta adds up the recorded time of the whole suite and of the classes it selected:

Recorded test time: 0.6 s of 3.4 s (83% saved).

The same line is in the GitHub job summary, and in the Markdown that --summary-file writes for other CI systems. It counts test time only. Building and restoring happen either way, except for test projects that are skipped entirely: those are not built at all, which saves more than the line shows.

Projects without timings, for example because no map was recorded for them yet, are left out of both numbers; the JSON lists them in projectsWithoutTimings.

In JSON

td affected --format json carries the same numbers for scripts, for the whole run and for each test project:

{
  "estimate": {
    "fullSeconds": 3.4,
    "selectedSeconds": 0.6,
    "savedSeconds": 2.8,
    "projectsWithoutTimings": []
  }
}

Adding it up

Keep the JSON of every pull request run as a build artifact. Summing savedSeconds over any period gives the test time saved, with nothing leaving your CI:

td affected --format json > testdetta.json      # in each pull request run

# later, over the files of a month:
jq -s 'map(.estimate.savedSeconds // 0) | add / 3600' runs/*.json   # hours saved

Multiply by the number of parallel jobs that run the tests (an OS or framework matrix) for runner minutes, and by your runner's price per minute for cost. The savings calculator does the same with estimates.

What the numbers mean