Bun

編寫測試

使用從內建 bun:test 模組匯入的類似 Jest 的 API 定義測試。長期而言,Bun 的目標是完全相容於 Jest;目前,僅支援有限的集合expect 匹配器。

基本用法

定義簡單測試

math.test.ts
import { expect, test } from "bun:test";

test("2 + 2", () => {
  expect(2 + 2).toBe(4);
});

Jest 風格的全域變數

可以使用 describe 將測試分組到套件中。

math.test.ts
import { expect, test, describe } from "bun:test";

describe("arithmetic", () => {
  test("2 + 2", () => {
    expect(2 + 2).toBe(4);
  });

  test("2 * 2", () => {
    expect(2 * 2).toBe(4);
  });
});

測試可以是 async

import { expect, test } from "bun:test";

test("2 * 2", async () => {
  const result = await Promise.resolve(2 * 2);
  expect(result).toEqual(4);
});

或者,使用 done 回呼來發出完成訊號。如果您在測試定義中包含 done 回呼作為參數,必須 呼叫它,否則測試將會掛起。

import { expect, test } from "bun:test";

test("2 * 2", done => {
  Promise.resolve(2 * 2).then(result => {
    expect(result).toEqual(4);
    done();
  });
});

逾時

您可以選擇性地指定每個測試的逾時時間(以毫秒為單位),方法是將數字作為 test 的第三個參數傳遞。

import { test } from "bun:test";

test("wat", async () => {
  const data = await slowOperation();
  expect(data).toBe(42);
}, 500); // test must run in <500ms

bun:test 中,測試逾時會拋出無法捕捉的例外,以強制停止測試執行並使其失敗。我們也會終止在測試中產生的任何子程序,以避免在背景中留下殭屍程序。

🧟 殭屍程序終結器

當測試逾時,且透過 Bun.spawnBun.spawnSyncnode:child_process 在測試中產生的程序未被終止時,它們將會被自動終止,並在主控台中記錄訊息。

test.skip

使用 test.skip 跳過個別測試。這些測試將不會執行。

import { expect, test } from "bun:test";

test.skip("wat", () => {
  // TODO: fix this
  expect(0.1 + 0.2).toEqual(0.3);
});

test.todo

使用 test.todo 將測試標記為待辦事項。這些測試將不會執行。

import { expect, test } from "bun:test";

test.todo("fix this", () => {
  myTestFunction();
});

若要執行待辦測試並找出任何通過的測試,請使用 bun test --todo

bun test --todo
my.test.ts:
✗ unimplemented feature
  ^ this test is marked as todo but passes. Remove `.todo` or check that test is correct.

 0 pass
 1 fail
 1 expect() calls

使用此標記時,失敗的待辦測試不會導致錯誤,但通過的待辦測試將被標記為失敗,以便您可以移除待辦標記或 修正測試。

test.only

若要執行特定的測試或測試套件,請使用 test.only()describe.only()。一旦宣告,執行 bun test --only 將只會執行標記為 .only() 的測試/套件。在宣告了 test.only() 的情況下,不使用 --only 選項執行 bun test 將會執行給定套件中的所有測試,直到 遇到 .only() 的測試為止。describe.only() 在這兩種執行情境下的運作方式相同。

import { test, describe } from "bun:test";

test("test #1", () => {
  // does not run
});

test.only("test #2", () => {
  // runs
});

describe.only("only", () => {
  test("test #3", () => {
    // runs
  });
});

以下命令將僅執行測試 #2 和 #3。

bun test --only

以下命令將僅執行測試 #1、#2 和 #3。

bun test

test.if

若要有條件地執行測試,請使用 test.if()。如果條件為真值,則測試將會執行。這對於僅應在特定架構或作業系統上執行的測試特別有用。

test.if(Math.random() > 0.5)("runs half the time", () => {
  // ...
});

const macOS = process.arch === "darwin";
test.if(macOS)("runs on macOS", () => {
  // runs if macOS
});

test.skipIf

若要改為根據某些條件跳過測試,請使用 test.skipIf()describe.skipIf()

const macOS = process.arch === "darwin";

test.skipIf(macOS)("runs on non-macOS", () => {
  // runs if *not* macOS
});

test.todoIf

如果改為想要將測試標記為 TODO,請使用 test.todoIf()describe.todoIf()。仔細選擇 skipIftodoIf 可以區分例如「在此目標上無效」和「已計劃但尚未實作」的意圖。

const macOS = process.arch === "darwin";

// TODO: we've only implemented this for Linux so far.
test.todoIf(macOS)("runs on posix", () => {
  // runs if *not* macOS
});

test.each

若要為測試表格中的多個案例傳回函式,請使用 test.each

const cases = [
  [1, 2, 3],
  [3, 4, 5],
];

test.each(cases)("%p + %p should be %p", (a, b, expected) => {
  // runs once for each test case provided
});

有多種選項可用於格式化案例標籤,具體取決於其類型。

%p美化格式
%s字串
%d數字
%i整數
%f浮點數
%jJSON
%o物件
%#測試案例的索引
%%單個百分比符號 (%)

Matchers

Bun 實作了以下 Matchers。完整的 Jest 相容性正在路線圖上;在此處追蹤進度 here