You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将fixtures生成的测试数据ID传递至global.teardown.ts?

问题

我在fixtures.ts中调用API在数据库创建对象并获取其ID,希望所有测试完成后清理这些数据库对象。请问如何将这些ID传递至global.teardown.ts?

当前尝试方案

我尝试在global.teardown.ts中导入包含单例GUID数组的fixtures模块,但模块会被重新初始化,导致数组始终为空。

global.teardown.ts

import { entityGuidsToDelete, api } from './fixtures'

async function globalTeardown() {
    // 无法正常工作,因为数组始终为空
    for(const entityGuid of entityGuidsToDelete) { 
        await api.deleteEntity(entityGuid);
    }
}

export default globalTeardown;

playwright.config.ts

export default defineConfig({
  ...
  /* 为主流浏览器配置测试项目 */
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
  ],

  globalTeardown: require.resolve('./global-teardown')
});

fixtures.ts

type Fixtures = {
  userApi: Api;
  newEntity: LegalEntityModel;
};

export const entityGuidsToDelete = new Array<string>();

export const test = base.extend<Fixtures>({
 ...
 newEntity: async ({ userApi }, use) => {
    const newEntity = await createNewEntity()
    entityGuidsToDelete.push(newEntity.id); // 这段代码确实会被执行
    await use(newEntity);
  }  
}

export { expect } from '@playwright/test';

解决方法

Playwright的全局前置/后置钩子和测试fixtures运行在不同进程中,内存中的数组无法跨进程共享,推荐以下几种可行方案:

方案1:临时文件存储ID

在fixtures中将需要清理的ID写入临时JSON文件,全局后置钩子从文件读取ID并执行清理:

  1. 修改fixtures.ts添加文件写入逻辑:
import fs from 'fs/promises';
import path from 'path';

const tempFile = path.join(__dirname, '.temp-entities.json');

// 初始化空文件,避免读取时出错
(async () => {
  await fs.writeFile(tempFile, JSON.stringify([]), 'utf-8');
})();

type Fixtures = {
  userApi: Api;
  newEntity: LegalEntityModel;
};

export const test = base.extend<Fixtures>({
 ...
 newEntity: async ({ userApi }, use) => {
    const newEntity = await createNewEntity();
    // 读取现有ID并追加新ID
    const existingIds = JSON.parse(await fs.readFile(tempFile, 'utf-8'));
    existingIds.push(newEntity.id);
    await fs.writeFile(tempFile, JSON.stringify(existingIds), 'utf-8');
    
    await use(newEntity);
  }  
}

export { expect } from '@playwright/test';
  1. 修改global.teardown.ts读取文件并清理:
import fs from 'fs/promises';
import path from 'path';
import { api } from './fixtures';

const tempFile = path.join(__dirname, '.temp-entities.json');

async function globalTeardown() {
    try {
        const entityGuids = JSON.parse(await fs.readFile(tempFile, 'utf-8'));
        for(const entityGuid of entityGuids) { 
            await api.deleteEntity(entityGuid);
        }
        // 清理临时文件
        await fs.unlink(tempFile);
    } catch (err) {
        console.error('清理资源失败:', err);
    }
}

export default globalTeardown;

方案2:测试结束后即时清理

如果不需要等待所有测试完成再统一清理,可以在fixture中添加后置清理逻辑,每个测试结束后立即删除对象:

newEntity: async ({ userApi }, use) => {
    const newEntity = await createNewEntity();
    await use(newEntity);
    // 测试执行完成后立即清理当前对象
    await userApi.deleteEntity(newEntity.id);
}

这种方式无需依赖全局后置钩子,能避免测试间的资源依赖问题,适合独立测试场景。

方案3:使用环境变量传递(适合少量ID)

如果需要清理的ID数量不多,可以在fixtures中将ID拼接为字符串存入环境变量,全局后置钩子再解析该变量:

// fixtures.ts中添加
process.env.ENTITY_IDS = (process.env.ENTITY_IDS || '') + ',' + newEntity.id;

// global.teardown.ts中解析
const entityGuids = (process.env.ENTITY_IDS || '').split(',').filter(Boolean);

内容的提问来源于stack exchange,提问作者Liero

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 04:25:12