Files
vac-optimizer/src/app/benchmark/benchmark-budget.spec.ts
T
nessarandClaude Opus 5.5 3bbe989eca
CI / policy (push) Successful in 7s
CI / validate (push) Successful in 1m5s
CI / build (push) Successful in 1m38s
CI / policy (pull_request) Successful in 10s
CI / security (push) Successful in 1m19s
CI / test (push) Successful in 3m29s
CI / validate (pull_request) Successful in 1m42s
CI / benchmark (push) Successful in 4m13s
CI / security (pull_request) Successful in 56s
CI / build (pull_request) Successful in 1m42s
CI / test (pull_request) Successful in 3m8s
CI / images (push) Successful in 1m15s
CI / required (push) Successful in 1s
CI / benchmark (pull_request) Successful in 3m37s
CI / images (pull_request) Successful in 1m11s
CI / required (pull_request) Successful in 1s
test(benchmark): print a readable summary table
Print the calibration and a Markdown table with one aligned row per
scenario as soon as it finishes: both planning times, mean, budget, ratio,
multiplier, outcome, placements, determinism and budget status. Write
directly to stdout so Vitest adds no per-line headers. The complete TSV
report still follows the table.

Refs #281, #285

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 02:09:54 +02:00

64 lines
2.0 KiB
TypeScript

import {
BenchmarkMeasurement,
benchmarkSummaryHeader,
benchmarkSummaryRow,
budgetViolations,
} from './leave-planner-benchmark';
const measure = (scenario: string, planningMs: number) =>
({ scenario, planningMs }) as BenchmarkMeasurement;
describe('benchmark budget gate', () => {
const multipliers = { a: 2 };
it('accepts a mean within multiplier x calibration', () => {
expect(budgetViolations([measure('a', 150), measure('a', 250)], 100, multipliers)).toEqual(
[],
);
});
it('reports measured time, budget, multiplier and calibration when over budget', () => {
const [message] = budgetViolations(
[measure('a', 300), measure('a', 320)],
100,
multipliers,
);
expect(message).toContain('a:');
expect(message).toContain('measured 310.0 ms');
expect(message).toContain('budget 200.0 ms');
expect(message).toContain('multiplier 2');
expect(message).toContain('calibration 100.0 ms');
});
it('fails a scenario without a multiplier', () => {
expect(budgetViolations([measure('new', 1)], 100, multipliers)).toEqual([
'new: no budget multiplier defined',
]);
});
});
describe('benchmark summary table', () => {
const runs = (planningMs: number[]) =>
planningMs.map(
(ms, index) =>
({
scenario: 'a',
planningMs: ms,
outcome: 'Plan',
lastCompletedStage: 'dates',
placements: 3,
deterministic: index ? 'yes' : 'baseline',
}) as BenchmarkMeasurement,
);
it('aligns rows with the header', () => {
const [header, separator] = benchmarkSummaryHeader().split('\n');
const row = benchmarkSummaryRow(runs([150, 250]), 100, { a: 2 });
expect(row).toHaveLength(header.length);
expect(separator).toHaveLength(header.length);
expect(row).toContain('0.15 / 0.25 s');
expect(row).toContain('Plan (dates)');
expect(row).toMatch(/\| ok +\|$/);
});
it('marks scenarios over budget or without a budget', () => {
expect(benchmarkSummaryRow(runs([300, 320]), 100, { a: 2 })).toMatch(/\| OVER +\|$/);
expect(benchmarkSummaryRow(runs([1]), 100, {})).toMatch(/\| no budget \|$/);
});
});