Playwright Fixture未为每个测试生成新实例问题排查
Playwright Fixture 测试间数据串扰问题排查与解决
问题根源
你遇到的测试数据串扰,核心原因是TestContext中引用了模块级的单例对象。看你提供的代码,Bank是通过export const定义的模块级变量,Node.js模块加载机制会让它在整个进程中只存在一个实例。即便Fixture每次测试都会新建TestContext,但TestContext.user和TestContext.bank始终指向同一个全局单例,导致TEST1修改的数据会被TEST2读取到。
原beforeEach方案能实现隔离,大概率是因为你在beforeEach中不仅新建了TestContext,还为user/bank创建了全新的对象实例,而非直接引用全局单例。
解决方案
要解决这个问题,核心是确保每次测试都能拿到完全独立的TestContext及内部属性实例,具体可以从以下两方面修改:
1. 重构User/Bank的定义,避免全局单例
将原来的export const单例改为工厂函数或类,每次调用都返回新的对象实例:
示例:用工厂函数重构Bank
// variables/Bank.ts export type Bank = { bankName: string | null routingNumber: number | null accountNumber: number | null // 修正原代码中的拼写错误accountNumer } // 工厂函数:每次调用返回全新Bank对象 export const createBank = (): Bank => ({ bankName: null, routingNumber: null, accountNumber: null, })
示例:用类重构User(如果适用)
// variables/User.ts export class User { username: string | null = null email: string | null = null // 其他用户属性... // 可选:添加初始化方法 init(username: string, email: string) { this.username = username this.email = email } }
2. 修改TestContext,每次创建内部属性的新实例
让TestContext在实例化时,通过工厂函数或类创建全新的user/bank对象:
// TestContext.ts import { User } from './variables/User' // 如果是类 import { createBank } from './variables/Bank' export class TestContext { // 如果User是类,每次new一个新实例 public user = new User() // 如果是工厂函数,调用函数获取新对象 public bank = createBank() }
3. 确保Fixture的作用域为Test
Playwright Fixture默认作用域是test(每个测试独立创建),如果之前手动设置了scope: 'worker'会导致Fixtures在整个Worker进程共享,需要确认Fixture定义正确:
// fixture定义文件 import { test as base } from '@playwright/test' import { TestContext } from './TestContext' type MyTestFixtures = { testContext: TestContext } export const test = base.extend<MyTestFixtures>({ testContext: async ({}, use) => { // 每次测试创建全新的TestContext实例 const ctx = new TestContext() await use(ctx) // 可选:测试结束后的清理逻辑 }, // 其他Fixture(如页面类)同理,确保每次返回新实例 })
验证修改效果
修改后,每个测试用例都会拿到独立的TestContext,其中的user/bank都是全新对象,TEST1修改的数据不会影响TEST2,实现测试间的数据隔离。
内容的提问来源于stack exchange,提问作者Marko Dzelajlija
相关产品推荐
相关产品推荐

