天天看點

Jest測試文法系列之Globals

在上一篇文章中,我們主要介紹了​​Jest測試架構文法系列之Matchers​​​的相關内容,本篇主要涉及的是Global Functions(全局函數),也是官方提供給開發者的核心功能之一。官方API位址為:​​https://jestjs.io/docs/en/api。​​

方法

  • afterAll(fn, timeout)
  • afterEach(fn, timeout)
  • beforeAll(fn, timeout)
  • beforeEach(fn, timeout)
  • describe(name, fn)
  • describe.each(table)(name, fn, timeout)
  • describe.only(name, fn)
  • describe.only.each(table)(name, fn)
  • describe.skip(name, fn)
  • describe.skip.each(table)(name, fn)
  • test(name, fn, timeout)
  • test.each(table)(name, fn, timeout)
  • test.only(name, fn, timeout)
  • test.only.each(table)(name, fn)
  • test.skip(name, fn)
  • test.skip.each(table)(name, fn)

Global

下面就列舉Jest中常見的一些全局函數,欲知更多細節,請通路​​Jest官方文檔​​。

afterAll(fn, timeout)

此API的意思是,它是在所有測試運作完之後才會執行的,如果你的測試中包含promise,則将會等待promise被驗證之後被執行。

當然,你還可以提供一個timeout的參數(以毫秒為機關),用于指定在終止前等待的時間。預設的逾時時間是5秒。

如果想要清理一些跨測試共享的全局設定狀态,afterAll也是有用的。

const globalDatabase = makeGlobalDatabase();

function cleanUpDatabase(db) {
  db.cleanUp();
}

afterAll(() => {
  cleanUpDatabase(globalDatabase);
});

test('can find things', () => {
  return globalDatabase.find('thing', {}, results => {
    expect(results.length).toBeGreaterThan(0);
  });
});

test('can insert a thing', () => {
  return globalDatabase.insert('thing', makeThing(), response => {
    expect(response.success).toBeTruthy();
  });
});      

需要說明的是,afterAll確定在所有測試運作後調用cleanUpDatabase。

并且,如果你想在每次測試之後運作一些清理,而不是在所有測試之後,請使用afterEach代替。

afterEach(fn, timeout)

在該檔案中的每一個測試完成後運作一個函數,如果函數傳回一個promise,Jest會等待該promise在繼續之前解決。

當然,你還可以提供一個逾時(以毫秒為機關),用于指定在終止前等待的時間。afterEach預設的逾時是5秒。

如果您想清除每個測試建立的臨時狀态,afterEach通常也是有用的。

const globalDatabase = makeGlobalDatabase();

function cleanUpDatabase(db) {
  db.cleanUp();
}

afterEach(() => {
  cleanUpDatabase(globalDatabase);
});

test('can find things', () => {
  return globalDatabase.find('thing', {}, results => {
    expect(results.length).toBeGreaterThan(0);
  });
});

test('can insert a thing', () => {
  return globalDatabase.insert('thing', makeThing(), response => {
    expect(response.success).toBeTruthy();
  });
});      

需要注意的是,afterEach確定在每次測試運作後調用cleanUpDatabase。如果每個都在一個描述塊内,它隻在這個描述塊内的測試之後運作。如果隻想在運作完所有測試之後運作一些清理工作,那麼使用afterAll代替。

beforeAll(fn, timeout)

在該檔案運作的任何測試之前運作一個函數,如果函數傳回一個承諾,則Jest會等待在運作測試之前解決這個問題。

當然,你還可以提供一個逾時(以毫秒為機關),用于指定在終止前等待的時間,預設的逾時是5秒。

如果你想設定一些将被許多測試使用的全局狀态,beforeAll通常也是有用的。

const globalDatabase = makeGlobalDatabase();

beforeAll(() => {
  // Clears the database and adds some testing data.
  // Jest will wait for this promise to resolve before running tests.
  return globalDatabase.clear().then(() => {
    return globalDatabase.insert({testData: 'foo'});
  });
});

// Since we only set up the database once in this example, it's important
// that our tests don't modify it.
test('can find things', () => {
  return globalDatabase.find('thing', {}, results => {
    expect(results.length).toBeGreaterThan(0);
  });
});      

如果beforeAll在一個描述塊中,它在描述塊的開始處運作。 如果你想在每次測試之前運作一些東西,而不是在任何測試之前運作,那麼請在每個測試之前使用。

beforeEach(fn, timeout)

在該檔案運作的每個測試之前運作一個函數,如果函數傳回一個promise,Jest将等待該承諾在運作測試之前解決。

你還可以提供一個逾時(以毫秒為機關),用于指定在終止前等待的時間,預設的逾時是5秒。

如果你想要重置一些将被許多測試所使用的全局狀态,beforeEach通常也是有用的。

const globalDatabase = makeGlobalDatabase();

beforeEach(() => {
  // Clears the database and adds some testing data.
  // Jest will wait for this promise to resolve before running tests.
  return globalDatabase.clear().then(() => {
    return globalDatabase.insert({testData: 'foo'});
  });
});

test('can find things', () => {
  return globalDatabase.find('thing', {}, results => {
    expect(results.length).toBeGreaterThan(0);
  });
});

test('can insert a thing', () => {
  return globalDatabase.insert('thing', makeThing(), response => {
    expect(response.success).toBeTruthy();
  });
});      

如上,測試代碼的含義是在每個測試都要重置資料庫。如果在一個描述塊内部,它運作在描述塊中的每個測試。如果你隻需要運作一些設定代碼,在任何測試運作之前,就使用之前的所有代碼。

describe(name, fn)

describe(name, fn)建立一個塊,在一個“測試套件”中,将幾個相關的測試組合在一起。

const myBeverage = {
  delicious: true,
  sour: false,
};

describe('my beverage', () => {
  test('is delicious', () => {
    expect(myBeverage.delicious).toBeTruthy();
  });

  test('is not sour', () => {
    expect(myBeverage.sour).toBeFalsy();
  });
});      

當然,這不是必需的。你可以直接在頂層編寫測試塊,但是,如果您希望将測試組織成組,那麼這就很友善,且利于檢視和維護。

const binaryStringToNumber = binString => {
  if (!/^[01]+$/.test(binString)) {
    throw new CustomError('Not a binary number.');
  }

  return parseInt(binString, 2);
};

describe('binaryStringToNumber', () => {
  describe('given an invalid binary string', () => {
    test('composed of non-numbers throws CustomError', () => {
      expect(() => binaryStringToNumber('abc')).toThrowError(CustomError);
    });

    test('with extra whitespace throws CustomError', () => {
      expect(() => binaryStringToNumber('  100')).toThrowError(CustomError);
    });
  });

  describe('given a valid binary string', () => {
    test('returns the correct number', () => {
      expect(binaryStringToNumber('100')).toBe(4);
    });
  });
});      

describe.only(name, fn)

如果你隻想運作一次子產品測試的話,可以使用 describe.only。

describe.only('my beverage', () => {
  test('is delicious', () => {
    expect(myBeverage.delicious).toBeTruthy();
  });

  test('is not sour', () => {
    expect(myBeverage.sour).toBeFalsy();
  });
});

describe('my other beverage', () => {
  // ... will be skipped
});      

describe.skip(name, fn)

describe 等價于 xdescribe。可以使用skip 跳過某一個測試。

describe('my beverage', () => {
  test('is delicious', () => {
    expect(myBeverage.delicious).toBeTruthy();
  });

  test('is not sour', () => {
    expect(myBeverage.sour).toBeFalsy();
  });
});

describe.skip('my other beverage', () => {
  // ... will be skipped
});      

使用跳過通常隻是一種比較簡單的替代方法,如果不想運作則可以暫時将大量的測試注釋掉。

test(name, fn, timeout)

test(name, fn, timeout) 等價于 it(name, fn, timeout)。在測試檔案中,您所需要的是運作測試的測試方法。例如,假設有一個函數inchesOfRain()應該是零。

test('did not rain', () => {
  expect(inchesOfRain()).toBe(0);
});      

其中,第一個參數是測試名稱,第二個參數是包含測試期望的函數,第三個參數(可選)是逾時(以毫秒為機關),用于指定在中止前等待多長時間,預設的逾時是5秒。

如果測試傳回了一個promise,Jest會在測試完成之前等待promise。Jest還将等待,如果你為測試函數提供一個參數,通常稱為done。當你想要測試回調時,這将非常友善。請參見如何在此測試異步代碼。

例如,假設fetchBeverageList()傳回一個承諾,該承諾将解析到其中有lemon的清單。

test('has lemon in it', () => {
  return fetchBeverageList().then(list => {
    expect(list).toContain('lemon');
  });
});      

在上面的測試例子中,即使對測試的調用會立即傳回,測試也不會完成,直到promise解決。

test.only(name, fn, timeout)

test.only(name, fn, timeout)等同于 it.only(name, fn, timeout) or fit(name, fn, timeout)

在調試大型代碼庫時,有時候你隻希望運作一個子集的測試。 test.only可以指定哪些測試是您想要運作的。

當然,您還可以提供一個逾時(以毫秒為機關),用于指定在終止前等待的時間。預設的逾時是5秒。

test.only('it is raining', () => {
  expect(inchesOfRain()).toBeGreaterThan(0);
});

test('it is not snowing', () => {
  expect(inchesOfSnow()).toBe(0);
});      

test.skip(name, fn)

test.skip(name, fn)等同于it.skip(name, fn) or xit(name, fn) or xtest(name, fn)

當您維護一個大型的代碼庫時,您可能有時會發現由于某種原因而臨時中斷的測試。

test('it is raining', () => {
  expect(inchesOfRain()).toBeGreaterThan(0);
});

test.skip('it is not snowing', () => {
  expect(inchesOfSnow()).toBe(0);
});      

test.skip.each(table)(name, fn)

test.skip.each([[1, 1, 2], [1, 2, 3], [2, 1, 3]])(
  '.add(%i, %i)',
  (a, b, expected) => {
    expect(a + b).toBe(expected); // will not be ran
  },
);

test('will be ran', () => {
  expect(1 / 0).toBe(Infinity);
});      

繼續閱讀