runCached
uses tcmts.cli.vitest.keysForResults, which uses process
Run tests, reusing cached results. A test's hash covers its code and, through its dependencies, everything
it calls (pinned npm versions included), so a cached result is only stale if the test depends on something
outside the codebase, like the filesystem, the clock, or the network. fresh ignores the cache. A test whose code
reaches files, the environment or other processes is kept for the platform too (keysForResults).
Only passes are reused. A failure can be the environment's or the runner's (a variable a test inherited, a bug in how tcm runs tests), which no key holds, and a failure kept would outlive its fix: a test that failed runs again, and says when it failed last time too with nothing it runs changed since (a fix that didn't save shows as this).
import type { Codebase } from "#codebase/tcmts/cli/codebase"; import type { TestOutcome } from "#codebase/tcmts/cli/testing"; import { keysForResults, runTestsWithVitest } from "#codebase/tcmts/cli/vitest"; import type { DefRecord } from "#codebase/tcmts/core/types"; import type { DefSource } from "#codebase/tcmts/loader"; import type { TestResult } from "#codebase/tcmts/store"; export function runCached( cb: Codebase, items: { path: string; rec: DefRecord }[], src: DefSource, fresh: boolean, ): TestOutcome[] { // results depend on the runtime and the test framework too (and some, the platform) const keys = keysForResults( cb, items.map(({ rec }) => rec.hash), src, ); const cached = new Map<string, TestResult>(); const failedBefore = new Set<string>(); if (!fresh) for (const { rec } of items) { const r = cb.store.testResult(rec.hash, keys.get(rec.hash)!); if (r?.ok) cached.set(rec.hash, r); else if (r) failedBefore.add(rec.hash); } const toRun = [ ...new Map( items.filter(({ rec }) => !cached.has(rec.hash)).map(({ rec }) => [rec.hash, rec]), ).values(), ]; const ran = new Map(runTestsWithVitest(cb, toRun, src).map((r) => [r.hash, r])); // (kept under the keys as they are after running: the first run installs the test framework) const after = ran.size ? keysForResults(cb, ran.keys(), src) : keys; for (const r of ran.values()) if (!r.infrastructure) cb.store.putTestResult(r, after.get(r.hash)!); return items.map(({ path, rec }) => { const result = (cached.get(rec.hash) ?? ran.get(rec.hash))!; return { path, result, cached: cached.has(rec.hash), ...(!result.ok && failedBefore.has(rec.hash) ? { failedBefore: true } : {}), }; }); }
uses
- tcmts.cli.codebase.Codebase
- tcmts.cli.testing.TestOutcome
- tcmts.cli.vitest.keysForResults
- tcmts.cli.vitest.runTestsWithVitest
- tcmts.core.types.DefRecord
- tcmts.loader.DefSource
- tcmts.store.TestResult