Jest looping through dynamic test cases
Solution 1
There's an in-built way to do this: test.each(table)(name, fn, timeout)
e.g.
test.each([[1, 1, 2], [1, 2, 3], [2, 1, 3]])(
'.add(%i, %i)',
(a, b, expected) => {
expect(a + b).toBe(expected);
},
);
where each inner array in the 2D array is passed as args to the test function.
Solution 2
If one passes, they all will. So you only need one for a positive test. Ideally, you want 1 positive where the 2 numbers equal the sum, and a failure where you pass a string or something and throw an error.
TL/DR; You don't need 4 tests that all do the same thing. Also, you need to pull the looped test cases out of the parent test for the loop to work.
This will work just fine:
import jest from 'jest';
import { sumModule } from './';
const tests = [
{x: 1, y: 2, r: 3},
{x: 3, y: 4, r: 7}
];
describe('Adding method', () => {
for(let i = 0; i < tests.length; i++){
it('should add its params', () => {
const actual = sumModule(tests[i].x, tests[i].y);
expect(actual).toBe(tests[i].r);
});
}
});
Solution 3
If anyone wondering how this can work for a single input function here is an example
const testData = [
['input1', 'output1'],
['input2', 'output2'],
['input3', 'output3'],
]
test.each(testData)('myFunc work correctly for %s',(input, output) =>{
expect(yourFunc(input)).toBe(output)
})
https://jestjs.io/docs/en/api#testeachtablename-fn-timeout
Solution 4
You can use classic JS, it is more readable and with less code:
[
{ input: [2, 3], output: 5 },
{ input: [1, 2], output: 3 },
].forEach(({ input, output }) => {
it(`works correctly for ${input}`, () => {
// ...
expect(...).toBe(output);
});
})
Comments
-
mehari over 2 years
How do I loop through dynamic test cases in Jest?
I have test cases like the following how do I dynamically create jest test case using
it/test
methods.Here is what I have tried , However it just passes without excuting the test cases in the loop.
const mymodule = require('mymodule'); const testCases = [ {q: [2, 3],r: 5}, {q: [1, 2],r: 3}, {q: [7, 0],r: 7}, {q: [4, 4],r: 8} ]; describe("Test my Math module", () => { test("test add method", () => { for (let i = 0; i < testCases.length; i++) { const { q,r } = testCases[i]; it(`should add ${q[0]},${q[1]} to ${expected}`, () => { const actual = mymodule.add(q[0] + q[1]); expect(actual).toBe(expected); }); } }); });
-
Kevin Farrugia over 5 yearsUnfortunately the same is not possible when looping through dynamic test cases generated from an async operation. :( github.com/facebook/jest/issues/1619#issuecomment-358576732
-
Kevin Farrugia over 5 yearsYes. Doesn't work when iterating through async config, irrelevant of the method. :(
-
M.Abulsoud over 4 yearsI have a code block async in beforeAll, and I want to generate test cases based on the results of the code block in the beforeAll. It keep write
Your test suite must contain at least one test.
-
justin almost 3 years@nickang yes it can be useful. I have also found use of
expect(result).toMatchInlineSnapshot(<string>)
to be useful if the output under test can be rendered to string (this doesn't have to be JSX, you can e.g. render a JSON data structure and snapshot match against it). -
GhostBytes over 2 yearsThis should be the answer. It's easier to write, read and work with. Being able to user interpolation on the test name is a huge advantage as well and enough for me not to use test.each.