在 Node.js 開發中,自動化測試至關重要,能有效提升程式碼品質與可靠度。本文將深入探討如何運用 Jest 測試框架,實作 Node.js 應用程式的自動化測試,包含測試流程、Jest 安裝設定、測試結構安排、命名規範、程式碼範例、執行方式、mock 物件的應用,以及闡述單元測試的價值與優勢,幫助開發者建立穩固的測試流程。透過 Jest 提供的便捷 API 與豐富功能,開發者能輕鬆撰寫各種測試案例,涵蓋單元測試、整合測試及端對端測試等不同層面,有效保障程式碼的正確性與穩定性。

測試流程

當我們執行Playwright時,它會載入我們的測試程式碼,然後執行我們的應用程式。從我們的測試中,我們直接呼叫我們的應用程式程式碼,然後驗證它是否按照預期執行。

Jest

Jest是一個流行的JavaScript測試框架,提供了方便的API和強大的功能。它支援多種測試風格,包括單元測試、整合測試和端對端測試。

在我們的例子中,我們使用Jest來測試我們的JavaScript數學函式庫。Jest提供了方便的API,允許我們輕鬆地建立和執行測試。

安裝Jest

要安裝Jest,我們需要先安裝依賴項:

cd chapter-9/example-1
npm install

然後,我們就可以使用Jest來執行測試了。

Mermaid 圖表
  graph LR
    A[Docker Compose] --> B[Playwright]
    B --> C[Jest]
    C --> D[測試結果]

圖表翻譯

這個Mermaid圖表展示了Docker Compose、Playwright和Jest之間的關係。Docker Compose用於建置和執行應用程式,Playwright用於執行自動化測試,Jest用於測試JavaScript程式碼。最終,測試結果會被輸出。

Jest自動化測試框架

Jest是一個流行的JavaScript測試框架,廣泛應用於前端和後端開發專案中。下面將介紹如何使用Jest進行自動化測試。

安裝Jest

要使用Jest,首先需要將其安裝到專案中。可以透過npm安裝Jest:

npm install --save-dev jest

這裡使用了--save-dev引數將Jest作為開發依賴項儲存在package.json檔案中。

Jest組態檔案

安裝Jest後,需要建立一個組態檔案。可以透過以下命令建立一個預設的組態檔案:

npx jest --init

這將建立一個名為jest.config.js的組態檔案。以下是預設組態檔案的內容:

module.exports = {
  clearMocks: true,
  testEnvironment: "node",
};

這裡組態了兩個選項:clearMockstestEnvironmentclearMocks選項用於指定是否在每次測試後清除mocks,而testEnvironment選項用於指定測試環境。

測試檔案

測試檔案通常以.test.js為副檔名。例如,可以建立一個名為math.test.js的測試檔案,內容如下:

// math.test.js
const math = require('./math');

describe('math', () => {
  it('should add two numbers', () => {
    expect(math.add(1, 2)).toBe(3);
  });
});

這裡定義了一個測試套件,包含一個測試案例。測試案例使用expect函式斷言math.add(1, 2)的傳回值是否為3。

執行測試

可以透過以下命令執行測試:

jest

Jest將自動發現並執行所有測試檔案。

Jest工作原理

Jest工作原理如下:

  1. 載入測試檔案:Jest載入所有測試檔案,包括.test.js.spec.js檔案。
  2. 執行測試:Jest執行每個測試案例,並使用expect函式斷言結果。
  3. 報告結果:Jest報告每個測試案例的結果,包括透過和失敗的案例。

Jest優點

Jest具有以下優點:

  • 快速:Jest執行速度快,可以快速完成測試。
  • 簡單:Jest組態簡單,易於使用。
  • 強大:Jest支援多種測試風格,包括單元測試、整合測試和端對端測試。

自動化測試與Jest

在開發Node.js應用程式時,自動化測試是一個非常重要的環節。它可以幫助我們確保程式碼的正確性和可靠性。在這個章節中,我們將介紹如何使用Jest進行自動化測試。

Jest安裝和設定

首先,我們需要安裝Jest。可以使用npm或yarn進行安裝。安裝完成後,Jest會被安裝在我們的專案目錄中。

測試結構

一個典型的Node.js專案結構如下所示:

專案目錄
|-- node_modules
|-- src
|    |-- math.js
|    |-- math.test.js
|-- package.json

在上面的結構中,math.js是我們的程式碼檔案,math.test.js是對應的測試檔案。

測試命名規則

Jest使用特定的命名規則來識別測試檔案。預設情況下,Jest會尋找以.test.js結尾的檔案作為測試檔案。

測試程式碼

以下是math.test.js檔案的內容:

describe('square function', () => {
  test('can square two', () => {
    // 測試邏輯
  });
});

在上面的程式碼中,describe函式定義了一個測試套件,test函式定義了一個具體的測試。

被測試程式碼

以下是math.js檔案的內容:

function square(n) {
  return n * n;
}

module.exports = {
  square,
};

在上面的程式碼中,square函式是一個簡單的函式,它計算一個數字的平方。

測試執行

當我們執行測試時,Jest會自動尋找以.test.js結尾的檔案,並執行其中的測試程式碼。

圖表翻譯:

  flowchart TD
    A[測試檔案] --> B[測試執行]
    B --> C[結果輸出]

在上面的圖表中,測試檔案代表我們的測試檔案,測試執行代表Jest的測試執行過程,結果輸出代表測試結果的輸出。

自動化測試對於微服務的重要性

在微服務架構中,自動化測試扮演著至關重要的角色。它確保每個微服務單元都能夠正確地執行其功能,並且能夠與其他微服務進行順暢的互動。下面是一個使用 Jest 進行自動化測試的例子:

const { square } = require("./math");

describe("平方函式", () => {
  test("可以計算2的平方", () => {
    const result = square(2);
    expect(result).toBe(4);
  });
});

在這個例子中,我們定義了一個名為「平方函式」的測試套件,裡麵包含了一個名為「可以計算2的平方」的測試案例。這個測試案例呼叫了 square 函式,並傳入了數值 2 作為輸入,然後使用 expecttoBe 函式來驗證結果是否為 4。

執行測試

要執行這個測試,我們可以在終端機中輸入以下命令:

npx jest

這將會執行我們定義的測試,並顯示測試結果。如果所有測試都透過,則表示我們的程式碼是正確的。

測試命名的重要性

一個良好的測試名稱可以讓我們瞬間瞭解被測試的內容。例如,在上面的例子中,測試名稱「可以計算2的平方」清晰地表明瞭這個測試的目的。

Jest 的 expect 函式

Jest 的 expect 函式提供了一種豐富的語法來描述被測試程式碼的預期輸出。透過鏈式呼叫不同的匹配函式(如 toBetoEqual 等),我們可以對預期結果進行詳細的描述。

測試套件和測試案例

在 Jest 中,測試套件(test suite)是指一組相關的測試案例的集合。每個測試案例(test case)代表了一個獨立的測試。透過組織成套的方式,可以更好地管理和維護測試程式碼。

自動化測試的好處

自動化測試可以幫助我們快速地發現程式碼中的錯誤,並確保程式碼的正確性和可靠性。透過使用 Jest 進行自動化測試,我們可以提高程式碼的品質,並減少手動測試的時間和成本。

圖表翻譯:

  graph LR
    A[撰寫程式碼] --> B[編寫測試]
    B --> C[執行測試]
    C --> D[檢視測試結果]
    D --> E[修復錯誤]
    E --> B

這個流程圖展示了撰寫程式碼、編寫測試、執行測試、檢視測試結果和修復錯誤之間的流程。

Jest 自動測試框架

Jest 是一個流行的 JavaScript 測試框架,廣泛用於 React、Angular 和 Vue.js 等前端框架的測試。它提供了快速、可靠和易於使用的測試解決方案。

Jest 的優點

  • 快速: Jest 的測試速度非常快,尤其是在大型專案中。
  • 可靠: Jest 提供了穩定的測試結果,減少了測試失敗的風險。
  • 易於使用: Jest 的 API 簡單易懂,讓開發者可以快速上手。

Jest 的基本使用

要使用 Jest,首先需要安裝它。可以使用 npm 或 yarn 來安裝:

npm install --save-dev jest

yarn add jest --dev

安裝完成後,可以在 package.json 中增加一個指令碼來執行 Jest:

"scripts": {
  "test": "jest"
}

然後,可以執行以下命令來啟動 Jest:

npm run test

yarn test

Jest 的測試結構

Jest 的測試結構通常如下:

describe('測試套件', () => {
  it('測試案例', () => {
    // 測試程式碼
  });
});

其中,describe 是用來定義一個測試套件,而 it 是用來定義一個測試案例。

Jest 的斷言

Jest 提供了多種斷言函式,例如 expecttoBetoEqual 等。以下是一個簡單的範例:

expect(1 + 1).toBe(2);

這個斷言檢查 1 + 1 的結果是否等於 2

Jest 的 Live Reload

Jest 提供了 Live Reload 功能,可以在程式碼變化時自動重新執行測試。可以使用以下命令來啟動 Live Reload:

npx jest --watchAll

npx jest --watch

第二個命令使用 Git 來檢查程式碼變化,效能更好。

Jest 的錯誤處理

當測試失敗時,Jest 會顯示錯誤訊息。可以使用 try/catch 來捕捉錯誤,並進行相應的處理。

try {
  // 測試程式碼
} catch (error) {
  // 錯誤處理
}
內容解密:

以上內容介紹了 Jest 的基本使用、優點和功能。透過瞭解 Jest,可以更好地使用它來提高程式碼品質和開發效率。

圖表翻譯:

  graph LR
    A[Jest] --> B[快速]
    A --> C[可靠]
    A --> D[易於使用]
    B --> E[大型專案]
    C --> F[穩定的測試結果]
    D --> G[簡單易懂的 API]

這個圖表展示了 Jest 的優點和功能。Jest 提供了快速、可靠和易於使用的測試解決方案,適合大型專案和需要穩定的測試結果的開發者。

Jest 測試框架:自動化測試與npm指令

在前面的章節中,我們已經瞭解瞭如何使用Jest進行單元測試。現在,我們將探討如何使用npm指令來執行Jest測試。

Jest 測試輸出

當我們執行Jest測試時,系統會顯示測試結果,包括透過和失敗的測試數量、失敗原因、測試名稱以及錯誤位置。這些訊息對於快速定位和修復錯誤至關重要。

使用npm指令執行Jest

為了方便執行Jest測試,我們可以在package.json檔案中組態一個名為test的npm指令碼。這樣,我們就可以使用npm test指令來執行測試套件。這種做法使得執行測試變得非常簡單,不需要知道具體的測試工具是Jest還是其他工具。

以下是組態test指令碼的示例:

{
  "name": "example-1",
  "version": "1.0.0",
  "scripts": {
    "test": "jest",
    "test:watch": "jest --watchAll"
  },
  "devDependencies": {
    "jest": "^29.6.4"
  },
  "dependencies": {}
}

在這個例子中,我們定義了兩個npm指令碼:testtest:watchtest指令碼簡單地執行Jest,而test:watch指令碼則啟用了Jest的監視模式,這樣就可以在程式碼變化時自動重新執行測試。

監視模式

監視模式是一個非常有用的功能,它允許我們在程式碼變化時自動重新執行測試。要啟用監視模式,可以使用jest --watchAll指令。這樣,Jest就會監視程式碼的變化,並在必要時自動重新執行測試。

透過組態npm指令碼和使用Jest的監視模式,我們可以簡化測試過程,提高開發效率。同時,這也使得我們的專案更加容易維護和擴充套件。

9.5.9 測試套件的填充

到目前為止,我們只看到了一個單獨的測試,但我也想給你展示一下當我們擴充套件到一個包含多個測試的套件時會是什麼樣子。清單 9.5(對 chapter-9/example-1/src/math.test.js 的補充)顯示了在增加第二個測試後 math.test.js 的內容。(示例-1 實際上並不包含這個新測試,但你可以自己增加它並進行實驗。)

const { square } = require("./math");

describe("平方函式", () => {
  test("可以對 2 進行平方", () => {
    //...
  });

  test("可以對 0 進行平方", () => {
    const result = square(0);
    expect(result).toBe(0);
  });
});

如清單 9.5 所示,我們可以透過 describe 函式增加更多測試到我們的平方函式測試套件中。新的測試「可以對 0 進行平方」是一個邊緣案例的例子。我們不需要為正數的平方增加更多測試;「可以對 2 進行平方」足以涵蓋所有正數案例,因此你可以將其重新命名為「可以對正數進行平方」。如果你想完成這個小測試套件,你可能還應該增加一個名為「可以對負數進行平方」的測試。

當我們開發我們的數學函式庫時,我們將增加更多數學函式和更多測試套件。例如,我們將增加 squareRootaverage 函式及其測試套件。請記住,我們將測試檔案命名為 math.test.js,這個名稱足夠通用,以便我們可以使用 describe 函式增加新的測試套件。

我們也可以為每個測試套件建立單獨的 JavaScript 程式碼檔案,例如 square.test.jssquare-root.test.jsaverage.test.js。注意,這些檔案名都以 .test.js 結尾,以便 Jest 可以自動找到它們。當我們在未來增加新函式庫時,我們將增加新的測試檔案,盡可能多地包含所有我們建立的測試。

你可以按照自己的方式結構化測試。你可以按照自己的喜好命名測試,並將其跨多個檔案組織,以適應自己的需求。但是,當你為公司工作時,你將被要求遵循現有的風格和約定。不論你遵循什麼約定,我只要求(代表所有開發人員)你為測試使用有意義的名稱,使得理解測試目的變得容易。

9.5.10 使用 Jest 進行模擬

JavaScript 是建立模擬的理想語言!JavaScript 的動態性使得建立自動化測試變得容易。但是,什麼是模擬?

定義 模擬是指在程式碼中用偽造或模擬版本替換真實依賴項。

我們用模擬替換的依賴項可以是函式、物件,甚至整個程式碼模組。在 JavaScript 中,建立函式和組裝新的物件和資料結構以用作模擬非常容易。

為什麼要這樣做?模擬的目的是隔離我們正在測試的程式碼。隔離特定的程式碼部分使我們能夠專注於僅測試那部分程式碼,而不是其他東西。隔離對於單元測試和測試驅動開發(TDD)至關重要。

模擬不僅有助於隔離我們正在測試的程式碼,而且還可以完全消除可能使測試變慢的程式碼和過程。例如,我們可以消除資料函式庫查詢、網路事務和檔案系統操作。這些是可能比我們正在測試的程式碼花費大量時間的事情。

在第 9.6 節中,你將學習單元測試,並看到模擬的真例項子。但首先,讓我們瞭解一下什麼是模擬。假設我們不使用乘法運運算元 (*) 在平方函式中,而是使用乘法函式,如下所示:

單元測試的重要性

單元測試是軟體開發中的一個重要步驟,它可以幫助我們確保程式碼的正確性和可靠性。在這篇文章中,我們將探討單元測試的概念和實踐,特別是在微服務架構中。

什麼是單元測試?

單元測試是一種軟體測試方法,旨在驗證程式碼中的一個單元(unit)是否正確地執行其功能。一個單元可以是一個函式、方法或類別中的某一部分。單元測試的目的是確保每個單元都能夠獨立地運作,並且不會受到其他程式碼的影響。

Jest 框架

Jest 是一個流行的 JavaScript 測試框架,它提供了一個簡單易用的 API 來撰寫和執行測試。在這篇文章中,我們將使用 Jest 來示範如何撰寫單元測試。

模擬(Mocking)

模擬是一種測試技術,旨在隔離被測試的程式碼與其依賴的其他程式碼。透過模擬,我們可以控制被測試程式碼的輸入和輸出,從而確保測試的結果是可預測的。在上面的例子中,我們使用模擬來隔離 square 函式與 multiply 函式。

實踐

在實踐中,單元測試可以幫助我們:

  • 確保程式碼的正確性和可靠性
  • 減少 bug 的數量
  • 提高程式碼的可維護性
  • 加速開發速度

微服務架構中的單元測試

在微服務架構中,單元測試尤其重要。每個微服務都是一個獨立的應用程式,它需要被測試以確保其正確性和可靠性。透過撰寫單元測試,我們可以確保每個微服務都能夠獨立地運作,並且不會受到其他微服務的影響。

內容解密:

在上面的例子中,我們定義了一個 square 函式,它接受兩個引數:nmultiplymultiply 是一個函式,它將兩個數字相乘。 我們使用模擬來隔離 square 函式與 multiply 函式。透過模擬,我們可以控制 multiply 函式的輸入和輸出,從而確保測試的結果是可預測的。

圖表翻譯:

  flowchart TD
    A[開始] --> B[定義 square 函式]
    B --> C[定義 mockMultiply 函式]
    C --> D[呼叫 square 函式]
    D --> E[驗證結果]

在上面的圖表中,我們展示了測試流程。首先,我們定義 square 函式和 mockMultiply 函式。然後,我們呼叫 square 函式,並傳入 mockMultiply 函式作為引數。最後,我們驗證結果是否正確。

單元測試的重要性

單元測試是軟體開發中的一個重要步驟,尤其是在微服務架構中。它們允許我們隔離地測試特定的程式碼片段,而不需要考慮其他依賴項或外部系統。這種隔離使得測試更快、更可靠、更容易維護。

Jest 測試框架

在這裡,我們使用 Jest 作為測試框架。Jest 提供了一個簡單的方式來撰寫和執行測試。它可以載入我們的測試程式碼和待測程式碼,並提供了一個環境來執行測試。

程式碼隔離

在單元測試中,隔離是關鍵。它意味著我們需要將待測程式碼與其他依賴項或外部系統隔離開來。在這個例子中,我們將使用 mock 物件來替換 Express 和 MongoDB 等依賴項。這樣,我們就可以控制和操縱這些 mock 物件,以便進行測試。

測試流程

當我們執行測試時,Jest 會載入我們的測試程式碼和待測程式碼。然後,測試程式碼會直接呼叫待測程式碼,並傳入 mock 物件。這樣,待測程式碼就會在一個受控的環境中執行,並且不會影響到外部系統。

優點

單元測試有許多優點,包括:

  • 快速執行:由於隔離了外部系統,單元測試可以非常快速地執行。
  • 可靠性:單元測試可以確保程式碼的正確性和可靠性。
  • 易於維護:單元測試可以幫助我們快速地發現和修復程式碼中的錯誤。

從技術架構視角來看,Jest 作為一個 JavaScript 測試框架,其簡潔的 API 和豐富的功能在前端和後端開發中都展現了其價值。透過 describetest 函式,開發者可以輕鬆組織測試套件和案例,搭配 expect 函式進行斷言,有效驗證程式碼的正確性。此外,Jest 的監視模式和模擬功能,分別提升了開發效率和測試的隔離性,有效降低了測試的複雜度和時間成本。然而,Jest 的模擬功能雖然強大,但也可能導致過度模擬,反而降低測試的真實性。因此,在實務應用中,需要謹慎評估模擬的範圍,並權衡測試的隔離性和真實性。展望未來,隨著微服務架構的普及,Jest 在單元測試和整合測試中的作用將更加重要。預期 Jest 將持續強化其效能和功能,以更好地支援更複雜的測試場景,並與其他開發工具更緊密地整合,進一步提升開發效率。對於追求程式碼品質和開發效率的團隊而言,Jest 是一個值得深入研究和應用的測試框架。玄貓認為,Jest 已成為現代 JavaScript 開發不可或缺的工具,能有效提升程式碼品質和開發效率。