mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-02 12:49:56 +00:00
ci(mutants): an unmatched --test-name-pattern is setup-failure, not survived (#650)
A name-filtered `node --test` that matches no test exits 0 and TAP reports only the file itself. The clean run took that for a healthy witness and the mutant run for `survived`, although no assertion ran either time — as in Validate 36151140394 on #649, where a renamed test left a guard pattern empty. - mutation-guard-outcome: nodeTestSelection/executedTestNames/ emptyTestSelection; a green oracle with a name filter and zero executed named tests is `setup-failure` (clean run: «FAIL чистая подготовка», diff mode: attributed like any setup failure, #568). - mutation-gate --check: staticTestSelectionProblems — every pattern must match a literal test(/it(/describe( name in the guard's files; files with ${…} names only warn. POSIX quoting keeps \( inside "…". - Registry today: 349 unique name-filtered commands run on dev, all execute ≥ 1 test; --check: 0 errors, 3 warnings (dynamic names). - Tests: 6 new in test/mutation-guard-outcome.test.mjs (incl. the installed node's real TAP and a registry-wide static check); 3 mutants. - Docs: TESTING.md pointer, testing-notes/infrastructure.md section. Issue: #650 User-Visible: no
This commit is contained in:
@@ -24,7 +24,9 @@ import {
|
||||
} from './mutation-evidence.mjs';
|
||||
import { attributeSetupFailure } from './mutation-attribution.mjs';
|
||||
import { guardEnvironment, planEnvironment, planEnvironmentLines } from './mutation-environment.mjs';
|
||||
import { MUTATION_OUTCOME, isProofOutcome } from './mutation-guard-outcome.mjs';
|
||||
import {
|
||||
MUTATION_OUTCOME, isProofOutcome, staticTestSelectionProblems,
|
||||
} from './mutation-guard-outcome.mjs';
|
||||
|
||||
const repoRoot = fileURLToPath(new URL('..', import.meta.url));
|
||||
|
||||
@@ -151,6 +153,11 @@ export async function main(argv) {
|
||||
|
||||
if (argv.includes('--check')) {
|
||||
let stale = 0;
|
||||
let warned = 0;
|
||||
const readTest = (file) => {
|
||||
const path = join(repoRoot, file);
|
||||
return existsSync(path) ? readFileSync(path, 'utf8') : null;
|
||||
};
|
||||
for (const m of selected) {
|
||||
try {
|
||||
// #499: бандл мутанта собирает раннер (`buildBundle`, только rollup +
|
||||
@@ -165,12 +172,21 @@ export async function main(argv) {
|
||||
const hits = source.split(patch.find).length - 1;
|
||||
if (hits !== 1) throw new Error(`якорь найден ${hits} раз(а)`);
|
||||
}
|
||||
// #650: a name filter that matches nothing makes the witness vacuous.
|
||||
const selection = staticTestSelectionProblems(m.guard, readTest);
|
||||
const error = selection.find((problem) => problem.level === 'error');
|
||||
if (error) throw new Error(error.text);
|
||||
for (const problem of selection) {
|
||||
console.log(`WARN ${m.id}: ${problem.text}`);
|
||||
warned++;
|
||||
}
|
||||
console.log(`ok ${m.id}`);
|
||||
} catch (error) {
|
||||
console.log(`FAIL ${m.id}: ${error.message}`);
|
||||
stale++;
|
||||
}
|
||||
}
|
||||
if (warned) console.log(`предупреждений о шаблонах имён: ${warned}`);
|
||||
reportPlanMetrics();
|
||||
return stale ? 2 : 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user