iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 2
0

來複習一下前一篇提到的 TDD 步驟:

  1. 寫測試: 在寫任何產品程式之前,只先編寫最少量、剛好能運作的自動化測試
  2. 寫程式: 編寫最少量、剛好能通過的產品程式
  3. 重構程式碼,並循環以上步驟

對於沒接觸過 TDD 的人來說,這樣的描述大概是一頭霧水,

所以今天直接用程式碼來說明,讓我們來看一段極簡風的範例,完整程式碼可以在Github取得,用$ git checkout切換查看。


假設我們要寫一個輸出 從1加到N 的函式
( PHP 版本: 7.3.8 )

步驟 1. 寫測試

<?php
// sum_n.php

assert(sum_n());

?>

『什麼!這樣是哪門子的單元測試?!它現在甚至連 function 名稱都還沒定義!』

第一次看到 TDD 大概會有這樣的疑惑,但這卻是符合步驟 1. 中所描述的「最少量、剛好能運作的測試」。

在每一次的步驟 1. 中,必定會編寫出一個「目前無法通過的測試」,而最小能運作的測試程式就是呼叫該 function 名稱,即使我們連 function 都還沒定義,不能編譯也算是無法通過 (需編譯的程式語言的話)。

Assertion (或稱斷言) assert() 是一種簡易的單元測試語法 [1],在多數的程式語言中都有,若是參數中傳入的值是 False,會跳出錯誤訊息。

這時執行看看 (簡單在 Terminal 中執行,不運行 Server [2, 3])

$ php sum_n.php

Terminal 上理所當然地出現了錯誤訊息,代表無法呼叫sum_n(),接著讓我們進入步驟 2.

PHP Fatal error:  Uncaught Error: Call to undefined function sum_n() in sum_n.php:4

步驟 2. 寫程式

<?php
// sum_n.php

function sum_n(){
    return 1;
}

assert(sum_n());

?>

( 若有下載範例程式碼,用$ git checkout 1a查看 )

編寫程式後再執行一次,雖然目前函式內還是空的

$ php sum_n.php

很好!這次沒有印出任何錯誤。

步驟 3. 重構程式碼,並循環以上步驟

目前程式碼還很少,判斷不需要重構,因此直接進入下一個循環。


步驟 1. 寫測試

<?php
// sum_n.php

function sum_n(){
    return 1;
}

assert(sum_n(4)==10);

?>

這次我們加入了,加總到 4 實際應該輸出的數字 10 的測試,接著編寫程式。

步驟 2. 寫程式

<?php
// sum_n.php

function sum_n($num){
    $result = 0;
    for($i = 1; $i<=$num; $i++){
        $result += $i;
    }
    return $result;
}

assert(sum_n(4)==10);

?>

( $ git checkout 1b )

太好了,sum_n()輸出了正確的總合,因此通過了測試。

步驟 3. 重構程式碼,並循環以上步驟

雖然是sum_n()的輸出已經是正確的總和,但卻是用很沒效率的方式做運算,

於是我們決定來修改一下。

<?php
// sum_n.php

function sum_n($num){
    $result = (1 + $num) * $num / 2;
    return $result;
}

assert(sum_n(4)==10);

?>

( $ git checkout 1c )

完成!

經過兩個循環,完成了我們的sum_n()函式。

是不是很簡單呢,一天馬上就學會了使用 TDD,下一篇我們來聊聊這樣違反直覺寫程式為什麼能帶來好處。


附註

  1. 之後的文章還會再提到單元測試與 Assertion,如果目前還不瞭解的話不用擔心。
  2. 這裡假設讀者已經瞭解如何在終端機 Terminal 上執行 command (CLI),且電腦已裝有 php 7。
  3. 這邊的範例在執行時,應該是不需要等待的,如果需要超過1、2秒以上,可以試著將/usr/local/php5/php.d/50-extension-imap.ini檔案中的extension=..imap.so此行註解掉。 (Ref: PHP from the terminal running very slow on new mac!)

上一篇
為什麼想講 TDD
下一篇
TDD 的理由
系列文
如何一步步實踐TDD (測試驅動開發)30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
ytyubox
iT邦新手 5 級 ‧ 2019-09-18 00:20:03

我習慣把 Library API的設計放在制定 test case 時,我會想像我會怎樣呼叫這個 API,預期的參數要怎麼處理,聽說這個作法是 API 的 Interface 為出發點 (design to interface).

Louis iT邦新手 5 級 ‧ 2019-09-18 09:49:16 檢舉

訂定Interface是設計階段蠻重要的部分,當團隊定好之後就可以讓成員同時開發各自的部分,減少相依性,不過目前我只能示範一個人寫的程式XD,

TDD的寫測試階段應該就算是在制定test case,不過是用編寫自動化測試的方式,並且跟開發穿插在一起。

ytyubox iT邦新手 5 級 ‧ 2019-09-18 11:08:53 檢舉

兩頂帽子的概念就是用在一個人的時候!

我要留言

立即登入留言