自動測試與 TDD 實務開發(使用 C#) by 91 哥 Day3

前兩週課程回顧

詳細的課程心得可以參考

上週提到了如何透過 Selenium 與 Unit Test 來進行前後搭配完整測試,透過 Unit Test 來進行最小單元測試,確保「程式照我們預期進行」,透過 E2E Testing 「確保程式可以照使用者期望執行」,透過兩者同時對 Legacy Code 進行完整測試,還有什麼比這個更能放心的去 Refactor Legacy Code 呢?

本週課程重點

本週課程將學習透過 BDD 來描述使用者需求,透過人的話語來描述測試案例,讓 PORD 間的 GAP 縮小,那什麼是透過人的話與來描述測試案例呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
Feature: PotterShoppingCart
In order to 提供最便宜的價格給來買書的爸爸媽媽
As a 佛心的出版社老闆
I want to 設計一個哈利波特的購物車
Scenario: 第一集買了一本,其他都沒買,價格應為100*1=100
Given 第一集買了 1
And 第二集買了 0
And 第三集買了 0
And 第四集買了 0
And 第五集買了 0
When 結帳
Then 價格應為 100

看完是否相當的直覺呢,我相信不是工程師也可以相當容易理解情境所要描述的測試案例。透過 BDD 除了可以提昇與 PO 溝通的效率,也可以自動產生 Document 與 Report 相當的方便。

如何透過 PHP 進行 BDD 測試

以下簡單的介紹如何將 feature 轉為可以測試的 PHP 程式碼, PHP 有兩套可以實踐 BDD:

以下會使用 Behat 進行範例解釋。

首先直接在 Scenario 那邊直接使用 [alt + Enter] 並且點選 Create all steps definition 建立 Feature Context ,如下圖。

預設會將 Feature Context 建置在 features/bootstrap 裡面,即會發現他已經針對每個動作建立了相對應的 method ,如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<?php
use Behat\Behat\Context\Context;
class FeatureContext implements Context
{
/**
* @Given /^第一集買了 (\d+) 本$/
*/
public function 第一集買了本($arg1)
{
throw new \Behat\Behat\Tester\Exception\PendingException();
}
/**
* @Given /^第二集買了 (\d+) 本$/
*/
public function 第二集買了本($arg1)
{
throw new \Behat\Behat\Tester\Exception\PendingException();
}
/**
* @Given /^第三集買了 (\d+) 本$/
*/
public function 第三集買了本($arg1)
{
throw new \Behat\Behat\Tester\Exception\PendingException();
}
/**
* @Given /^第四集買了 (\d+) 本$/
*/
public function 第四集買了本($arg1)
{
throw new \Behat\Behat\Tester\Exception\PendingException();
}
/**
* @Given /^第五集買了 (\d+) 本$/
*/
public function 第五集買了本($arg1)
{
throw new \Behat\Behat\Tester\Exception\PendingException();
}
/**
* @When /^結帳$/
*/
public function 結帳()
{
throw new \Behat\Behat\Tester\Exception\PendingException();
}
/**
* @Then /^價格應為 (\d+) 元$/
*/
public function 價格應為元($arg1)
{
throw new \Behat\Behat\Tester\Exception\PendingException();
}
}

接下來只需要將相對應 method 的行為修改一下,即可進行 BDD Testing 囉。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
<?php
use App\PotterShoppingCart;
use Behat\Behat\Context\Context;
use PHPUnit_Framework_Assert as PHPUnit;
class FeatureContext implements Context
{
private $potterShoppingCart;
private $total_price;
public function __construct()
{
$this->potterShoppingCart = new PotterShoppingCart();
}
/**
* @Given /^第一集買了 (\d+) 本$/
* @param int $number
*/
public function 第一集買了本(int $number)
{
$this->potterShoppingCart->addBook(1, $number);
}
/**
* @Given /^第二集買了 (\d+) 本$/
* @param int $number
*/
public function 第二集買了本(int $number)
{
$this->potterShoppingCart->addBook(2, $number);
}
/**
* @Given /^第三集買了 (\d+) 本$/
* @param int $number
*/
public function 第三集買了本(int $number)
{
$this->potterShoppingCart->addBook(3, $number);
}
/**
* @Given /^第四集買了 (\d+) 本$/
* @param int $number
*/
public function 第四集買了本(int $number)
{
$this->potterShoppingCart->addBook(4, $number);
}
/**
* @Given /^第五集買了 (\d+) 本$/
* @param int $number
*/
public function 第五集買了本(int $number)
{
$this->potterShoppingCart->addBook(5, $number);
}
/**
* @When /^結帳$/
*/
public function 結帳()
{
$this->total_price = $this->potterShoppingCart->getPrice();
}
/**
* @Then /^價格應為 (\d+) 元$/
* @param $expected
*/
public function 價格應為元($expected)
{
PHPUnit::assertEquals($expected, $this->total_price);
}
}

修改完成後執行測試。

一樣會有紅綠燈可以查看,但還沒結束唷,還可以透過 BDD 來產生文件,在這邊我使用了 「BehatHtmlFormatterPlugin」這個套件來產生漂亮的 HTML 文件。

安裝完成之後先於根目錄中增加 behat.yml ,範例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# behat.yml
default:
formatters:
html:
output_path: %paths.base%/build/html/behat
extensions:
emuse\BehatHTMLFormatter\BehatHTMLFormatterExtension:
name: html
renderer: Twig,Behat2
file_name: index
print_args: true
print_outp: true
loop_break: true

直接執行下列指令。

1
$ ./vendor/bin/behat --format html

即可於 build/html/behat/ 資料夾中看到已經 build 好的 html 網頁。

看到這邊,是不是覺得既簡單又好使用呢?

總結

上完課程後對於 TDD 與 BDD 不管是觀念還是實戰演練都有了更深刻的體會,老師上課透過完整的 Lab 題目讓大家有非常非常多的情境可以進行練習,就連我這個沒有在寫 C# 且沒有用過 Visual Studio 的工程師來說,要跟上老師的課程也是蠻 OK 的,由於老師上課分享的內容實在太豐富了,於本 Blog 中僅能擷取一些重點進行分享,扎實的課程與實戰體驗就是在課程上課已學到的,如果大家尚未使用 TDD 進行開發或是已經有在使用但不是很瞭解或不知該如何導入專案中,相當推薦大家可以來上「自動測試與 TDD 實務開發」Joey ( 91 哥 ) 的課程,詳細請 Follow SkillTree,也感謝 91 哥這三天來的指導與分享,真的獲益良多。