Inicialización y Finalización
Frecuentemente cuando escribes las pruebas tienes algo de trabajo de inicialización que necesita ejecutarse antes de correr las pruebas, y tienes trabajo de finalización que debe ejecutarse luego de correr las pruebas. Jest provee funciones para manejar esto.
Repeating Setup
If you have some work you need to do repeatedly for many tests, you can use beforeEach
and afterEach
hooks.
Por ejemplo, digamos que varias pruebas interactúan con la base de datos de ciudades. Tienes un método initializeCityDatabase()
que debe ser llamada antes de cada prueba, y un método clearCityDatabase()
que debe ser llamado luego de cada prueba. Puedes hacer esto con:
beforeEach(() => {
initializeCityDatabase();
});
afterEach(() => {
clearCityDatabase();
});
test('city database has Vienna', () => {
expect(isCity('Vienna')).toBeTruthy();
});
test('city database has San Juan', () => {
expect(isCity('San Juan')).toBeTruthy();
});
beforeEach
y afterEach
pueden manejar código asíncrono en el mismo modo que las pruebas manejan código asíncrono - ambos pueden tomar done
como parámetro o devolver una promesa. Por ejemplo, si initializeCityDatabase()
devuelve una promesa que es resuelta cuando la base de datos es inicializada, nos gustaría que devuelva esa promesa:
beforeEach(() => {
return initializeCityDatabase();
});
Inicialización una vez antes de todos los tests
En algunos casos, solo necesitarás realizar la preparación una sola vez, al principio del archivo. Esto puede ser especialmente molesto cuando la inicialización es asíncrona, y no puede hacerse simplemente en una sola línea. Jest provides beforeAll
and afterAll
hooks to handle this situation.
For example, if both initializeCityDatabase()
and clearCityDatabase()
returned promises, and the city database could be reused between tests, we could change our test code to:
beforeAll(() => {
return initializeCityDatabase();
});
afterAll(() => {
return clearCityDatabase();
});
test('city database has Vienna', () => {
expect(isCity('Vienna')).toBeTruthy();
});
test('city database has San Juan', () => {
expect(isCity('San Juan')).toBeTruthy();
});
Alcance
The top level before*
and after*
hooks apply to every test in a file. The hooks declared inside a describe
block apply only to the tests within that describe
block.
Por ejemplo, supongamos que hemos tenido no sólo una base de datos de ciudades, sino también una base de datos de alimentos. Podríamos hacer una configuración diferente para diferentes pruebas:
// Applies to all tests in this file
beforeEach(() => {
return initializeCityDatabase();
});
test('city database has Vienna', () => {
expect(isCity('Vienna')).toBeTruthy();
});
test('city database has San Juan', () => {
expect(isCity('San Juan')).toBeTruthy();
});
describe('matching cities to foods', () => {
// Applies only to tests in this describe block
beforeEach(() => {
return initializeFoodDatabase();
});
test('Vienna <3 veal', () => {
expect(isValidCityFoodPair('Vienna', 'Wiener Schnitzel')).toBe(true);
});
test('San Juan <3 plantains', () => {
expect(isValidCityFoodPair('San Juan', 'Mofongo')).toBe(true);
});
});
Ten en cuenta que el beforeEach
de nivel superior será ejecutado antes del beforeEach
dentro del describe
. Puede ayudar a ilustrar el orden de ejecución de todos los hooks.
beforeAll(() => console.log('1 - beforeAll'));
afterAll(() => console.log('1 - afterAll'));
beforeEach(() => console.log('1 - beforeEach'));
afterEach(() => console.log('1 - afterEach'));
test('', () => console.log('1 - test'));
describe('Scoped / Nested block', () => {
beforeAll(() => console.log('2 - beforeAll'));
afterAll(() => console.log('2 - afterAll'));
beforeEach(() => console.log('2 - beforeEach'));
afterEach(() => console.log('2 - afterEach'));
test('', () => console.log('2 - test'));
});
// 1 - beforeAll
// 1 - beforeEach
// 1 - test
// 1 - afterEach
// 2 - beforeAll
// 1 - beforeEach
// 2 - beforeEach
// 2 - test
// 2 - afterEach
// 1 - afterEach
// 2 - afterAll
// 1 - afterAll
Order of Execution
Jest ejecuta todos los manejadores de los describes en el archivo de tests antes que se ejecute alguno de los tests. This is another reason to do setup and teardown inside before*
and after*
handlers rather than inside the describe
blocks. Once the describe
blocks are complete, by default Jest runs all the tests serially in the order they were encountered in the collection phase, waiting for each to finish and be tidied up before moving on.
Considere el siguiente archivo de prueba ilustrativa y su respectiva salida:
describe('describe outer', () => {
console.log('describe outer-a');
describe('describe inner 1', () => {
console.log('describe inner 1');
test('test 1', () => console.log('test 1'));
});
console.log('describe outer-b');
test('test 2', () => console.log('test 2'));
describe('describe inner 2', () => {
console.log('describe inner 2');
test('test 3', () => console.log('test 3'));
});
console.log('describe outer-c');
});
// describe outer-a
// describe inner 1
// describe outer-b
// describe inner 2
// describe outer-c
// test 1
// test 2
// test 3
Just like the describe
and test
blocks Jest calls the before*
and after*
hooks in the order of declaration. Note that the after*
hooks of the enclosing scope are called first. For example, here is how you can set up and tear down resources which depend on each other:
beforeEach(() => console.log('connection setup'));
beforeEach(() => console.log('database setup'));
afterEach(() => console.log('database teardown'));
afterEach(() => console.log('connection teardown'));
test('test 1', () => console.log('test 1'));
describe('extra', () => {
beforeEach(() => console.log('extra database setup'));
afterEach(() => console.log('extra database teardown'));
test('test 2', () => console.log('test 2'));
});
// connection setup
// database setup
// test 1
// database teardown
// connection teardown
// connection setup
// database setup
// extra database setup
// test 2
// extra database teardown
// database teardown
// connection teardown
If you are using jasmine2
test runner, take into account that it calls the after*
hooks in the reverse order of declaration. To have identical output, the above example should be altered like this:
beforeEach(() => console.log('connection setup'));
+ afterEach(() => console.log('connection teardown'));
beforeEach(() => console.log('database setup'));
+ afterEach(() => console.log('database teardown'));
- afterEach(() => console.log('database teardown'));
- afterEach(() => console.log('connection teardown'));
// ...
Aviso General
Si una prueba falla, una de las primeras cosas a revisar debería ser si la prueba falla cuando se corre solo esa prueba. Para correr un único test en Jest, cambie temporalmente test
a test.only
:
test.only('this will be the only test that runs', () => {
expect(true).toBe(false);
});
test('this test will not run', () => {
expect('A').toBe('A');
});
Si tienes una prueba que a veces falla cuando se ejecuta junto a toda la suite, pero no falla cuando la corres individualmente, es probable que no haya independencia entre los tests. A veces puedes arreglar esto limpiando estados compartidos con beforeEach
. Si no estás seguro de que algun estado compartido se esté modificando, puedes probar un beforeEach
que imprima los datos.