資料提供者,能提供多筆的測試資料給測試案例進行多次的測試。
使用資料提供者,能讓測試更簡潔,因為,可以將測試的 assertions 與測試資料分開寫。
* ● 測試 3 - 限制報名人數*
在一開始有提到,活動報名系統,會限制每個活動的報名人數。測試案例要測試多個不同報名人數的活動,如果報名成功,reserve()
會回傳 true
,相反的報名失敗則回傳 false
。
src/PHPUnitEventDemo/Event.php
This e-mail address is being protected from spambots. You need JavaScript enabled to view it
';
$user = new \PHPUnitEventDemo\User($userId, $userName, $userEmail);
// 同一個使用者報名兩次
$event->reserve($user);
$event->reserve($user);
}
}
在 EventTest
內增加一個 testDuplicatedReservationWithException()
測試案例,在註解內標註:
@expectedException \PHPUnitEventDemo\EventException
: 預期的異常類別。@expectedExceptionMessage Duplicated reservation
: 預期的異常訊息。@expectedExceptionCode 1
: 預期的異常代碼。也就是,預期在這個測試案例內會接收到 EventException
的異常類別、異常訊息為 Duplicated reservation
,異常代碼為 1。
執行測試:
$ phpunit --bootstrap vendor/autoload.php tests/EventTest
PHPUnit 4.4.0 by Sebastian Bergmann.
.....
Time: 53 ms, Memory: 3.50Mb
OK (5 tests, 19 assertions)
Fixture 能協助測試時,需要用到的測試環境、物件的建立,在測試完後,把測試環境、物件拆解掉,還原到初始化前的狀態。
主要透過 setUp()
與 tearDown()
分別來初始化測試與拆解還原到初始化前的狀態。
下面一樣利用 test/EventTest.php 來示範,先了解目前測試有哪些問題。
tests/EventTest.php
This e-mail address is being protected from spambots. You need JavaScript enabled to view it
';
$user = new \PHPUnitEventDemo\User($userId, $userName, $userEmail);
// ignore ...
}
// ignore ...
/**
* @expectedException \PHPUnitEventDemo\EventException
* @expectedExceptionMessage Duplicated reservation
* @expectedExceptionCode 1
*/
public function testDuplicatedReservationWithException()
{
// 測試重複報名,預期丟出異常
$eventId = 1;
$eventName = '活動1';
$eventStartDate = '2014-12-24 12:00:00';
$eventEndDate = '2014-12-24 13:30:00';
$eventDeadline = '2014-12-23 23:59:59';
$eventAttendeeLimit = 10;
$event = new \PHPUnitEventDemo\Event($eventId, $eventName, $eventStartDate, $eventEndDate, $eventDeadline, $eventAttendeeLimit);
$userId = 1;
$userName = 'User1';
$userEmail = '
This e-mail address is being protected from spambots. You need JavaScript enabled to view it
';
$user = new \PHPUnitEventDemo\User($userId, $userName, $userEmail);
// ignore ...
}
}
注意 testReserve()
、testDuplicatedReservationWithException()
兩個測試案例,都需要在測試前建立 Event
與 User
物件,使用 setUp()
在測試前,建立兩個物件,測試完後,tearDown()
再把不需要的物件清空。
加入 fixtures 後
tests/PHPUnitEventDemo.php
This e-mail address is being protected from spambots. You need JavaScript enabled to view it
';
$this->user = new \PHPUnitEventDemo\User($userId, $userName, $userEmail);
}
public function tearDown()
{
$this->event = null;
$this->user = null;
}
public function testReserve()
{
// 測試報名
// 使用者報名活動
$this->event->reserve($this->user);
$expectedNumber = 1;
// 預期報名人數
$this->assertEquals($expectedNumber, $this->event->getAttendeeNumber());
// 報名清單中有已經報名的人
$this->assertContains($this->user, $this->event->attendees);
return $this->event;
}
// ignore ...
/**
* @expectedException \PHPUnitEventDemo\EventException
* @expectedExceptionMessage Duplicated reservation
* @expectedExceptionCode 1
*/
public function testDuplicatedReservationWithException()
{
// 測試重複報名,預期丟出異常
// 同一個使用者報名兩次
$this->event->reserve($this->user);
$this->event->reserve($this->user);
}
}
把 $event
、$user
物件修改成全域變數,接著把建立物件寫在 setUp()
中,清空物件寫在 tearDown()
,再將 原本 testReserve()
與 testDuplicatedReservationWithException()
中的 建立 $event
與 $user
物件程式移掉,且使用到這兩個變數改成使用全域變數,也就是 $this->event
、$this->user
。
所以在執行測試的時候,運作順序會是:
setUp()
→ testReserve()
→ tearDown()
→ … → setUp()
→ testDuplicatedReservationWithException()
→ tearDown()
在前面此用 PHPUnit 工具來執行測試時,有用到 –bootstrap,在執行測試前先執行 vendor/autoload.php 程式來註冊 autoloading 的 function。可是每次執行測試,都要加上參數有點麻煩,所以,PHPUnit 可以利用 XML 設定檔來設定。
將 phpunit.xml 設定檔放在專案目錄下,與 src、tests 同一層。
phpunit.xml
bootstrap="./vendor/autoload.php">
name="MyEventTests">
./tests/EventTest.php
: 加入 bootstrap
屬性,對應到的值就是要執行的程式檔案。
: 在專案底下,能採用不同的測試組合。由一至多個的 。
組成。
: name
屬性,設定測試組合的名稱。測試組合內會包括許多測試程式檔案。執行測試,如果 XML 設定檔檔名不是 phpunit.xml 的話,可以利用 --configuraton
來指定 XML 設定檔的路徑,如果檔名是 phpunit.xml ,就能省略不指定。
$ phpunit --configuration phpunit.xml tests/EventTest
也可以執行不同的測試組合。
$ phpunit MyEventTests
還有更多 XML 設定檔可以使用,參考:https://phpunit.de/manual/current/en/appendixes.configuration.html
撰寫好單元測試之後,該如何了解到哪些目標程式還沒有經過測試?目標程式被測試百分比有多少?
PHPUnit 是利用 PHP_CodeCoverage 來計算程式碼覆蓋率 (Code coverage),需要安裝 Xdebug。
該如何產生 Code coverage 呢?
先在專案底下建立一個 reports/ 目錄,存放 Code coverage 分析的結果。
$ phpunit --bootstrap vendor/autoload.php phpunit.xml --coverage-html reports/ tests/
當然,也可以使用 XML 設定檔來設定。
phpunit.xml
bootstrap="./vendor/autoload.php">
name="MyEventTests">
./tests/EventTest.php
type="coverage-html" target="reports/" charset="UTF-8"/>
接著執行測試:
$ phpunit tests/
就可以在 reports/ 下打開 index.html 或其他 HTML 檔案,瀏覽 Code coverage 分析的結果。