You cannot pass a variable set in the beforeAll block as a parameter to a parameterized test, as .each is run before beforeAll.
let values
beforeAll(() => {
values = ['hello', 'world']
})
describe('test setting variable in before all', () => {
test('non-parameterized', () => {
expect(values).toHaveLength(2) // passes
})
test.each(values)('parameterized', (value) => {
expect(value).toBeDefined() // fails - values is undefined
})
let otherValues = [1, 2, 3]
test.each(otherValues)('parameterized with variable set right before test', (value) => {
expect(value).toBeDefined() // passes
})
})
The beforeAll block should run before a parameterized test, in order to match the behaviour in non-parameterized tests.
N/A see block of code above
npx envinfo --preset jest System:
OS: macOS High Sierra 10.13.6
CPU: x64 Intel(R) Core(TM) i7-7820HQ CPU @ 2.90GHz
Binaries:
Node: 8.9.4 - ~/.nvm/versions/node/v8.9.4/bin/node
npm: 6.1.0 - ~/.nvm/versions/node/v8.9.4/bin/npm
npmPackages:
jest: ^23.4.0 => 23.4.0
@mattphillips what do you think about this?
All tests tests and hooks are collected before we start executing any of them, so you cannot use dynamic data from a hook to define its or tests (which .each is sugar for)
Related issue: https://github.com/facebook/jest/issues/6888
As @SimenB said tests need to be defined synchronously. Perhaps we should add this to the docs?
Ah, we've added an error message now! Nice.
I'm fine with adding a note in the FAQ or something, a lot of people want to use stuff in beforeAll/Each when defining tests (mostly because of async work). Having it in the docs makes sense to me!
EDIT: We should probably throw on empty arrays as well, not just non-arrays
FWIW, I've also run into this and expected beforeAll() to actually complete before test.each().
The documentation on test.each doesn't say anything about this.
@dandv it's documented under troubleshooting - hope that helps
If anyone needs to compute variables dynamically in beforeAll block, here is a way to do so: pass function references instead of values. Code example:
let values;
function getFirstValue() {
return values[0];
}
function getSecondValue() {
return values[1];
}
beforeAll(() => {
// Values of the array are computed dynamically
values = ['hello', 'world'];
});
describe('Test setting variables in beforeAll', () => {
test.each([getFirstValue, getSecondValue])('parameterized', (valueFn) => {
let value = valueFn();
// the rest of the test code...
})
});
If the data array is long, one could experiment with iterators like this:
let values;
let i = -1;
function getValue() {
i++;
return values[i];
}
beforeAll(() => {
values = ['hello', 'world'];
});
describe('Test setting variables in beforeAll', () => {
test.each([getValue, getValue])('parameterized', (valueFn) => {
let value = valueFn();
// the rest of the test code...
})
});
Most helpful comment
If anyone needs to compute variables dynamically in beforeAll block, here is a way to do so: pass function references instead of values. Code example:
If the data array is long, one could experiment with iterators like this: