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.
Reutilizando la inicialización para varias pruebas
Si tienes algo de trabajo que necesitas hacer repetidamente para muchas pruebas, puedes usar beforeEach
y afterEach
.
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 proporciona beforeAll
y afterAll
para manejar esta situación.
Por ejemplo, si initializeCityDatabase
y clearCityDatabase
devolvieron promesas, y la base de datos de de ciudades podría ser reutilizado entre pruebas, podríamos cambiar nuestro código de prueba para:
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
Orden de ejecución de describe y bloques de tests
Jest ejecuta todos los manejadores de los describes en el archivo de tests antes que se ejecute alguno de los tests. Esta es otra razón para inicializar y desmontar en los before*
y after*
en vez de en los describe
. Una vez que los describe
están completos, por defecto Jest corre todas las pruebas en serie en el orden que fueron escritas en la fase de colección, esperando que cada una termine antes de avanzar.
Considere el siguiente archivo de prueba ilustrativa y su respectiva salida:
describe('outer', () => {
console.log('describe outer-a');
describe('describe inner 1', () => {
console.log('describe inner 1');
test('test 1', () => {
console.log('test for describe inner 1');
expect(true).toBe(true);
});
});
console.log('describe outer-b');
test('test 1', () => {
console.log('test for describe outer');
expect(true).toBe(true);
});
describe('describe inner 2', () => {
console.log('describe inner 2');
test('test for describe inner 2', () => {
console.log('test for describe inner 2');
expect(false).toBe(false);
});
});
console.log('describe outer-c');
});
// describe outer-a
// describe inner 1
// describe outer-b
// describe inner 2
// describe outer-c
// test for describe inner 1
// test for describe outer
// test for describe inner 2
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.