I've been playing around comparing the functional paradigm and the object-oriented paradigm.
As part of this - I'm wanting to do some performance tests.
I have some tests that look like this for now:
it("Some long running performance test", () => {
const result = myFunctionWithLotsOfData();
});
For now, I'm just printing how long this code takes to run (around 5000ms).
I like using Jest for all of the assertions and mocking functionality it gives, and it's live reload, etc.
However, I don't want these tests to all the time, I'd run create a npm script like npm test:performance
, and only run these tests if an environment variable is present or similar.
What's the best way to do this?
const itif = (condition) => condition ? it : it.skip;
describe('suite name', () => {
itif(true)('test name', async () => {
// Your test
});
});
Along the same lines as the accepted answer:
const maybe = process.env.JEST_ALLOW_INTEG ? describe : describe.skip;
maybe('Integration', () => {
test('some integration test', async () => {
expect(1).toEqual(1);
return;
});
});
A small variation on the accepted post, but if we combine Jest's test.skip(...)
with the kind of blind argument forwarding that modern JS allows thanks to the spread operator, we can get a cleaner solution that conditionally runs tests, while letting Jest know it skipped something "the official way", without needing a "functionfunction" call:
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");
});
});
Half the time this will run as:
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 0.451 s, estimated 1 s
And half the time it will show:
Test Suites: 1 passed, 1 total
Tests: 1 skipped, 1 passed, 2 total
Snapshots: 0 total
Time: 0.354 s, estimated 1 s
But to cover the part that no one seems to have included in their answers, we can use this to skip over long-running tests by combining it with "looking at process.argv
for a runtime flag":
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
});
});
And then we can just put that runtime flag in our npm script. However, we need to make sure to forward that flag on to our script, rather than to jest, or to npm:
...
"scripts": {
...
"test": "jest somedir",
"test:long": "npm run test -- -- --run-long",
...
},
...
This looks kind of weird, and it is kind of weird, but it's a consequence of how argument forwarding works for npm scripts:
--
tells npm that it needs to forward what follows, rather than interpreting that flag itself (in effect: this makes npm run jest somedir -- --run-long
).--
tells jest that it needs to forward what follows, instead of considering it a runtime flag for itself, so that our script gets to see it in its process.argv
list (so that we call ourscript --run-long
).A common mistake is to forget that second --
, which would lead to a fun error that doesn't tell you that just forgot two dashes, and no tests running at all.
Here is one solution, create itif
function so that we can run the unit tests based on some conditions.
For example, the itif
function:
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();
}
});
};
The unit tests:
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();
}
);
});
Run your unit test when the value of process.env.PERFORMANCE_TEST
environment variable equal 'true'
, the result:
PERFORMANCE_TEST=true npm t -- /Users/elsa/workspace/github.com/mrdulin/jest-codelab/src/stackoverflow/58264344/index.spec.t
> [email protected] test /Users/elsa/workspace/github.com/mrdulin/jest-codelab
> jest --detectOpenHandles "/Users/elsa/workspace/github.com/mrdulin/jest-codelab/src/stackoverflow/58264344/index.spec.ts"
PASS src/stackoverflow/58264344/index.spec.ts
test suites
✓ functional-approach-2 perforance test (18ms)
console.info src/stackoverflow/58264344/index.spec.ts:22
Functional Approach 2 Performance Test
console.log src/stackoverflow/58264344/index.spec.ts:4
0
console.info src/stackoverflow/58264344/index.spec.ts:28
Length: 0
console.info src/stackoverflow/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
Do not run the unit test when the value of process.env.PERFORMANCE_TEST
environment variable is not set:
npm t -- /Users/elsa/workspace/github.com/mrdulin/jest-codelab/src/stackoverflow/58264344/index.spec.ts
> [email protected] test /Users/elsa/workspace/github.com/mrdulin/jest-codelab
> jest --detectOpenHandles "/Users/elsa/workspace/github.com/mrdulin/jest-codelab/src/stackoverflow/58264344/index.spec.ts"
PASS src/stackoverflow/58264344/index.spec.ts
test suites
✓ functional-approach-2 perforance test (11ms)
console.warn src/stackoverflow/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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With