首頁 > web前端 > js教程 > 初學者測試功能JavaScript指南

初學者測試功能JavaScript指南

Joseph Gordon-Levitt
發布: 2025-02-16 09:30:10
原創
359 人瀏覽過

A Beginner's Guide to Testing Functional JavaScript

關鍵要點

  • 結合函數式編程和測試可以編寫更清晰、更易維護的代碼。函數式編程允許獨立處理應用程序中的行為和數據,從而產生更清晰、更一致的代碼。
  • 測試是為了確保代碼按預期運行,即使在代碼更改後也能繼續按預期運行。不同類型的測試包括單元測試、集成測試和功能測試。
  • 測試驅動開發 (TDD) 是一種在編寫被測試函數之前先編寫單元測試的實踐。這鼓勵在編寫代碼之前分解應用程序功能並確定預期結果。
  • 純函數不依賴於外部狀態或變量,不會產生副作用,並且對於相同的輸入始終返回相同的結果,是函數式編程的基礎。它們使單元測試更容易,並為將來的代碼重構提供信心。
  • Jasmine 是一個強大的測試框架,可用於測試函數式 JavaScript。它可以用於使用測試驅動方法在瀏覽器中開發純函數。編寫測試驅動代碼的實踐可以由於其易於測試和修改而鼓勵創建純函數。

函數式編程和測試。您可能分別嘗試過它們,但不知何故,您從未將兩者都納入您的常規實踐中。它們本身聽起來可能很簡單,但測試和函數式編程結合在一起可以產生無法抗拒的誘惑,幾乎迫使您編寫更清晰、更緊湊、更易維護的代碼。

A Beginner's Guide to Testing Functional JavaScript

好消息是,同時使用這兩種技術可以提供一些實際優勢。事實上,一旦您體驗了這種組合的甜頭,您可能會像我一樣沉迷於它,而且我敢打賭,您會想要更多。

觀看《遵循函數式 JavaScript 原則編寫清晰的純代碼》課程,分解您的代碼並使其更易於維護……為什麼不呢? 觀看本課程 在本篇文章中,我將向您介紹測試函數式 JavaScript 的原則。我將向您展示如何使用 Jasmine 框架並使用測試驅動方法構建純函數。

為什麼要測試?

測試是為了確保應用程序中的代碼按預期運行,並在您進行更改時繼續按預期運行,以便在您完成工作時獲得可用的產品。您編寫一個測試來定義在定義的一組情況下預期的功能,針對代碼運行該測試,如果結果與測試所說的結果不符,則會收到警告。並且您會不斷收到該警告,直到您修復代碼為止。

然後您會得到獎勵。

是的,這會讓您感覺良好。

測試有很多種類型,關於邊界在哪裡劃分的討論空間很大,但簡而言之:

  • 單元測試驗證隔離代碼的功能
  • 集成測試驗證數據流和組件的交互
  • 功能測試查看整個應用程序的行為

注意:不要被名為功能測試的一種測試類型所分心。這並不是我們在本文中關於測試函數式 JavaScript 的內容中要關注的內容。事實上,無論您是否在 JavaScript 中使用函數式編程技術,您用於測試應用程序整體行為的功能測試方法可能不會發生太大變化。函數式編程真正有幫助的地方是在構建單元測試時。

您可以在編碼過程中的任何時候編寫測試,但我總是發現,在編寫計劃測試的函數之前編寫單元測試最有效。這種被稱為測試驅動開發 (TDD) 的實踐鼓勵您在開始編寫之前分解應用程序的功能,並確定您希望從每個代碼部分獲得什麼結果,首先編寫測試,然後編寫代碼以產生該結果。

一個附帶好處是,TDD 經常迫使您與付錢給您編寫程序的人進行詳細的討論,以確保您正在編寫的程序確實是他們正在尋找的程序。畢竟,讓單個測試通過很容易。困難的是確定要處理所有可能遇到的輸入,並正確處理所有輸入而不會破壞任何東西。

為什麼選擇函數式編程?

正如您所想像的那樣,編寫代碼的方式與測試的難易程度密切相關。有些代碼模式,例如將一個函數的行為與另一個函數緊密耦合,或嚴重依賴全局變量,會使代碼的單元測試變得更加困難。有時,您可能必須使用諸如“模擬”外部數據庫的行為或模擬複雜的運行時環境等不便的技術,以便建立可測試的參數和結果。這些情況並非總是可以避免的,但通常可以隔離代碼中需要這些情況的地方,以便更容易地測試其餘代碼。

函數式編程允許您獨立處理應用程序中的數據和行為。您可以通過創建一組獨立的函數來構建您的應用程序,這些函數各自獨立工作,並且不依賴於外部狀態。結果,您的代碼幾乎變成了自文檔化的代碼,將行為一致且易於理解的小型清晰定義的函數組合在一起。

函數式編程通常與命令式編程和麵向對象編程形成對比。 JavaScript 可以支持所有這些技術,甚至可以混合使用它們。函數式編程可以作為創建跟踪應用程序狀態的命令式代碼序列的另一種有價值的替代方法,直到返回結果為止。或者通過跨複雜對象的交互來構建您的應用程序,這些複雜對象封裝了適用於特定數據結構的所有方法。

純函數的工作原理

函數式編程鼓勵您使用微小、可重用、可組合的函數來構建您的應用程序,這些函數只做一件特定的事情,並且每次對於相同的輸入都返回相同的值。這樣的函數稱為純函數。純函數是函數式編程的基礎,它們都具有以下三個特性:

  • 不依賴於外部狀態或變量
  • 不會產生副作用或更改外部變量
  • 對於相同的輸入始終返回相同的結果

編寫函數式代碼的另一個優點是它使單元測試更容易。您可以單元測試的代碼越多,您就越能輕鬆地依靠您將來重構代碼的能力,而不會破壞基本功能。

是什麼使函數式代碼易於測試?

如果您考慮一下我們剛剛討論的概念,您可能已經明白為什麼函數式代碼更容易測試。為純函數編寫測試非常簡單,因為每個輸入都有一個一致的輸出。您只需設置期望值並針對代碼運行它們即可。不需要建立上下文,不需要跟踪函數間依賴關係,不需要模擬函數外部的更改狀態,也不需要模擬出變量外部數據源。

有很多測試選項,從完整的框架到實用程序庫和簡單的測試工具。其中包括 Jasmine、Mocha、Enzyme、Jest 和許多其他工具。每個工具都有不同的優點和缺點、最佳用例和忠實的追隨者。 Jasmine 是一個可以在各種情況下使用的強大框架,因此以下是如何在瀏覽器中使用 Jasmine 和 TDD 開發純函數的快速演示。

您可以創建一個 HTML 文檔,該文檔可以從本地或 CDN 中提取 Jasmine 測試庫。包含 Jasmine 庫和測試運行程序的頁面的示例可能如下所示:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Jasmine Test</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.6.1/jasmine.min.css">
</head>
<body>
    <🎜>
    <🎜>
    <🎜>
</body>
</html>
登入後複製
登入後複製
登入後複製

這引入了 Jasmine 庫,以及 Jasmine HTML 引導腳本和样式。在這種情況下,文檔的主體是空的,等待您的 JavaScript 進行測試和您的 Jasmine 測試。

測試函數式 JavaScript — 我們的第一個測試

首先,讓我們編寫第一個測試。我們可以在單獨的文檔中執行此操作,也可以通過將其包含在頁面上的 <script> 元素中來執行此操作。我們將使用 Jasmine 庫定義的 describe 函數來描述我們尚未編寫的新的函數的所需行為。

我們將編寫的新的函數將被稱為 isPalindrome,如果傳入的字符串前後相同,則返回 true,否則返回 false。測試將如下所示:

describe("isPalindrome", () => {
  it("returns true if the string is a palindrome", () => {
    expect(isPalindrome("abba")).toEqual(true);
  });
});
登入後複製
登入後複製

當我們將此添加到頁面中的腳本並將其加載到瀏覽器中時,我們會得到一個顯示錯誤的工作 Jasmine 報告頁面。這就是我們此時想要的。我們想知道測試是否正在運行,以及它是否失敗。這樣,我們渴望得到認可的大腦就知道我們需要修復某些東西。

因此,讓我們用 JavaScript 編寫一個簡單的函數,其中只有足夠的邏輯來使我們的測試通過。在這種情況下,它只是一個函數,通過返回預期值來使我們的一個測試通過。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Jasmine Test</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.6.1/jasmine.min.css">
</head>
<body>
    <🎜>
    <🎜>
    <🎜>
</body>
</html>
登入後複製
登入後複製
登入後複製

是的,真的。我知道它看起來很荒謬,但請堅持下去。

再次運行測試運行程序時,它會通過。當然。但顯然,這個簡單的代碼並沒有做到我們對回文測試程序的預期。我們現在需要的是額外的期望。因此,讓我們向我們的 describe 函數添加另一個斷言:

describe("isPalindrome", () => {
  it("returns true if the string is a palindrome", () => {
    expect(isPalindrome("abba")).toEqual(true);
  });
});
登入後複製
登入後複製

現在重新加載我們的頁面會使測試輸出變為紅色並失敗。我們收到一條消息,說明問題是什麼,測試結果變為紅色。

紅色!

我們的大腦感覺到有問題。

當然有問題。現在,我們簡單的 isPalindrome 函數每次都只返回 true,已被證明無法有效地針對此新測試。因此,讓我們更新 isPalindrome,添加比較傳入字符串前後功能的能力。

const isPalindrome = (str) => true;
登入後複製

測試會上癮

再次變為綠色。這令人滿意。當您重新加載頁面時,您是否得到了那種小小的多巴胺激增?

有了這些更改,我們的測試再次通過。我們的新代碼有效地比較了前後字符串,並在字符串前後相同時返回 true,否則返回 false

這段代碼是一個純函數,因為它只做一件事情,並且在給定一致的輸入值的情況下始終如一地執行,而不會產生任何副作用、更改自身外部的任何變量或依賴於應用程序的狀態。每次您向此函數傳遞字符串時,它都會在前後字符串之間進行比較,並返回結果,而不管何時或如何調用它。

您可以看到這種一致性使此函數的單元測試多麼容易。事實上,編寫測試驅動的代碼可以鼓勵您編寫純函數,因為它們更容易測試和修改。

而且您希望獲得通過測試的滿足感。我知道您會的。

重構純函數

此時,添加其他功能(例如處理非字符串輸入、忽略大寫和小寫字母之間的差異等)非常簡單。只需詢問產品所有者他們希望程序如何運行即可。由於我們已經有了測試來驗證字符串將始終如一地處理,因此我們現在可以為非字符串值添加錯誤檢查或字符串強制轉換或任何我們喜歡的行為。

例如,讓我們看看如果我們為數字 1001 添加一個測試會發生什麼,如果它是字符串,則可能被解釋為回文:

describe("isPalindrome", () => {
  it("returns true if the string is a palindrome", () => {
    expect(isPalindrome("abba")).toEqual(true);
  });
  it("returns false if the string isn't a palindrome", () => {
    expect(isPalindrome("Bubba")).toEqual(false);
  });
});
登入後複製

這樣做會再次使我們的屏幕變紅並導致測試失敗,因為我們當前的 isPalindrome 函數不知道如何處理非字符串輸入。

恐慌開始。我們看到紅色。測試失敗了。

但是現在我們可以安全地更新它以處理非字符串輸入,將它們強制轉換為字符串然後進行檢查。我們可能會想出一個看起來更像這樣的函數:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Jasmine Test</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.6.1/jasmine.min.css">
</head>
<body>
    <🎜>
    <🎜>
    <🎜>
</body>
</html>
登入後複製
登入後複製
登入後複製

現在所有測試都通過了,我們看到綠色,甜蜜的多巴胺正在湧入我們測試驅動的大腦。

通過向評估鏈中添加 toString(),我們能夠適應非字符串輸入並在測試之前將其轉換為字符串。最棒的是,因為每次都會運行我們的其他測試,所以我們可以確信,通過向我們的純函數添加此新功能,我們並沒有破壞我們之前獲得的功能。最終結果如下:

(此處應插入 CodePen 代碼,但由於我無法訪問外部網站,我無法提供 CodePen 鏈接。)

嘗試一下這個測試,並開始編寫您自己的測試,使用 Jasmine 或任何適合您的其他測試庫。

一旦您將測試納入代碼設計工作流程,並開始編寫純函數進行單元測試,您可能會發現很難回到過去的生活。但您永遠不會想這樣做。

(本文由 Vildan Softic 進行了同行評審。感謝所有 SitePoint 的同行評審人員,使 SitePoint 內容達到最佳狀態!)

關於函數式 JavaScript 測試的常見問題解答 (FAQ)

什麼是函數式 JavaScript 測試?

函數式 JavaScript 測試是一種測試,它檢查代碼各個部分(例如函數)的功能,以確保它們按預期工作。這涉及編寫測試用例,這些測試用例使用不同的輸入調用函數,並將輸出與預期結果進行比較。它是軟件開發中至關重要的一部分,有助於儘早發現開發過程中的錯誤,確保代碼的質量和可靠性。

如何在 JavaScript 中編寫函數式測試?

在 JavaScript 中編寫函數式測試涉及創建測試用例,該測試用例使用特定輸入調用要測試的函數,然後檢查輸出是否與預期結果匹配。這可以使用各種測試框架來完成,例如 Jest、Mocha 或 Jasmine。這些框架提供函數來定義測試用例、運行它們和檢查結果。

JavaScript 中的 RegExp test 方法是什麼?

JavaScript 中的 RegExp test 方法是一種在字符串中測試匹配的方法。如果找到匹配項,則返回 true,否則返回 false。當您需要驗證用戶輸入或在字符串中搜索模式時,此方法特別有用。

如何在 JavaScript 中使用 RegExp test 方法?

要在 JavaScript 中使用 RegExp test 方法,您首先需要使用要匹配的模式創建一個 RegExp 對象。然後,您在此對象的 test 方法上調用,將要測試的字符串作為參數傳遞。如果找到匹配項,該方法將返回 true,否則返回 false

JavaScript 中的功能測試和單元測試有什麼區別?

功能測試和單元測試都是測試過程的重要組成部分,但它們的目的不同。單元測試專注於隔離測試代碼的各個部分(例如函數或方法),與系統的其餘部分隔離。另一方面,功能測試測試系統更大塊的功能(例如模塊或整個應用程序),以確保它們在集成在一起時按預期工作。

如何改進 JavaScript 中的功能測試?

改進 JavaScript 中的功能測試通常涉及確保您的測試涵蓋所有可能的情況,包括極端情況和潛在的錯誤條件。確保您的測試是獨立的並且可以按任何順序運行也很重要,因為這使它們更可靠且更容易維護。使用測試框架還可以幫助構建測試並提供有用的工具來檢查結果和報告錯誤。

JavaScript 中的功能測試的一些良好實踐是什麼?

JavaScript 中的功能測試的一些良好實踐包括編寫清晰簡潔的測試用例、測試正面和負面場景,以及確保測試是獨立的並且可以按任何順序運行。使用測試框架也是一個好主意,因為它可以為您的測試提供有用的工具和結構。

如何調試 JavaScript 中的功能測試?

可以使用各種工具和技術來調試 JavaScript 中的功能測試。一種常見的方法是使用 console.log 語句在測試執行期間打印出值。您還可以使用開發環境或測試框架提供的調試工具,這些工具可以讓您逐步執行代碼並在不同的時間點檢查變量。

JavaScript 中功能測試的一些常見挑戰是什麼?

JavaScript 中功能測試的一些常見挑戰包括處理異步代碼、測試與外部系統交互的代碼以及管理大型測試套件的複雜性。可以使用各種技術和工具來解決這些挑戰,例如對異步代碼使用 Promise 或 async/await、模擬外部系統以及以易於理解和維護的方式構建測試。

如何進一步學習 JavaScript 中的功能測試?

有很多資源可以學習有關 JavaScript 中的功能測試的更多信息。這包括在線教程、書籍和課程。 W3Schools、Mozilla 開發者網絡和 Geeks for Geeks 等網站提供了關於該主題的全面指南和教程。您還可以在 YouTube 等平台上找到許多視頻教程。此外,許多 JavaScript 測試框架(如 Jest、Mocha 和 Jasmine)在其官方網站上提供了詳細的文檔和指南。

以上是初學者測試功能JavaScript指南的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板