在 Jest 中有条件地 运行 测试

Conditionally run tests in Jest

我一直在比较函数式范式和面向对象范式。

作为其中的一部分 - 我想做一些性能测试。

我现在有一些看起来像这样的测试:

it("Some long running performance test", () => {
    const result = myFunctionWithLotsOfData();       
}); 

现在,我只是打印这段代码需要多长时间 运行(大约 5000 毫秒)。

我喜欢将 Jest 用于它提供的所有断言和模拟功能,以及实时重新加载等。

但是,我不想一直进行这些测试,我会 运行 创建一个像 npm test:performance 这样的 npm 脚本,并且只有 运行 这些测试如果一个环境变量存在或类似。

最好的方法是什么?

这是一个解决方案,创建 itif 函数以便我们可以 运行 根据某些条件进行单元测试。

例如,itif函数:

export const itif = (name: string, condition: () => boolean | Promise<boolean>, cb) => {
  it(name, async done => {
    if (await condition()) {
      cb(done);
    } else {
      console.warn(`[skipped]: ${name}`);
      done();
    }
  });
};

单元测试:

describe('test suites', () => {
  itif(
    'functional-approach-2 perforance test',
    async () => process.env.PERFORMANCE_TEST === 'true',
    done => {
      console.info('Functional Approach 2 Performance Test');
      const t0 = Date.now();
      const m0 = getMemory();
      const li0 = instantiateFanRecursive(20, 2, 0, 0, 1, 1, 2, 1);
      const r0 = getDrawablesFromLineInstances(li0);
      printMemory(getMemory() - m0);
      console.info(`Length: ${r0.length}`);
      console.info(`Time Taken: ${Date.now() - t0}ms`);
      done();
    }
  );
});

运行 当 process.env.PERFORMANCE_TEST 环境变量的值等于 'true' 时你的单元测试,结果:

PERFORMANCE_TEST=true npm t -- /Users/elsa/workspace/github.com/mrdulin/jest-codelab/src/Whosebug/58264344/index.spec.t

> jest-codelab@1.0.0 test /Users/elsa/workspace/github.com/mrdulin/jest-codelab
> jest --detectOpenHandles "/Users/elsa/workspace/github.com/mrdulin/jest-codelab/src/Whosebug/58264344/index.spec.ts"

 PASS  src/Whosebug/58264344/index.spec.ts
  test suites
    ✓ functional-approach-2 perforance test (18ms)

  console.info src/Whosebug/58264344/index.spec.ts:22
    Functional Approach 2 Performance Test

  console.log src/Whosebug/58264344/index.spec.ts:4
    0

  console.info src/Whosebug/58264344/index.spec.ts:28
    Length: 0

  console.info src/Whosebug/58264344/index.spec.ts:29
    Time Taken: 5ms

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        5.67s, estimated 9s

未设置process.env.PERFORMANCE_TEST环境变量值时不运行单元测试:

npm t -- /Users/elsa/workspace/github.com/mrdulin/jest-codelab/src/Whosebug/58264344/index.spec.ts

> jest-codelab@1.0.0 test /Users/elsa/workspace/github.com/mrdulin/jest-codelab
> jest --detectOpenHandles "/Users/elsa/workspace/github.com/mrdulin/jest-codelab/src/Whosebug/58264344/index.spec.ts"

 PASS  src/Whosebug/58264344/index.spec.ts
  test suites
    ✓ functional-approach-2 perforance test (11ms)

  console.warn src/Whosebug/58264344/index.spec.ts:11
    [skipped]: functional-approach-2 perforance test

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        2.758s, estimated 5s
const itif = (condition) => condition ? it : it.skip;

describe('suite name', () => {
  itif(true)('test name', async () => {
    // Your test
  });
});

与接受的答案相同:

const maybe = process.env.JEST_ALLOW_INTEG ? describe : describe.skip;
maybe('Integration', () => {
  test('some integration test', async () => {
    expect(1).toEqual(1);
    return;
  });
});

接受的 post 的一个小变体,但是如果我们将 Jest 的 test.skip(...) 与现代 JS 允许的盲目参数转发类型结合起来,这要归功于 spread operator,我们可以得到一个更清晰的解决方案,有条件地 运行s 测试,同时让 Jest 知道它跳过了一些“官方方式”,而不需要“functionfunction”调用:

const testIf = (condition, ...args) =>
  condition ? test(...args) : test.skip(...args);

describe(`a mix of tests and conditional tests`, () => {
  test(`this will always run`, () => {
    expect("1").toBe("1");
  });

  testIf(Math.random() > 0.5, `this will only run half the time`, () => {
    expect("2").toBe("2");
  });
});

一半时间这将 运行 为:

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        0.451 s, estimated 1 s

一半时间会显示:

Test Suites: 1 passed, 1 total
Tests:       1 skipped, 1 passed, 2 total
Snapshots:   0 total
Time:        0.354 s, estimated 1 s

但是为了涵盖似乎没有人包含在他们的答案中的部分,我们可以使用它来跳过长时间的 运行ning 测试,方法是将它与“查看 process.argv for 运行时间标志":

const runLong = process.argv.includes(`--run-long`);

const testIf = (condition, ...args) =>
  condition ? test(...args) : test.skip(...args);

describe(`Run tests, and long tests only if told to`, () => {

  // ...

  testIf(runLong, `Some long-running test, skip if --run-long is not set`, () => {
    // a test that runs for a long time here
  });
});

然后我们可以将 运行time 标志放入我们的 npm 脚本中。但是,我们需要确保将该标志转发到我们的脚本,而不是开玩笑或 npm:

...
"scripts": {
  ...
  "test": "jest somedir",
  "test:long": "npm run test -- -- --run-long",
  ...
},
...

这看起来有点奇怪,有点奇怪,但这是 npm 脚本的参数转发方式的结果:

  1. 第一个 -- 告诉 npm 它需要转发后面的内容,而不是解释该标志本身(实际上:这使得 npm 运行 jest somedir -- --run-long).
  2. 第二个 -- 告诉 jest 它需要转发接下来的内容,而不是将其视为自己的 运行time 标志,以便 我们的脚本可以在它的process.argv列表中看到它(所以我们调用ourscript --run-long)。

一个常见的错误是忘记了第二个 --,这会导致一个有趣的错误,它不会告诉您只是忘记了两个破折号,根本没有测试 运行ning。