5月27日 23:18

Cypress 的 beforeEach、before、afterEach 和 after 钩子有什么区别?

核心区别

四个钩子的根本区别在于执行频率作用域

  • beforeEach / afterEach:每个 it 用例前后各执行一次,作用域为当前 describe 块内所有用例
  • before / after:整个 describe 块开始前和结束后各执行一次,作用域为整个测试套件
钩子执行时机执行次数典型用途
beforeEach每个 it 之前N 次(N = 用例数)重置状态、登录、访问页面
afterEach每个 it 之后N 次清除 cookie、会话、快照
before所有 it 之前1 次种子数据、全局配置
after所有 it 之后1 次数据库清理、资源释放

执行顺序

嵌套 describe 时,钩子的执行顺序遵循"从外到内"原则:

javascript
describe("外层", () => { before(() => cy.log("outer before")); // 1 beforeEach(() => cy.log("outer beforeEach")); // 3, 7 describe("内层", () => { before(() => cy.log("inner before")); // 2 beforeEach(() => cy.log("inner beforeEach")); // 4, 8 it("测试A", () => cy.log("test A")); // 5 it("测试B", () => cy.log("test B")); // 9 afterEach(() => cy.log("inner afterEach")); // 6, 10 }); afterEach(() => cy.log("outer afterEach")); // 最后执行 });

输出:outer before → inner before → (outer beforeEach → inner beforeEach → 测试A → inner afterEach → outer afterEach) × 2轮

选择依据

  • 需要每个用例都从干净状态开始 → beforeEach,不要用 before
  • 用例之间允许共享状态(如只读数据) → before 一次性初始化
  • afterEach 适合清理当前用例产生的副作用(如 localStorage)
  • after 适合清理整个套件的资源(如测试数据库)

常见错误:在 before 中登录,然后所有用例共享登录态。一旦某个用例意外注销,后续用例全部失败。正确做法是用 beforeEach 登录,保证每个用例的独立性。

追问

Q: beforeEachcy.visit()cy.request() 有什么区别? cy.visit() 会加载完整页面并等待页面事件,较慢;cy.request() 只发 HTTP 请求不渲染,适合用 API 预设数据来加速测试。

Q: 钩子中的断言失败会影响用例执行吗? 会。beforeEach 中断言失败,该用例跳过;afterEach 中失败会标记用例为失败,但不影响下一个用例的执行。

Q: 为什么 Cypress 官方更推荐 beforeEach 而非 before 因为 Cypress 的核心原则是测试隔离。before 共享状态容易导致用例间耦合,一个用例的副作用会污染后续用例。beforeEach 保证每个用例从相同初始状态运行,测试更稳定。

标签:Cypress