【问题标题】:Do jest tests wait for previous async tests to resolve?开玩笑测试是否等待先前的异步测试解决?
【发布时间】:2019-06-30 07:33:05
【问题描述】:

我读过同一测试文件中的开玩笑测试按顺序执行。我还读到,在编写涉及回调的测试时,应该使用 done 参数。

但是,当使用我在下面的代码中使用的 async/await 语法使用 Promise 时,我可以指望测试按顺序运行和解决吗?

import Client from '../Client';
import { Project } from '../Client/types/client-response';

let client: Client;

beforeAll(async () => {
    jest.setTimeout(10000);
    client = new Client({ host: 'ws://127.0.0.1', port: 8080 , logger: () => {}});
    await client.connect();
})


describe('Create, save and open project', () => {
    let project: Project;
    let filename: string;

    beforeAll(async () => {
        // Close project
        let project = await client.getActiveProject();
        if (project) {
            let success = await client.projectClose(project.id, true);
            expect(success).toBe(true);
        }
    })

    test('createProject', async () => {
        project = await client.createProject();
        expect(project.id).toBeTruthy();
    });

    test('projectSave', async () => {
        filename = await client.projectSave(project.id, 'jesttest.otii', true);
        expect(filename.endsWith('jesttest.otii')).toBe(true);
    });

    test('projectClose', async () => {
        let success = await client.projectClose(project.id);
        expect(success).toBe(true);
    });

    test('projectOpen', async () => {
        project = await client.openProject(filename);
        expect(filename.endsWith('jesttest.otii')).toBe(true);
    });
})

afterAll(async () => {
    await client.disconnect();
})

【问题讨论】:

    标签: async-await jestjs


    【解决方案1】:

    来自the docs

    ...默认情况下,Jest 按照在收集阶段遇到的顺序依次运行所有测试,等待每个测试完成并在继续之前进行整理。

    所以虽然Jest 可能会并行运行测试文件,但默认情况下它会连续运行文件内的测试

    这种行为可以通过以下测试来验证:

    describe('test order', () => {
    
      let count;
    
      beforeAll(() => {
        count = 0;
      })
    
      test('1', async () => {
        await new Promise((resolve) => {
          setTimeout(() => {
            count++;
            expect(count).toBe(1);  // SUCCESS
            resolve();
          }, 1000);
        });
      });
    
      test('2', async () => {
        await new Promise((resolve) => {
          setTimeout(() => {
            count++;
            expect(count).toBe(2);  // SUCCESS
            resolve();
          }, 500);
        });
      });
    
      test('3', () => {
        count++;
        expect(count).toBe(3);  // SUCCESS
      });
    
    });
    

    【讨论】:

    • 正如@skyboyer 指出的那样,有未记录的test.concurrent,但使用起来可能很棘手(例如,beforeAll 不能保证在test.concurrent 测试之前运行)并且不是默认行为。
    • 是按测试文件连续,还是按describe block连续?
    【解决方案2】:

    当然,这取决于配置的测试运行器。假设Jasmine2 it seems impossible 同时运行测试:

    由于 javascript 的单线程性,实际上不可能在单个浏览器窗口中并行运行测试

    但是查看docs' config section

    --最大并发= 防止 Jest 同时执行超过指定数量的测试。仅影响使用 test.concurrent 的测试。

    --maxWorkers=| 别名:-w。指定工作池为运行测试生成的最大工作人员数。这默认为您机器上可用的内核数。在 CI 等资源有限的环境中调整它可能很有用,但默认值对于大多数用例来说应该足够了。

    对于具有可变 CPU 可用的环境,您可以使用基于百分比的配置:--maxWorkers=50%

    同时查看jest-runner-concurrent 的描述:

    Jest 的默认运行程序为每个测试文件使用一个新的 child_process(也称为 worker)。尽管工人的最大数量是可配置的,但运行大量工人很慢并且消耗大量内存和 CPU。

    所以看起来您可以配置并行运行的测试文件数量(maxWorkers)以及单个工作人员范围内的并发测试用例(maxConcurrency)。如果您使用jest 作为测试运行器。这只影响test.concurrent() 测试。

    由于某种原因,我无法在他们的主要文档站点上的 test.concurrent() 上找到任何内容。

    无论如何,您都可以自己检查您的环境:

    describe('checking concurrent execution', () => {
        let a = 5;
    
        it('deferred change', (done) => {
            setTimeout(() => { 
                a = 11;
                expect(a).toEqual(11); 
                done();
            }, 1000);
        });
    
        it('fails if running in concurrency', () => {
            expect(a).toEqual(11);
        });
    })
    

    当然,上面我使用了 Jasmine 的语法(describe, it),所以您可能需要用其他调用替换它。

    【讨论】:

      猜你喜欢
      • 2023-02-09
      • 2023-03-25
      • 2022-01-13
      • 2018-02-22
      • 1970-01-01
      • 2018-11-23
      • 1970-01-01
      • 2020-10-08
      • 1970-01-01
      相关资源
      最近更新 更多