I am familiar with RSpec where it is very easy to reuse test cases by writing shared examples
shared_example_for 'a cute pet' do
it 'tests that the pet is a small' { expect(pet.size).to be_lesser_than(10) }
it 'tests that the pet can smile' { expect(pet.can_smile?).to be }
end
describe 'The Octocat' do
let(:pet) { Octocat.new }
it_behaves_like 'a cute pet'
end
...
describe 'The Doge' do
let(:pet) { Doge.new }
it_behaves_like 'a cute pet'
end
Is there an equivalent in Jest ? Something that would let me reuse variables set in beforeEach() blocks ? I am trying to find a way using something like the following :
# __tests__/cuteness.js
export const cutenessTests = function() {
test('it is small', () => {
expect(petSetInBefore.length).toBeLesserThan(5)
})
test('it can smile', () => {
expect(petSetInBefore.canSmile).toBe(true)
})
}
# __tests__/famous_animals.test.js
import { cutenessTests } from './cuteness'
describe('Famous animals', () => {
let petSetInBefore;
describe('Octocat', () => {
beforeEach(() => {
petSetInBefore = new Octocat();
})
cutenessTests.bind(this)()
})
})
The important here is that I am trying to share multiple test
definitions and not just one, otherwise I could have passed the petSetInBefore to the shared function.
EDIT : each of my tests and nested describe are likely to alter my test environment and objects, so the beforeEach is used to restore a proper test environment. Here is a better example
class Octocat {
get strokeFor(time) {
this.strokeTime = this.strokeTime + time
if (this.strokeTime <= 10) {
this.mood = 'happy'
} else {
this.mood = 'bored'
}
}
}
class Doge {
get strokeFor(time) {
this.strokeTime = this.strokeTime + time
if (this.strokeTime <= 5) {
this.mood = 'happy'
} else {
this.mood = 'bored'
}
}
}
const cutenessTests = function() {
describe('when stroked for a short while', () => {
beforeEach(() => {
petSetInBefore.strokeFor(1);
})
test('it is happy', () => { expect(petSetInBefore.mood).to(eq('happy')) }
describe('when stroked too much', () => {
beforeEach(() => {
petSetInBefore.stroke(1000);
})
test('it gets bored', () => { expect(petSetInBefore.mood).to(eq('bored')) }
})
describe('when stroked a little longer', () => {
beforeEach(() => {
petSetInBefore.strokeFor(4);
})
test('it is still happy', () => { expect(petSetInBefore.mood).to(eq('happy')) }
})
})
}
EDIT2: Here is a repl.it based on Gui3's answer
EDIT3 : the object can be altered before or during the reusable tests
describe('Famous animals', () => {
let petSetInBefore;
describe('Octocat', () => {
beforeEach(() => {
petSetInBefore = new Octocat();
})
describe('when it is not well rested', () => {
beforeEach(() => { petSetInBefore.wellRested() } // Extra object preparation / context before calling reusable examples
cutenessTests()
}),
describe('when it is not well rested', () => {
// Calling reusable examples without extra context
cutenessTests()
})
})
})
beforeEach(fn, timeout) Runs a function before each of the tests in this file runs. If the function returns a promise or is a generator, Jest waits for that promise to resolve before running the test. Optionally, you can provide a timeout (in milliseconds) for specifying how long to wait before aborting.
If beforeEach is inside a describe block, it runs for each test in the describe block. If you only need to run some setup code once, before any tests run, use beforeAll instead.
Jest provides beforeAll and afterAll . As with test / it it will wait for a promise to resolve, if the function returns a promise. beforeAll(() => { return new Promise(resolve => { // Asynchronous task // ...
describe breaks your test suite into components. Depending on your test strategy, you might have a describe for each function in your class, each module of your plugin, or each user-facing piece of functionality. You can also nest describes to further subdivide the suite. it is where you perform individual tests.
If you still want beforeEach,
for reasons ... it works if you declare your variable in the global scope
let petSetInBefore; // here it works
describe('Famous animals', () => {
//let petSetInBefore; // here it's undefined
describe('Octocat', () => {
//let petSetInBefore; // undefined too
beforeAll(() => {
petSetInBefore = new Octocat();
})
cutenessTests() // .bind(this) results the same
});
describe('Doge', () => {
beforeEach(() => {
petSetInBefore = new Doge();
})
cutenessTests.bind(this)()
});
})
https://repl.it/@gui3/jestSharedTests
seems like the tests inside the shared function cannot share variables from beforeEach otherwise ...
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