/ JavaScript

[測試] e2e 的測試方法 Day 0

End-to-End 測試,是近幾年開始流行的測試方法。身為一個農夫,其實沒有寫測試也是很合理的(不是!因應開發需求,所以趕流行也得開始寫一點測試的東西,不然會不夠潮!

這篇是相當入門的火星文,如果已經是火星人,請直接 End 謝謝。


前置作業

首先,測試工具有很多,在我們討論測試工具之前,要先釐清幾件事情:

  1. 測試是什麼東西?
  2. 該怎麼把想法變成測試程式?
  3. 測試的程式該怎麼寫?
  4. 要用哪一種測試工具?

「測試」顧名思義就是一種測試(廢話,目的在於驗證結果是否 正確,我們主要的目的在於確保 那個黑盒子 能夠正常運作。也就是說,在我們定義的邏輯沒有問題的前提下,那個黑盒子 應該要通過我們的測試。

舉個例子來說,我們有一台飲料販賣機,我拿出 10 元投入販賣機中,按了「 10 元 咖啡」這個飲料,他要掉出一罐咖啡給我。那個黑盒子 就是這台販賣機,我並不需要知道販賣機的實際運作方式是什麼,但是『他要掉出一罐咖啡給我』是最終的結果,我們的目的就是要 確保 這個結果是正確的。

pseudo-code 在想法變成程式之前

又稱為「虛擬碼是一種虛寶,我們在把想法變成程式碼之前,我們可以把想法條列出來,讓自己可以理解該做的事情、作法與結果的正確性。

就以剛剛的販賣機為例子,有一台飲料販賣機,上面有個「 10 元 咖啡」的飲料,

  1. 拿出 10 元
  2. 投入販賣機
  3. 按下「咖啡」的按鈕
  4. 掉下一罐咖啡
  5. 這個結果是 正確
  6. 這個測試結果是 通過

以上就是一段簡易的虛擬碼。虛擬碼在此處的用途,在於用以描述一件事情,將我們想做的事情以任何一種我們熟悉的語言來表達。所以,我們用習慣的自然語言來描述一個測試,讓自己可以理解要做的事情有哪些。接著在將其轉換成測試本身所需要的程式碼。

而,測試會有「通過」與「不通過」兩種,可能會讓初學者搞混的情況,就是「表述的結果」與「測試的結果」這兩者之間的關係。以剛剛販賣機的例子來說明,

有一台飲料販賣機,上面有個「 15 元 咖啡」的飲料,

  1. 拿出 10 元
  2. 投入販賣機
  3. 按下「咖啡」的按鈕
  4. 掉下一罐咖啡
  5. 這個結果是 錯誤
  6. 這個測試結果是 通過

為何『錯誤』的結果,測試卻是『通過』呢?我們再重頭看一次整個步驟,

  1. 拿出 10 元
  2. 投入販賣機
  3. 按下「咖啡」的按鈕
  4. 掉下一罐咖啡

一直到第四個步驟,有沒有發現什麼奇怪的地方?販賣機上的標價是「 15 元 咖啡」,但是,我用 10 元就買到了,如果你覺得這個很正常(請告訴我這台販賣機在哪裡,那會不會是投入了美金 10 元呢(不是

所以,

  1. 這個結果是 錯誤

這樣的描述是正確的,投入 10 元按下 15 元咖啡,卻買到了,所以,我們可以知道這個結果是 錯誤 的!

所以,

  1. 這個測試結果是 通過

由於我們 認知 到這個結果是 錯誤 的,所以會 通過 這一項測試。以上這樣的步驟,就有助於我們去釐清一件事情的結果,與該項測試的正確性。這就是虛擬碼在測試步驟中,可以幫助到我們的地方。

換成程式碼

我們有了虛擬碼,就能明確的知道 接下來要做什麼,與程式碼應該依循什麼樣的步驟去做。所以,無論是採用哪一種程式語言做測試的開發,我們都可以有一個明確的指示,依照這樣的指示做就不會出錯(除非程式寫錯

所以,我們可以簡易的將販賣機的測試寫成程式碼,以下用簡單的 JavaScript 來說明,

// 以下的測試程式碼是舉例,並不能真的執行,請不要丟到你熟悉的測試工具裡面跑,一定不會動的喔(啾咪

// 拿出了 10 元 (1)
let coin = 10;

// 這裡有一台飲料販賣機
vendingMachine
  // 投入 10 元到販賣機 (2)
  .put(coin)
  // 我按下了咖啡的飲料按鈕 (3)
  .press('咖啡')
  // 販賣機掉出了飲料 (4)
  .drop(drink => {
    // 這個飲料應該要是咖啡  (5, 6)
    // 5. drink, '咖啡'
    // 6. this.assets.equals 方法
    this.assets.equals(result, '咖啡');
  });

上述程式碼註解中的數字,代表了我們在虛擬碼當中的步驟。關於最後的兩點,可能初學者會比較困擾,如果翻譯成地球話來說,大概可以這樣說明,

  1. 虛擬碼中,我們要他掉出一罐咖啡 (5)
  2. 所以我們指定了我們想要的 咖啡
  3. 接著虛擬碼中,我們的測試結果要「通過」,表示販賣機掉出來的飲料 drink,是我們想要的 咖啡
  4. 所以,我們使用 this.assets.equals 用來檢驗結果是否「相等」,這個方法大多是由測試工具提供,在此只是簡單舉例
  5. 承上,這個方法需要放入要比對的東西,所以放入了販賣機掉出來的 drink 與 我們想要的 咖啡
  6. 如果這個測試「通過」,就表示我們的測試是正確的,販賣機確實掉出了 咖啡
  7. 如果這個測試「不通過」,就表示我們的測試失敗了,販賣機沒有掉出 咖啡,而是其他的東西

「不通過」代表什麼事情?

  1. 販賣機有 Bug
  2. 販賣機有 Bug
  3. 販賣機有 Bug
  4. 販賣機有 Bug
  5. 販賣機有 Bug

如果販賣機堅持這是 Feature,那就是 詐騙,請撥 165 反詐騙專線(地方農夫關心您

測試的工具

市面上有非常多種 e2e 的測試工具,大多都離不開以 Selenium 為底子的工具,例如,

  1. nightwatch.js
  2. cypress.io
  3. mochajs
  4. webdriver.io

雖然身為農夫都種過,不過目前開發以 nightwatch.js 測試框架為主力,所以,後續會在持續介紹這個工具的相關應用(如果有時間的話

小結

身為農夫,不寫測試也是很合理的(挺