我们使用 jest 来测试我们的 API,并且有相当复杂的场景。我们使用 beforeAll
为每个测试设置通用辅助变量的函数,有时设置租户分离,在其他情况下,我们使用 beforeEach
为测试设置租户分离的功能,为测试租户提供一些默认配置,...
例如,测试可能像这样(如您所见,我们使用 TypeScript 来编写测试,以防万一):
let apiClient: ApiClient;
let tenantId: string;
beforeAll(async () => {
apiClient = await getClientWithCredentials();
});
beforeEach(async () => {
tenantId = await createNewTestTenant();
});
describe('describing complex test scenario', () => {
it('should have some initial state', async () => {
await checkState(tenantId);
});
it('should have some state after performing op1', async () =>{
await op1(tenantId);
await checkStateAfterOp1(tenantId);
});
it('should have some state after performing op2', async () =>{
await op2(tenantId);
await checkStateAfterOp2(tenantId);
});
it('should have some state after performing op1 and op2', async () =>{
await op1(tenantId);
await op2(tenantId);
await checkStateAfterOp1AndOp2(tenantId);
});
it('the order of op1 and op2 should not matter', async () =>{
await op2(tenantId);
await op1(tenantId);
await checkStateAfterOp1AndOp2(tenantId);
});
});
describe('another similar complex scenario', () => {
// ... you see where this is going
});
问题是,共享由
beforeAll
初始化的变量的最佳方式是什么?和 beforeEach
? - 如果使用 --runInBand
执行上述测试,则有效选项,它“......在当前进程中连续运行所有测试......”但是当并行执行时,它开始非常随机地失败,主要是指
tenantId
未定义。鉴于这些测试是大约 200 个类似测试的一部分,因此全部通过。同时,它取决于机器。具有 8 核/16 线程的构建代理只有 50-60% 通过测试。我的四核 CPU 同事通过了约 80% 的测试,而对我来说,双核 CPU 有时只有 1-2 次测试失败,其他时候约 10 次。所以很明显,这取决于并行度。我发现了 2 个 GitHub 问题,人们提到了使用
this
的可能性。共享上下文(不再起作用)或将所有内容封装在 describe
中:所以我尝试了一个非常幼稚的方法:
describe('tests', () => {
let apiClient: ApiClient;
let tenantId: string;
beforeAll(async () => {
apiClient = await getClientWithCredentials();
});
beforeEach(async () => {
tenantId = await createNewTestTenant();
});
describe('describing complex test scenario', () => {
it('should have some initial state', async () => {
await checkState(tenantId);
});
it('should have some state after performing op1', async () =>{
await op1(tenantId);
await checkStateAfterOp1(tenantId);
});
it('should have some state after performing op2', async () =>{
await op2(tenantId);
await checkStateAfterOp2(tenantId);
});
it('should have some state after performing op1 and op2', async () =>{
await op1(tenantId);
await op2(tenantId);
await checkStateAfterOp1AndOp2(tenantId);
});
it('the order of op1 and op2 should not matter', async () =>{
await op2(tenantId);
await op1(tenantId);
await checkStateAfterOp1AndOp2(tenantId);
});
});
describe('another similar complex scenario', () => {
// ... you see where this is going
});
});
但这似乎没有任何效果。
我真的很想并行运行测试,但我在文档中找不到任何相关内容。也许我不知道我应该寻找什么?
最佳答案
这对你有用吗?
describe('tests', () => {
let apiClient: ApiClient;
let tenantIds: {id: string, used: boolean}[];
const findUnusedTenantId = () => {
const tenant = tenantIds.find(a => !a.used);
tenant.used = true;
return tenant.id
}
beforeAll(async () => {
apiClient = await getClientWithCredentials();
});
beforeEach(async () => {
const id = await createNewTestTenant();
tenantIds.push({id, used: false})
});
describe('describing complex test scenario', () => {
let tenantId: string
it('should have some initial state', async () => {
tenantId = fineUnusedTenantId();
await checkState(tenantId);
});
it('should have some state after performing op1', async () =>{
await op1(tenantId);
await checkStateAfterOp1(tenantId);
});
// ...
});
describe('next scenario', () => {
let tenantId: string
it('first test', async () => {
tenantId = fineUnusedTenantId();
await checkState(tenantId);
});
你可能想要一个 afterAll Hook 来清理数据库
关于typescript - 如何在 Jest 中的 beforeAll/beforeEach 和测试之间共享数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48528502/