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

前兩週課程回顧

詳細的課程心得可以參考

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

本週課程重點

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

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 ,如下。

<?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 囉。

<?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 ,範例如下:

# 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

直接執行下列指令。

$ ./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 哥這三天來的指導與分享,真的獲益良多。

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *