JavaScript >> Javascript 文檔 >  >> JavaScript

使用 Mocha 在 JavaScript 中進行單元測試

測試驅動開發 (TDD) 是一種開發方法,包括編寫測試,然後是生產代碼,並根據需要進行重構。最初編寫的測試是失敗的,開發人員編寫代碼來滿足測試的要求,因此它們通過了。

在本教程中,我們將學習如何通過使用 Node.js 從頭開始開發一個簡單的命令行計算器應用程序來實現 TDD 過程。如果您不熟悉,Node.js 允許在服務器端使用 JavaScript。閱讀入門文章以快速了解 Node.js。我們將使用 Mocha(一個測試框架)為此應用設置測試。

您還將學習如何使用 Node.js 中內置的 readline 模塊通過命令行向程序發送命令。

  • 在 GitHub 上查看源代碼

目標

  • 應用程序應加、減、除和乘 任意兩個數字
  • 應用程序應顯示警告並退出 如果它接收到任何不包含數字的輸入
  • 系統會提供命令行界面 允許最終用戶使用程序功能

現在我們知道應用程序應該做什麼,我們可以開始設置測試和開發環境了。

先決條件

  • 為了學習本教程,您應該在計算機上安裝了 Node.js 服務器環境和 npm。了解 Node.js 和 npm 以及如何在 Mac/Windows 上安裝它們。

  • 您需要具備 Ja​​vaScript 語法和代碼結構、數據類型、數學運算和條件語句的工作知識。

設置我們的環境

由於我們的應用程序在 Node.js 中運行,因此我們需要為我們的文件和依賴項設置本地環境。

創建一個名為 calc 的新目錄 .在命令提示符下,導航到目錄並使用 npm init 初始化一個新項目 ,這將創建一個新的 package.json 我們的程序的文件。

npm init

系統將提示您輸入包名稱、版本、描述和其他常見包詳細信息。我們可以輸入名稱calc.js ,然後繼續按 ENTER 對於所有默認項目,如果您願意,請提供說明。當你到達 test command , 輸入 mocha ,這是我們將使用的測試框架。

test command: mocha

繼續輸入默認值,直到演練完成。該腳本將創建一個 package.json 文件看起來像這樣:

package.js
{
  "name": "calc.js",
  "version": "1.0.0",
  "description": "A simple calculator application built with Node.js",
  "main": "index.js",
  "scripts": {
    "test": "mocha"
  },
  "author": "",
  "license": "ISC"
}

我們設置環境的最後一步是安裝 Mocha,這是我們將用於我們的應用程序的 JavaScript 測試框架。輸入以下命令安裝 Mocha:

npm install --save-dev mocha

運行此命令將添加一個 node_modules 目錄,一個 package-lock.json 文件,並將以下代碼添加到您的原始 package.json

package.json
"devDependencies": {
  "mocha": "^4.0.1"
}

我們有我們的 Node 項目,其中加載了測試腳本和依賴項。讓我們確保我們的測試框架正常工作。

創建一個 test.js 文件。我們將使用內置的 Node.js 斷言模塊來測試 true 等於 true .既然如此,那測試應該就通過了。

test.js

const assert = require('assert')

it('should return true', () => {
  assert.equal(true, true)
})

現在在命令提示符下,運行測試。

npm test

> mocha

  ✓ should return true

  1 passing (8ms)

測試按預期通過,因此我們的測試環境設置完成。從 test.js 中刪除除第一行之外的所有內容 .

test.js
const assert = require('assert')

test.js 是我們將在整個應用程序創建過程中用於測試的文件。讓我們創建兩個附加文件:operations.js 對於我們的算術和驗證函數,以及 calc.js 對於我們的應用程序本身。我們希望將我們的文件分開,這樣它們就不會變得太長和太複雜。以下是我們的文件列表。

  • calc.js
  • 節點模塊
  • 操作.js
  • package-lock.json
  • package.json
  • test.js

從這裡開始,我們將開始為應用程序添加我們的第一個實際測試。

添加數學運算

我們的應用程序的第一個要求是它應該加、減、除和乘任意兩個數字。這意味著我們必須為每個數學運算創建一個函數。

讓我們從加法開始。我們將編寫一個測試來計算我們知道為真的兩個數字的總和。下面的代碼正在測試 1 加上 3 等於 4add() 功能。

test.js
const assert = require('assert')

it('correctly calculates the sum of 1 and 3', () => {
  assert.equal(add(1, 3), 4)
})

使用 npm test 運行我們的測試後 ,我們會得到如下輸出:

> mocha

  0 passing (9ms)
  1 failing

  1) correctly calculates the sum of 1 and 3:
      ReferenceError: add is not defined
      at Context.it (test.js:5:16)

npm ERR! Test failed.  See above for more details.

測試失敗,給我們以下信息:ReferenceError: add is not defined .我們正在測試 add() 尚不存在的函數,因此此錯誤非常有意義。

operations.js 中 ,我們將創建 add() 功能。

操作.js
const add = (x, y) => +x + +y

add() 函數接受兩個參數 (xy ) 並返回它們的總和。你可能會注意到它被寫成 (+x) + (+y) 而不是 x + y .如果輸入是字符串,我們使用一元運算符將參數強制轉換為數字。

由於我們使用的是 Node.js 並將我們的代碼分成多個文件,因此我們需要使用 module.exports 導出代碼。

操作.js
const add = (x, y) => +x + +y

module.exports = { add }

test.js 的頂部 ,我們將導入我們的 operations.js require() 的代碼 .因為我們是通過 operations 引入函數 變量,我們將更改 add()operations.add() .

test.js
const operations = require('./operations.js')
const assert = require('assert')

it('correctly calculates the sum of 1 and 3', () => {
  assert.equal(operations.add(1, 3), 4)
})

運行測試。

npm test
> mocha

  ✓ correctly calculates the sum of 1 and 3

  1 passing (8ms)

現在我們有了一個工作函數,我們的測試按預期通過了。由於其他算術函數都遵循相同的模式,我們可以對 subtract() 進行測試 , multiply() , 和 divide() ,以及用於測試負整數的一種。

test.js
it('correctly calculates the sum of 1 and 3', () => {
  assert.equal(operations.add(1, 3), 4)
})

it('correctly calculates the sum of -1 and -1', () => {
  assert.equal(operations.add(-1, -1), -2)
})

it('correctly calculates the difference of 33 and 3', () => {
  assert.equal(operations.subtract(33, 3), 30)
})

it('correctly calculates the product of 12 and 12', () => {
  assert.equal(operations.multiply(12, 12), 144)
})

it('correctly calculates the quotient of 10 and 2', () => {
  assert.equal(operations.divide(10, 2), 5)
})

我們將在 operations.js 中創建和導出所有函數 ...

操作.js
const add = (x, y) => +x + +y
const subtract = (x, y) => +x - +y
const multiply = (x, y) => +x * +y
const divide = (x, y) => +x / +y

module.exports = {
  add,
  subtract,
  multiply,
  divide,
}

...並運行我們的新測試。

npm test
> mocha

  ✓ correctly calculates the sum of 1 and 3
  ✓ correctly calculates the sum of -1 and -1
  ✓ correctly calculates the difference of 33 and 3
  ✓ correctly calculates the product of 12 and 12
  ✓ correctly calculates the quotient of 10 and 2

  5 passing (8ms)

我們所有的測試都通過了,所以現在我們可以確定我們的應用程序的主要目標將正常運行。展望未來,我們將添加一些額外的驗證。

添加驗證

現在,如果用戶輸入任何數字並選擇一個操作,一切都會按預期進行。但是,如果他們試圖找到一個數字和一個字符串的總和會發生什麼✓ 應用程序會嘗試進行計算,但由於它期望數字,輸出將是 NaN , 或不是數字。

我們不只是返回奇怪的輸出,而是要填充應用程序的第二個目標 - 如果它收到任何不是數字的輸入,它應該顯示警告並退出。

首先,我們必須創建一個函數來測試輸入是否為數字。該應用程序將接受兩個數字,因此我們將測試三個內容:兩個輸入是否都是數字,是否只有一個是數字,以及兩個都不是數字。

test.js
it('indicates failure when a string is used instead of a number', () => {
  assert.equal(operations.validateNumbers('sammy', 5), false)
})

it('indicates failure when two strings is used instead of numbers', () => {
  assert.equal(operations.validateNumbers('sammy', 'sammy'), false)
})

it('successfully runs when two numbers are used', () => {
  assert.equal(operations.validateNumbers(5, 5), true)
})

我們的 validateNumbers() 函數將測試這兩個參數。 isNaN() 函數將檢查參數是否不是 數字,並將返回 false 如果是這樣。否則它將返回 true ,則驗證成功。

操作.js
const validateNumbers = (x, y) => {
  if (isNaN(x) && isNaN(y)) {
    return false
  }
  return true
}

確保添加 validateNumbersmodule.exports 在文件的底部。現在我們可以運行我們的新測試了。

npm test
1) indicates failure when a string is used instead of a number
✓ indicates failure when two strings is used instead of numbers
✓ successfully runs when two numbers are used

7 passing (12ms)
1 failing


1) indicates failure when a string is used instead of a number:

    AssertionError [ERR_ASSERTION]: true == false
    + expected - actual

    -true
    +false

其中兩個通過了,但一個失敗了。通過測試兩個數字的成功,以及測試兩個字符串的失敗。我們的第一個驗證測試,一個字符串和一個數字,失敗了。

回顧我們的函數,它需要 both 參數必須是 NaN 失敗。我們希望它失敗,即使只有一個參數是 NaN ,所以我們將更改 &&|| .

操作.js
const validateNumbers = (x, y) => {
  if (isNaN(x) || isNaN(y)) {
    return false
  }
  return true
}

一旦我們進行此更改並運行 npm test ,所有八項測試都會通過。

✓ indicates failure when a string is used instead of a number
✓ indicates failure when two strings is used instead of numbers
✓ successfully runs when two numbers are used

8 passing (9ms)

我們應用程序的所有功能都已經過測試。這些函數已被證明可以成功地進行數學運算並驗證輸入。最後一步是為用戶創建界面。

創建最終命令行界面

我們有必要的函數來進行算術和驗證,但目前用戶無法訪問這些函數。有必要使用一個接口。用戶界面可以是圖形用戶界面 (GUI) 或 命令行界面 (命令行界面)。我們將使用命令行界面來製作我們的應用程序。

目前,我們的 calc.js 文件為空。這是我們的應用程序將要存在的地方。首先,我們將從 operations.js 中提取函數 .

calc.js

const operations = require('./operations.js')

我們的界面本身將使用 Readline 模塊,這是一個內置的 Node.js CLI。

calc.js
const readline = require('readline')

現在我們已經滿足了所有需求,我們可以開始構建應用程序了。我們將訪問 readline 通過rl 變量來創建接口。

calc.js
// Use readline to create command line interface
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
})

我們希望用戶在運行程序時看到的第一件事是初始歡迎屏幕,它告訴他們他們打開了什麼,以及使用說明。我們將使用 console.log() .

calc.js
console.log(`
Calc.js

Welcome to the Node.js Calculator app! 
Version: 1.0.0.

Usage: The user will be prompted for two numbers, 
then asked to select their operation of choice.
`)

在我們開始使用計算器的實際功能之前,讓我們測試一下我們的 console.log() 工作正常。我們會讓我們的應用打印出消息,然後退出。 readline 將使用 rl.close() 方法退出。

calc.js
rl.close()

要使用 node 運行命令行應用程序,您將輸入 node 後跟文件名。

node calc.js
Calc.js

Welcome to the Node.js Calculator app!
Version: 1.0.0.

Usage: The user will be prompted for two numbers,
then asked to select their operation of choice.

我們的歡迎屏幕顯示,然後程序終止。下一步將是接受一些用戶輸入。我們總共需要三個:兩個數字和一個操作選擇。我們將使用 rl.question() 請求每個輸入 方法。

calc.js
rl.question('Enter the first number: ', (x) => {
  rl.question('Enter the second number: ', (y) => {
    rl.question(
      `
    Please select from the following options:
    
    [1] Addition (+)
    [2] Subtraction (-)
    [3] Multiplication (*)
    [4] Division (/)
    
    Enter your choice: `,
      (choice) => {
        // additional code to be added here
        rl.close()
      }
    )
  })
})

我們的第一個數字將使用 x 的參數輸入 , y 的第二個數字 , 和 choice 的操作選擇 .此時,運行程序將請求所需的輸入,但不會對它做任何事情。

在我們的第三個問題之後,我們要做的第一件事是驗證輸入以確保只輸入數字。我們將引用 validateNumbers() 功能。使用邏輯 NOT 運算符,我們將測試參數值是否為 not 數字,如果是則結束程序。

calc.js
if (!operations.validateNumbers(x, y)) {
  console.log('Only numbers are allowed! Please restart the program.')
}

如果所有輸入都有效且正確,我們將希望繼續該過程並運行我們之前創建的相應數學運算。我們將使用 switch 語句根據四種可能的選擇執行代碼,並輸出操作結果。如果做出了無效的選擇,default 代碼塊將運行,告訴用戶重新開始。

calc.js
if (!operations.validateNumbers(x, y)) {
  console.log('Only numbers are allowed! Please restart the program.')
} else {
  switch (choice) {
    case '1':
      console.log(`The sum of ${x} and ${y} is ${operations.add(x, y)}.`)
      break
    case '2':
      console.log(
        `The difference of ${x} and ${y} is ${operations.subtract(x, y)}.`
      )
      break
    case '3':
      console.log(
        `The product of ${x} and ${y} is ${operations.multiply(x, y)}.`
      )
      break
    case '4':
      console.log(
        `The quotient of ${x} and ${y} is ${operations.divide(x, y)}.`
      )
      break
    default:
      console.log(
        'Please restart the program and select a number between 1 and 4.'
      )
      break
  }
}

這是最終的代碼。

calc.js
/**
 * A simple Node.js calculator app that uses
 * the built-in Readline command line interface.
 */

const operations = require('./operations.js')
const readline = require('readline')

// Use readline to create command line interface
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
})

console.log(`
    Calc.js
    Welcome to the Node.js Calculator app! 
    Version: 1.0.0.
    Usage: The user will be prompted for two numbers, 
    then asked to select their operation of choice.
    `)

rl.question('Enter the first number: ', (x) => {
  rl.question('Enter the second number: ', (y) => {
    rl.question(
      `
    Please select from the following options:
    [1] Addition (+)
    [2] Subtraction (-)
    [3] Multiplication (*)
    [4] Division (/)
    Enter your choice: `,
      (choice) => {
        if (!operations.validateNumbers(x, y)) {
          console.log('Only numbers are allowed! Please restart the program.')
        } else {
          switch (choice) {
            case '1':
              console.log(
                `The sum of ${x} and ${y} is ${operations.add(x, y)}.`
              )
              break
            case '2':
              console.log(
                `The difference of ${x} and ${y} is ${operations.subtract(
                  x,
                  y
                )}.`
              )
              break
            case '3':
              console.log(
                `The product of ${x} and ${y} is ${operations.multiply(x, y)}.`
              )
              break
            case '4':
              console.log(
                `The quotient of ${x} and ${y} is ${operations.divide(x, y)}.`
              )
              break
            default:
              console.log(
                'Please restart the program and select a number between 1 and 4.'
              )
              break
          }
        }
        rl.close()
      }
    )
  })
})

我們的申請現已完成。讓我們測試一下最終的輸出。我們將輸入 9991 ,並請求減法運算。

node calc.js

Enter the first number: 999
Enter the second number: 1
Enter your choice: 2
The difference of 999 and 1 is 998.

一切順利進行,我們的輸出符合預期。恭喜!您已經使用 Node.js 成功創建了一個簡單的計算器應用程序,並在此過程中學習了測試驅動開發方法的基礎知識。

結論

如果你遺漏了什麼或者中途卡住了,你可以在 GitHub 上找到源代碼。

  • 在 GitHub 上查看源代碼

我們剛剛通過在 Node.js 中創建命令行計算器應用程序介紹了測試驅動開發的基礎知識。我們使用 Mocha 框架進行測試,並使用內置的 Node.js Readline 模塊來創建命令行界面。

向前推進的一個選擇是測試和實現計算器的新功能,例如添加對數字求平方或求餘數的功能,或者您可以為計算器實現一個循環方法來詢問用戶是否願意做另一個完成後計算。


Tutorial JavaScript 教程
  1. 使用 TypeScript 的 5 個理由

  2. 我對 API 的願景

  3. 如何使用 JavaScript 動態設置樣式 -webkit-transform?

  4. 更改數組中的對像不會觸發 html React 中的更改

  5. 2005 年編寫 JavaScript 的十個良好實踐

  6. 如果 Svelte 和 RxJS 有一個孩子

  7. JWT(JSON 網絡令牌)

  1. 提高程序員的工具

  2. 加號登錄查詢字符串

  3. 將 JSON 用於與語言無關的配置文件

  4. 我應該將 document.getElementById() 緩存在變量中還是每次都調用它?

  5. JavaScript 異步編程簡介

  6. 反應環境

  7. Next.js 中使用 react-paginate 的簡單分頁

  1. 使用 prefers-color-scheme 將深色主題應用到您的網站

  2. USB - Web 開發人員的視角

  3. 反應白屏死機:如何防止您的 UI 崩潰

  4. 10 個帶有 jQuery 插件/擴展的 Node.js