route-coverage 补下界断言防「数不到路由也绿」;跳过告警点名哪道保险没跑

评审 Important:missing 为空有两种可能——真的不漏,或者根本没数到路由
(app.routes 形状变了、createServer 早退)。空集是任何集合的子集,不设
下界这条 fail-closed 测试会从「会红」退化成「永远绿」。补
registered.length > 50 的下界,反向验证过(临时调到 1000 确认真的报红)。

无库跳过时的 stderr 告警原来只说连不上库,没说清「这道保险这次没跑、
漏的是哪一类」——按评审裁决不改 skipIf 行为(仓库级惯例),只改措辞
点名到位。
This commit is contained in:
xcs
2026-08-25 18:17:03 +08:00
parent 61622f94d5
commit fc5afa9600
@@ -35,7 +35,9 @@ async function provisionDatabase(): Promise<{ url: string; stop(): Promise<void>
return { url: started.getConnectionUri(), stop: () => started.stop().then(() => undefined) }; return { url: started.getConnectionUri(), stop: () => started.stop().then(() => undefined) };
} catch (error) { } catch (error) {
process.stderr.write( process.stderr.write(
`⚠️ 路由覆盖 it 跳过:连不上开发实例也起不了 Testcontainers(${error instanceof Error ? error.message : String(error)})\n`, `⚠️ 路由覆盖 it 跳过 —— **这道 fail-closed 的安全保险这一次没有跑**:` +
`「写了路由处理器却没有契约声明 access」这一类漏网,本次构建没有检查。\n` +
` 连不上开发实例也起不了 Testcontainers(${error instanceof Error ? error.message : String(error)})\n`,
); );
return undefined; return undefined;
} }
@@ -78,10 +80,17 @@ describe.skipIf(database === undefined)('路由覆盖', () => {
it('Hono 里每条注册的路由都在归属注册表里', () => { it('Hono 里每条注册的路由都在归属注册表里', () => {
const app = createServer(container!); const app = createServer(container!);
const registry = appRouteRegistry(); const registry = appRouteRegistry();
const missing = app.routes const registered = app.routes.filter((r) => r.method !== 'ALL');
.filter((r) => r.method !== 'ALL')
.filter((r) => !registry.has(r.method, r.path)) /*
.map((r) => `${r.method} ${r.path}`); * 先钉下界:`missing` 为空有两种可能 —— 真的一条不漏,或者**根本没数到路由**
* (createServer 改用子应用组合、Hono 换了 routes 的形状、建 server 中途早退)。
* 空集是任何集合的子集,不设下界的话后一种情况会伪装成前一种,
* 这道保险就从「会红」变成「永远绿」。
*/
expect(registered.length, '一条路由都没数到 —— 先查 createServer 与 app.routes 的形状').toBeGreaterThan(50);
const missing = registered.filter((r) => !registry.has(r.method, r.path)).map((r) => `${r.method} ${r.path}`);
expect(missing, '这些路由没有声明归哪个端(契约加 access,或 EXTRA_ROUTES 补入)').toEqual([]); expect(missing, '这些路由没有声明归哪个端(契约加 access,或 EXTRA_ROUTES 补入)').toEqual([]);
}); });
}); });