identity-and-auth-testing

身份与认证测试

这是 youteacher 集成测试套件里专门面向认证的辅助层。它的核心主张是:认证只有在被真人使用的方式下走通,才算被证明——走真实的 UI、打真实的后端服务、再回到那些服务真正写下的状态去核对。认证服务和它们各自的存储从不被 mock;唯一的替身是外部邮件投递和 OAuth 提供方——这两样测试无法真的去驱动。辅助函数通过渲染出来的页面完成注册和登录,像认证器 App 那样生成第二因子验证码,用浏览器里真实的凭据设备走通 passkey,最后读取每个服务各自的数据库,确认该有的行存在、该删的行已消失。

走真实 UI,不抄近路

注册和登录辅助函数点击的是访客看到的同一批对话框和页面。它们打开登录框、填入凭据、提交,然后等到页头的账户控件报告"已认证"状态才继续。注册辅助函数走完整的"先验邮箱、再设密码"流程:填地址、触发一次性验证码邮件、从 mock 邮件服务里取回验证码、提交、设置密码、创建账户。

这些辅助函数里的大部分代码,不是主流程本身,而是围着主流程的时序纪律。页面在服务端 HTML 到达后才 hydrate,有些列表会自动选中一行并悄悄改写 URL,而闸门控件在挑战 token 就绪前一直是禁用的。点击早了一瞬,要么毫无反应,要么把正在输入的字段拆掉。所以辅助函数等的是具体信号——某个元素的认证状态属性、某个特定的网络响应、一个已稳定的 URL——而不是挂钟延时。这是反复出现的教训:一个 e2e 辅助函数的篇幅,大半花在把流程变得确定上,整套测试的可靠性就压在这些等待上。

当 UI 登出路径失败时,辅助函数会退回到直接清掉会话 cookie,避免一个陈旧会话泄漏进下一个测试。测试隔离在这里被当作正确性属性,而不是可有可无的讲究。

第二因子,是生成而非造假

基于时间的一次性密码由一个小而合标准的生成器产出(RFC 6238 构造),它把一个共享密钥变成认证器 App 会显示的同一串滚动验证码。设置辅助函数在安全页里注册第二因子,读回服务端下发的密钥,立刻据此算出一个有效码提交以确认注册;后续登录再用同一个生成器回答第二因子提示。因为验证码是算出来的而不是伪造的,服务端真实的校验路径原封不动地跑了一遍。

passkey 通过一个挂在 Chrome DevTools Protocol 上的虚拟认证器来走通。这不是对凭据 API 的打桩——它是浏览器提供的真实 WebAuthn 设备,所以 navigator.credentials 的行为和生产环境完全一致,只是背后换成了虚拟设备而非物理硬件。辅助函数可以添加和移除该设备、列出它存的凭据、清空它们、切换用户验证是否成功——这样一个测试就能覆盖生物识别成功和失败两种情形。

测试直接发起(而非经浏览器)的服务间调用,带一个短时效的 bearer token,用来证明请求来自可信服务。这个 token 刻意不携带任何用户身份——用户会话活在会话 cookie 里,服务信任是另一件事。该 token 的签名与过期校验交给后端单元和集成测试;e2e 层只需要一个有效 token 就能触达 admin 和 profile 接口。

回到真相之源去核对

每个后端服务各自拥有自己的存储,数据库辅助层伸进每一个去核对结果:auth 服务里的用户账户、会话、第二因子密钥、passkey 与 OAuth 关联;profile 服务里的人才、雇主、招聘方与管理员记录;job 服务里的职位与投递;搜索索引里的文档;以及 Redis 里的限流与缓存计数。断言辅助函数把期望表述成状态——这个用户存在且带这些属性、恰好新建了一个会话、只剩下这一个会话、被删用户的所有行在每个服务里都已清空——并在不匹配时报出指名的错误。

这就补上了只看 UI 的断言留下的缺口。屏幕可以显示"已登录"而后端什么都没写;删除可以看起来成功而孤儿行还活在兄弟服务里。读取真相之源,才让一个绿测意味着能力真的跑过了。两个习惯值得注意:会话断言比对的是动作前后的两张快照,所以量的是"这一次动作"而非累积状态;删除检查按 user id 直接查每张表,而不是走 join,这样一个没有父行的孤儿行也仍会被抓到。

为什么这样建

整个这一层是在论证一件事:在多服务系统里,身份是测试中最不能假造的东西。认证横跨浏览器、多个服务、多个存储;任何一处接缝上的 mock,恰恰盖住了最伤人的那个集成 bug。通过驱动真实 UI、生成真实因子、使用真实凭据设备、读取真实存储,这些辅助函数让测试对每个其他测试都依赖的那条流程保持诚实。

另见

  • youteacher_integral ——本层所属的集成测试套件
  • e2e-must-be-blackbox ——为什么测试驱动用户动作、断言可见状态
  • guard-must-fail-on-the-bug ——断言只有在 bug 能让它变红时才有价值
about this entry

One of sijie's wiki entries. The AI on this site is grounded in the same corpus and answers in sijie's voice, with citations back to entries like this one — answering costs sijie money, so it waits behind a code: enter an access code →

identity-and-auth-testing