☰
成为全栈·Next.js 网站前台篇·质量门禁:契约测试、会话竞态、双运行时与浏览器验收
2026/10/8 18:18:57 网站建设 项目流程

成为全栈·Next.js 网站前台篇·质量门禁:契约测试、会话竞态、双运行时与浏览器验收

类型检查、单元测试、接口联调、页面冒烟和浏览器操作证明的是不同事情。把它们统称为“测试通过”,会让没有覆盖的风险悄悄消失。

前言

本项目曾出现过一个典型问题:后端退出接口测试通过,浏览器里的退出按钮却失败。原因是直接接口工具携带了 access token,而真实客户端封装错误地跳过鉴权。

这个故障说明,测试层级不能互相替代。接口可用不等于组件调用正确,构建成功不等于 Worker 缓存正确,桌面截图也不等于键盘和手机路径可用。

每道门禁回答一个问题

门禁能证明不能证明
类型检查调用与类型约束一致运行行为正确
Biome规范与静态问题符合规则用户流程可用
单元测试被覆盖的不变量成立组件接线与真实 API 正确
接口联调契约、代理和测试库往返浏览器按钮使用了正确封装
页面冒烟路由、metadata、状态码所有交互和视觉正确
浏览器验收指定用户路径实际可操作全浏览器、全设备覆盖
双构建Node 与 Worker 产物可生成线上资源、容量和缓存 SLA

从共享 OpenAPI 重新生成类型

pnpmgen:apipnpmtypecheck

类型来源是共享契约,不手写第二套 DTO。生成成功只能说明 schema 可转换,仍要用真实响应检查业务字段、错误码与消费者行为。

生成器与应用 TypeScript 版本曾存在兼容差异,因此工具运行环境独立;这类问题应与业务源码错误分开诊断。

并发会话必须用可控时序测试

test('parallel expired requests share one refresh',async()=>{constresults=awaitPromise.all([request('/me/profile'),request('/me/favorites'),request('/me/history'),])assert.equal(refreshes,1)assert.deepEqual(results,['private-data','private-data','private-data'])})
test('logout during refresh cannot restore old account',async()=>{awaitassert.rejects(request('/me/profile'))assert.equal(useAuthStore.getState().accessToken,null)})

这些测试保护刷新 Promise、会话代次和单次重放。只测“登录成功”看不到任何竞态风险。

测试真实客户端适配器,而不只测端点

test('logout sends backend-required access token',async()=>{awaitlogout()assert.equal(sentAuthorization,'Bearer logout-token')})

这个用例来自实际浏览器故障。它把覆盖面从“后端支持退出”推进到“当前前端的 logout 封装正确调用后端”。回归测试最有价值的来源,往往就是曾经漏掉的真实路径。

两种运行时都要构建和联调

pnpmbuildpnpmstartpnpmbuild:cfpnpmexecwrangler dev--local

标准 Next.js Node 运行和 OpenNext Cloudflare Worker 在 Cookie、流式响应、缓存与 Node 兼容层上可能不同。项目分别运行接口联调和页面冒烟,而不是假设 Node 通过就等于 Worker 通过。

故障注入验证恢复,而不只验证错误画面

1. 正常打开搜索页并记录结果 2. 停止独立测试后端 3. 刷新,确认进入错误状态而不是 404/空结果 4. 恢复后端 5. 点击重新加载 6. 确认真实结果与会话状态恢复

“页面出现错误提示”只证明失败被展示;最后一步才证明恢复链路有效。

浏览器路径覆盖组合状态

登录 → 刷新恢复 → 首页继续加载 → 收藏 → 会员列表出现 → 退出 → 再访问收藏页 → 跳登录并保留返回路径

这条路径同时穿过会话、公开查询、互动失效、会员守卫和安全 redirect。单独测每个组件无法证明它们组合后不互相破坏。

测试数据必须与生产隔离

.local/test.db .local/uploads .local/*.log

接口联调会创建账号、草稿、评论和附件,因此只指向独立测试库。环境文件、测试凭证和报告进入忽略目录,不提交到仓库,也不把预览数据当成生产迁移。

当前验证证据

检查已记录结果
类型与规范typecheck、Biome 通过
单元测试会话、URL、Markdown、Cookie、投稿、评论树
接口联调Node 与 Worker 两种环境
页面冒烟公开/会员、metadata、sitemap、robots、代理
浏览器登录退出、文章流、搜索恢复、投稿评论、五种宽度
缓存公开再验证变化、私有 no-store

旧报告描述旧版本。任何认证、缓存或运行平台改动后,都要按风险重跑相关层级,不能引用历史“全绿”当作新证明。

推荐执行顺序

pnpmgen:apipnpmtypecheckpnpmlintpnpmtestpnpmbuildpnpmbuild:cf

之后启动独立后端、Node 生产服务和本地 Worker,运行接口联调、冒烟与浏览器路径。生成、构建和开发服务共享产物目录时应串行,避免交错写入导致假失败。

适用边界

现有证据没有覆盖真实手机硬件、完整跨浏览器、生产压测、新机器零安装和远程 Cloudflare。报告必须保留这些空白,不能因为检查很多就顺带声称全部完成。

质量门禁应按改动风险选择。改一句文案无需跑远程缓存;修改认证内核则不能只看截图。

小结

测试的核心不是数量,而是证据与结论对应。每一层都要说明证明了什么,也要说明不能证明什么。

当故障注入、真实客户端封装、双运行时和组合用户路径都进入门禁以后,“通过”才不再只是一个模糊形容词。

延伸阅读

  • Core Web Vitals 与前台性能

如果这篇文章对你有帮助,欢迎订阅我的 CSDN 专栏「成为全栈」:

🔗 专栏地址:https://blog.csdn.net/fungleo/category_13204651.html

📦 本系列配套代码仓库:https://github.com/fengcms/become-a-full-stack-developer

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询