在 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 脚本的参数转发方式的结果:
- 第一个
--
告诉 npm 它需要转发后面的内容,而不是解释该标志本身(实际上:这使得 npm 运行 jest somedir -- --run-long
).
- 第二个
--
告诉 jest 它需要转发接下来的内容,而不是将其视为自己的 运行time 标志,以便 我们的脚本可以在它的process.argv
列表中看到它(所以我们调用ourscript --run-long
)。
一个常见的错误是忘记了第二个 --
,这会导致一个有趣的错误,它不会告诉您只是忘记了两个破折号,根本没有测试 运行ning。
我一直在比较函数式范式和面向对象范式。
作为其中的一部分 - 我想做一些性能测试。
我现在有一些看起来像这样的测试:
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 脚本的参数转发方式的结果:
- 第一个
--
告诉 npm 它需要转发后面的内容,而不是解释该标志本身(实际上:这使得 npm 运行jest somedir -- --run-long
). - 第二个
--
告诉 jest 它需要转发接下来的内容,而不是将其视为自己的 运行time 标志,以便 我们的脚本可以在它的process.argv
列表中看到它(所以我们调用ourscript --run-long
)。
一个常见的错误是忘记了第二个 --
,这会导致一个有趣的错误,它不会告诉您只是忘记了两个破折号,根本没有测试 运行ning。