Files
cc-1c-skills/tests/skills/expected-skips.mjs
T
Nick ShirokovandClaude Opus 5 26ca7276e6 test(skills): expected-skips.mjs — ожидаемое число пропусков вместо запомненного
«skipped» — норма, а не падение, но само число ни о чём не говорит, пока не с чем сверить,
а запоминать его нельзя: оно растёт с набором кейсов. Прежняя сверка жила в личной памятке
как grep по 'external:|runtimeOnly|osOnly' и уже сломалась — она считает скипом ЛЮБОЙ osOnly,
а posix-кейсы фейка платформы на маке как раз выполняются (grep давал 67 против 59 реальных).

Скрипт повторяет правила гейтинга раннера и живёт рядом с ним, поэтому расходиться им негде.
--list печатает пропуски поимённо с причиной. Сверено: win32/powershell 8, win32/python 11,
darwin/python 59 — совпало с прогонами.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-13 15:55:07 +03:00

64 lines
3.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
// Сколько кейсов ДОЛЖНО быть пропущено на этой ОС и этом порте.
//
// «skipped» в прогоне — норма, а не падение: часть кейсов гейтится по ОС, по порту или по
// наличию внешней выгрузки. Но само число ни о чём не говорит, пока не с чем сверить, а
// запоминать его нельзя — оно растёт с набором кейсов. Отсюда этот скрипт: он считает
// ожидаемое значение по тем же правилам, что и раннер, и его надо сверять с `Skipped: N`.
//
// Совпало — норма. Разошлось — разбираться: появился новый источник скипа либо кейс
// скипается не по той причине, что заявлена.
//
// Запуск: node tests/skills/expected-skips.mjs [--runtime python] [--list]
import { readFileSync, readdirSync, existsSync, statSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';
const HERE = dirname(fileURLToPath(import.meta.url));
const CASES = join(HERE, 'cases');
const argv = process.argv.slice(2);
const runtime = argv.includes('--runtime') ? argv[argv.indexOf('--runtime') + 1] : 'powershell';
const listMode = argv.includes('--list');
const os = process.platform;
const reasons = { external: [], runtimeOnly: [], osOnly: [] };
for (const skill of readdirSync(CASES)) {
const dir = join(CASES, skill);
if (!statSync(dir).isDirectory()) continue;
const skillCfgPath = join(dir, '_skill.json');
const skillCfg = existsSync(skillCfgPath) ? JSON.parse(readFileSync(skillCfgPath, 'utf8')) : {};
for (const file of readdirSync(dir)) {
if (!file.endsWith('.json') || file === '_skill.json') continue;
const id = `${skill}/${file.replace(/\.json$/, '')}`;
const c = JSON.parse(readFileSync(join(dir, file), 'utf8'));
// Порядок совпадает с раннером: сначала ОС, потом порт, потом фикстура.
if (c.osOnly && ![].concat(c.osOnly).includes(os)) { reasons.osOnly.push(id); continue; }
if (c.runtimeOnly && c.runtimeOnly !== runtime) { reasons.runtimeOnly.push(id); continue; }
const setup = String(c.setup || skillCfg.setup || '');
if (setup.startsWith('external:') && !existsSync(setup.slice('external:'.length))) {
reasons.external.push(id);
}
}
}
const total = reasons.external.length + reasons.runtimeOnly.length + reasons.osOnly.length;
if (listMode) {
for (const [key, ids] of Object.entries(reasons)) {
if (!ids.length) continue;
console.log(`\n${key} (${ids.length}):`);
for (const id of ids) console.log(` ${id}`);
}
console.log('');
}
console.log(
`Ожидается пропущенных: ${total} [${os}, runtime: ${runtime}] ` +
`= external ${reasons.external.length} + runtimeOnly ${reasons.runtimeOnly.length} + osOnly ${reasons.osOnly.length}`,
);
console.log('Сверить с "Skipped: N" из прогона runner.mjs с теми же --runtime.');