交易工具

自動化測試基本上只是程式碼,會在下列情況下擲回或導致錯誤: 發生問題大部分的程式庫或測試架構都提供 可更輕鬆地編寫測試的基本功能。

如上一節所述,這些基元通常都包含一個 定義獨立測試 (稱為測試案例) 並提供 斷言。斷言是一種結合檢查結果和擲回 並視為 以及測試基元

本頁說明這些基元的通用做法。您選擇的架構 可能有類似的內容,但並非確切的參考值

例如:

import { fibonacci, catalan } from '../src/math.js';
import { assert, test, suite } from 'a-made-up-testing-library';

suite('math tests', () => {
  test('fibonacci function', () => {
    // check expected fibonacci numbers against our known actual values
    // with an explanation if the values don't match
    assert.equal(fibonacci(0), 0, 'Invalid 0th fibonacci result');
    assert.equal(fibonacci(13), 233, 'Invalid 13th fibonacci result');
  });
  test('relationship between sequences', () => {
    // catalan numbers are greater than fibonacci numbers (but not equal)
    assert.isAbove(catalan(4), fibonacci(4));
  });
  test('bugfix: check bug #4141', () => {
    assert.isFinite(fibonacci(0)); // fibonacci(0) was returning NaN
  })
});

這個範例會建立一組稱為「數學」的測試 (有時也稱為套件) 測試」,並定義三個獨立測試案例,每個案例都會執行一些斷言。 這些測試案例通常可以個別處理或執行,例如 在測試執行工具中 建立篩選器旗標

做為斷言輔助工具

大部分的測試架構,包括 Vitest 都提供一組斷言 assert 物件的輔助程式,可讓您快速檢查回傳值或 不符合某些期望的狀態。預期情況通常為「已知良好」 輕鬆分配獎金在前一個範例中,我們知道 13 個費波那契數必須是 233,方便我們直接使用 assert.equal 確認。

您可能也會預期價值會採特定形式, 或其他屬性。這堂課程不會 涵蓋所有可能的斷言輔助程式,不過測試架構 一律提供下列基本檢查:

  • 'truthy' 通常被認為是「確定」並檢查條件是否為 True 您會如何編寫 if 來檢查事物是否成功 正確。通常以 assert(...)assert.ok(...) 提供。 就會接受單一值和選填註解。

  • 等式檢查 (例如數學測試範例中) 傳回物件的值或狀態,等於已知的良好值。適用對象 基本等式 (例如數字和字串) 或參照等式 (這些是同一個物件)。但其實這些只是「趨勢」確認 與 ===== 比較。

    • JavaScript 會區分鬆散 (==) 和嚴格 (===) 等式。 大多數測試程式庫都提供方法 assert.equalassert.strictEqual
  • 深度品質檢查,將品質檢查延伸為包含檢查 物件、陣列的內容以及其他較複雜的資料類型, 內部邏輯來掃遍物件來進行比較。重要的是 因為 JavaScript 並沒有內建 兩個物件或陣列例如,[1,2,3] == [1,2,3] 一律為 false。測試 架構通常包含 deepEqualdeepStrictEqual 輔助程式。

比較兩個值的宣告輔助程式 (而非僅限「truthy」檢查) 通常會使用兩個或三個引數:

  • 由測試中程式碼產生的實際值,或是描述 待驗證的狀態。
  • 預期的值,通常使用硬式編碼 (例如 字串)。
  • 選填註解,描述預期狀況或失敗情形 如果這一行失敗,列就會納入其中。
,瞭解如何調查及移除這項存取權。

我們也相當常見的做法是結合斷言結合斷言 再次檢查,因為很少能夠正確確認 基礎架構例如:

  test('JWT parse', () => {
    const json = decodeJwt('eyJieSI6InNhbXRob3Ii');

    assert.ok(json.payload.admin, 'user should be admin');
    assert.deepEqual(json.payload.groups, ['role:Admin', 'role:Submitter']);
    assert.equal(json.header.alg, 'RS265')
    assert.isAbove(json.payload.exp, +new Date(), 'expiry must be in future')
  });

Vitest 使用 Chai 斷言程式庫 內部提供斷言輔助程式 因此查看 ,瞭解何種斷言和輔助程式可能適用於您的程式碼。

Fluent 和 BDD 斷言

有些開發人員偏好使用行為導向的斷言樣式 開發 (BDD),或 流利風格 斷言。也稱為「預期」因為這個進入點 檢查預期是一種名為 expect() 的方法。

預期輔助程式的行為與以簡單方法寫成的斷言相同 呼叫 assert.okassert.strictDeepEquals,但有些開發人員覺得它們更容易閱讀。 BDD 斷言可能如下所示:

// A failure here would generate "Expect result to be an array that does include 42"
const result = await possibleMeaningsOfLife();
expect(result).to.be.an('array').that.does.include(42);

// or a simpler form
expect(result).toBe('array').toContainEqual(42);

// the same in assert might be
assert.typeOf(result, 'array', 'Expected the result to be an array');
assert.include(result, 42, 'Expected the result to include 42');

這類斷言的運作方式,在於一種稱為方法鏈結的技術 其中 expect 傳回的物件可與 進階方法呼叫通話的部分環節,包括 to.bethat.does 上述範例不含任何函式,只會用於發出呼叫 更容易閱讀;如果測試,則可能會產生自動留言 失敗。(請注意,expect 通常不支援選擇性註解,因為 鏈結應清楚描述失敗情形)

許多測試架構都支援 Fluent/BDD 和一般斷言。Vitest, 例如,匯出 Chai 採用的做法,對 BDD 採取略為簡潔的做法。Jest、 另一方面,如果包含 預期 method

跨檔案將測試分組

編寫測試時,我們通常已經提供隱含的分組方式,而非 比起在單一檔案中所有的測試中,編寫多個測試是很常見的情況 檔案。事實上,測試執行者通常只會知道檔案僅供測試,因為 預先定義的篩選器或規則運算式,例如 vitest 檔案中結尾為「.test.jsx」等副檔名的檔案或「.spec.ts」 (「.test」和「.spec」加上多個有效副檔名)。

元件測試通常位於受測試元件的對等檔案中。 如以下目錄結構所示:

存放區中的檔案清單
  ,包括 UserList.tsx 和 UserList.test.tsx。
元件檔案和相關測試檔案。

同樣地,單元測試通常位於受測試的程式碼附近。 端對端測試可能會位於各自的檔案中,而整合測試 放在自己專屬的資料夾中您可以運用這些結構 不斷拓展複雜的測試案例,需要自己的非測試支援檔案,例如 測試所需的支援資料庫

在檔案中將測試分組

和前面的例子一樣,一般做法是將測試放入呼叫 suite() 會將您使用 test() 設定的測試分組。套房通常不會有 但有助於將相關測試分組 呼叫傳遞的方法,或是設定目標如果是 test(),傳遞的方法會說明 測試本身的動作

和斷言一樣,Fluent/BDD 中的 Fluent/BDD 同樣具有相當標準的標準 以便將測試分組以下程式碼中有一些常見範例的比較:

// traditional/TDD
suite('math tests', () => {
  test('handle zero values', () => {
    assert.equal(fibonacci(0), 0);
  });
});

// Fluent/BDD
describe('math tests', () => {
  it('should handle zero values', () => {
    expect(fibonacci(0)).toBe(0);
  });
})

在大多數架構中,suitedescribe 的行為與 testit,相比之下,使用 expectassert 的差異性較高 以便寫入斷言

其他工具則對於安排套件和測試的安排方式有細微差異。適用對象 例如,Node.js 內建測試執行器支援建立對 test() 的巢狀呼叫 間接建立測試階層不過,Vitest 規定 使用 suite() 建立巢狀結構,且不會執行另一個 test() 中定義的 test()

和斷言一樣,請記得 技術堆疊提供的方法並不重要。本課程將介紹 方便您瞭解它們如何應用到 這些工具

生命週期方法

將測試分組的理由之一,即使是隱式的頂層 為每次測試或一次執行一次 一組測試。多數架構提供四種方法:

針對每個 `test()` 或 `it()` 一年一次
測試執行前 「beforeEvery()」 `beforeAll()`
測試執行後 「afterEach()」 「afterAll()」

舉例來說,您可以在每個虛擬使用者資料庫 測試,然後在結束後清除:

suite('user test', () => {
  beforeEach(() => {
    insertFakeUser('bob@example.com', 'hunter2');
  });
  afterEach(() => {
    clearAllUsers();
  });

  test('bob can login', async () => {  });
  test('alice can message bob', async () => {  });
});

這有助於簡化測試。您可以分享常用設定和 而不是每次測試都要複製一次此外, 「安裝」和「拆解」程式碼本身會擲回錯誤,表示結構 但不含測試本身失敗的問題

通用建議

思考這些基元時,以下提供幾個要點。

基本觀念可以當做參考

請記住,這些工具與基本功能,在接下來幾頁中不會有 完全符合 Vitest、Jest、Mocha 或 Web Test Runner 或其他任何項目 具體而言雖然我們是 Vitest 的一般指南,但請務必 搭配您選擇的架構

視需要混合及比對斷言

測試基本上就是可能會擲回錯誤的程式碼。每位跑者都會提供 基本 (可能是 test()) 用來描述不同的測試案例。

但如果該執行器也會提供 assert()expect() 和斷言輔助程式, 別忘了,這部分比較方便好用,可以略過這個步驟 不需要手動操作您可以執行任何可能會擲回錯誤的程式碼,包括 斷言程式庫,或舊式的良好 if 陳述式。

IDE 設定能有效節省電力

確認 IDE (例如 VSCode) 可以存取自動完成功能, ,瞭解如何提升測試效率。適用對象 例如,assertChai 斷言中有超過 100 個方法 程式庫,並取得有關 以內嵌方式顯示註解是最方便的做法

這在部分填入 通用命名空間和測試方法這只是細微差異 您通常可以使用測試程式庫,不必匯入 會自動新增至全域命名空間:

// some.test.js
test('using test as a global', () => {  });

建議您「即使」系統支援自動支援的輔助程式,仍建議您匯入。 因為這樣您的 IDE 才能明確查詢這些方法。(您 會在建構 React 時遇到這個問題,因為部分程式碼集具有神奇 全域 React,但有些則不支援,且需要透過以下方式在所有檔案中匯入: React.)

// some.test.js
import { test } from 'vitest';
test('using test as an import', () => {  });