Jest 設(shè)置和拆卸

2021-09-04 10:13 更新

寫(xiě)測(cè)試的時(shí)候你經(jīng)常需要在運(yùn)行測(cè)試前做一些準(zhǔn)備工作,和在運(yùn)行測(cè)試后進(jìn)行一些整理工作。 Jest 提供輔助函數(shù)來(lái)處理這個(gè)問(wèn)題。

為多次測(cè)試重復(fù)設(shè)置

如果你有一些要為多次測(cè)試重復(fù)設(shè)置的工作,你可以使用 ?beforeEach ?和 ?afterEach?。

例如,我們考慮一些與城市信息數(shù)據(jù)庫(kù)進(jìn)行交互的測(cè)試。 你必須在每個(gè)測(cè)試之前調(diào)用方法 ?initializeCityDatabase() ?,同時(shí)必須在每個(gè)測(cè)試后,調(diào)用方法 ?clearCityDatabase()?。 你可以這樣做:

  1. beforeEach(() => {
  2. initializeCityDatabase();
  3. });
  4. afterEach(() => {
  5. clearCityDatabase();
  6. });
  7. test('city database has Vienna', () => {
  8. expect(isCity('Vienna')).toBeTruthy();
  9. });
  10. test('city database has San Juan', () => {
  11. expect(isCity('San Juan')).toBeTruthy();
  12. });

?beforeEach ?和 ?afterEach ?能夠通過(guò)與 異步代碼測(cè)試 相同的方式處理異步代碼 — — 他們可以采取 ?done ?參數(shù)或返回一個(gè) promise。 例如,如果 ?initializeCityDatabase() ?返回解決數(shù)據(jù)庫(kù)初始化時(shí)的 promise ,我們會(huì)想返回這一 promise︰

  1. beforeEach(() => {
  2. return initializeCityDatabase();
  3. });

一次性設(shè)置

在某些情況下,你只需要在文件的開(kāi)頭做一次設(shè)置。當(dāng)設(shè)置是異步的時(shí),這可能會(huì)特別麻煩,因此你就不能內(nèi)聯(lián)執(zhí)行。Jest 提供 ?beforeAll ?和 ?afterAll ?處理這種情況。

例如,如果 ?initializeCityDatabase ?和 ?clearCityDatabase ?都返回了 promise ,城市數(shù)據(jù)庫(kù)可以在測(cè)試中重用,我們就能把我們的測(cè)試代碼改成這樣:

  1. beforeAll(() => {
  2. return initializeCityDatabase();
  3. });
  4. afterAll(() => {
  5. return clearCityDatabase();
  6. });
  7. test('city database has Vienna', () => {
  8. expect(isCity('Vienna')).toBeTruthy();
  9. });
  10. test('city database has San Juan', () => {
  11. expect(isCity('San Juan')).toBeTruthy();
  12. });

作用域

默認(rèn)情況下,?before ?和 ?after ?的塊可以應(yīng)用到文件中的每個(gè)測(cè)試。 此外可以通過(guò) ?describe ?塊來(lái)將測(cè)試分組。 當(dāng) ?before ?和 ?after ?的塊在 ?describe ?塊內(nèi)部時(shí),則其只適用于該 ?describe ?塊內(nèi)的測(cè)試。

例如,我們不僅有一個(gè)城市數(shù)據(jù)庫(kù),而且還有一個(gè)食品數(shù)據(jù)庫(kù)。 我們可以為不同的測(cè)試進(jìn)行不同的設(shè)置:

  1. // Applies to all tests in this file
  2. beforeEach(() => {
  3. return initializeCityDatabase();
  4. });
  5. test('city database has Vienna', () => {
  6. expect(isCity('Vienna')).toBeTruthy();
  7. });
  8. test('city database has San Juan', () => {
  9. expect(isCity('San Juan')).toBeTruthy();
  10. });
  11. describe('matching cities to foods', () => {
  12. // Applies only to tests in this describe block
  13. beforeEach(() => {
  14. return initializeFoodDatabase();
  15. });
  16. test('Vienna <3 sausage', () => {
  17. expect(isValidCityFoodPair('Vienna', 'Wiener Schnitzel')).toBe(true);
  18. });
  19. test('San Juan <3 plantains', () => {
  20. expect(isValidCityFoodPair('San Juan', 'Mofongo')).toBe(true);
  21. });
  22. });

注意,頂級(jí)的 ?beforeEach ?在 ?describe ?塊級(jí)的 ?beforeEach ?之前被執(zhí)行。 這可能有助于說(shuō)明所有鉤子的執(zhí)行順序。

  1. beforeAll(() => console.log('1 - beforeAll'));
  2. afterAll(() => console.log('1 - afterAll'));
  3. beforeEach(() => console.log('1 - beforeEach'));
  4. afterEach(() => console.log('1 - afterEach'));
  5. test('', () => console.log('1 - test'));
  6. describe('Scoped / Nested block', () => {
  7. beforeAll(() => console.log('2 - beforeAll'));
  8. afterAll(() => console.log('2 - afterAll'));
  9. beforeEach(() => console.log('2 - beforeEach'));
  10. afterEach(() => console.log('2 - afterEach'));
  11. test('', () => console.log('2 - test'));
  12. });
  13. // 1 - beforeAll
  14. // 1 - beforeEach
  15. // 1 - test
  16. // 1 - afterEach
  17. // 2 - beforeAll
  18. // 1 - beforeEach
  19. // 2 - beforeEach
  20. // 2 - test
  21. // 2 - afterEach
  22. // 1 - afterEach
  23. // 2 - afterAll
  24. // 1 - afterAll

describe 和 test 塊的執(zhí)行順序

Jest 會(huì)在所有真正的測(cè)試開(kāi)始之前執(zhí)行測(cè)試文件里所有的 describe 處理程序(handlers)。 這是在 ?before* ?和 ?after* ?處理程序里面 (而不是在 describe 塊中)進(jìn)行準(zhǔn)備工作和整理工作的另一個(gè)原因。 默認(rèn)情況下,當(dāng) describe 塊運(yùn)行完后,Jest 會(huì)按照 test 出現(xiàn)的順序(譯者注:原文是in the order they were encountered in the collection phase)依次運(yùn)行所有測(cè)試,,等待每一個(gè)測(cè)試完成并整理好,然后才繼續(xù)往下走。

考慮以下示例測(cè)試文件和輸出:

  1. describe('outer', () => {
  2. console.log('describe outer-a');
  3. describe('describe inner 1', () => {
  4. console.log('describe inner 1');
  5. test('test 1', () => {
  6. console.log('test for describe inner 1');
  7. expect(true).toEqual(true);
  8. });
  9. });
  10. console.log('describe outer-b');
  11. test('test 1', () => {
  12. console.log('test for describe outer');
  13. expect(true).toEqual(true);
  14. });
  15. describe('describe inner 2', () => {
  16. console.log('describe inner 2');
  17. test('test for describe inner 2', () => {
  18. console.log('test for describe inner 2');
  19. expect(false).toEqual(false);
  20. });
  21. });
  22. console.log('describe outer-c');
  23. });
  24. // describe outer-a
  25. // describe inner 1
  26. // describe outer-b
  27. // describe inner 2
  28. // describe outer-c
  29. // test for describe inner 1
  30. // test for describe outer
  31. // test for describe inner 2

通用建議

如果測(cè)試失敗,第一件要檢查的事就是,當(dāng)僅運(yùn)行這條測(cè)試時(shí),它是否仍然失敗。 要使用Jest僅運(yùn)行一個(gè)?test?,請(qǐng)將該測(cè)試命令臨時(shí)更改為?test.only?:

  1. test.only('this will be the only test that runs', () => {
  2. expect(true).toBe(false);
  3. });
  4. test('this test will not run', () => {
  5. expect('A').toBe('A');
  6. });

如果你有一個(gè)測(cè)試,當(dāng)它作為一個(gè)更大的用例中的一部分時(shí),經(jīng)常運(yùn)行失敗,但是當(dāng)你單獨(dú)運(yùn)行它時(shí),并不會(huì)失敗,所以最好考慮其他測(cè)試對(duì)這個(gè)測(cè)試的影響。 通常可以通過(guò)修改 ?beforeEach ?來(lái)清除一些共享的狀態(tài)來(lái)修復(fù)這種問(wèn)題。 如果不確定是否正在修改某些共享狀態(tài),也可以嘗試使用?beforeEach?記錄數(shù)據(jù)。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)