Fixtures (基礎設施)
通常在測試裡面,我們會需要初始化我們的測試環境 (例如建立一個被測試類別的物件) ,但如果每一個測試都要做一次初始化的動作,就會非常麻煩。
雖然可以把初始化的動作包裝成一個方法,但還是需要每次都在測試一開始時手動呼叫。如果這個動作可以讓自動測試幫我們處理,就會方便很多。
setUp
方法與 tearDown
方法
PHPUnit 提供了一組協助我們初始化測試環境的方法,即 setUp
方法與 tearDown
方法。而在 setUp
方法 初始化,以供所有測試共用的物件或變數,則稱為 fixture 。
在 setUp
方法中,會將 fixture 初始化,讓每個測試都可以使用 fixture 最初的狀態。而在 tearDown
方法中,一般是會將 fixture 消滅,以釋出它所佔用的記憶體,否則就得靠不確定何時會執行的 GC (垃圾收集) 。
修改測試
以下程式為引入 fixture 後的寫法:
<?php
/* tests/CartTest.php */
require __DIR__ . '/../Cart.php';
class CartTest extends PHPUnit_Framework_TestCase
{
private $cart = null;
public function setUp()
{
$this->cart = new Cart();
}
public function tearDown()
{
$this->cart = null;
}
/**
* @dataProvider provider
* @group update
*/
public function testUpdateQuantitiesAndGetTotal($quantities, $expected)
{
$this->cart->updateQuantities($quantities);
$this->assertEquals($expected, $this->cart->getTotal());
}
// ...
/**
* @group update
* @group exception
*/
public function testUpdateQuantitiesWithException()
{
$this->setExpectedException('CartException');
$quantities = [ -1, 0, 0, 0, 0, 0 ];
$this->cart->updateQuantities($quantities); // 預期會產生一個 Exception
}
/**
* @group get
*/
public function testGetProducts()
{
$products = $this->cart->getProducts();
$this->assertEquals(6, count($products));
$this->assertEquals(0, $products[3]['quantity']);
}
}
主要改變有:
加入一個 fixture ,即私有屬性
$cart
。加入
setUp
與tearDown
兩個方法;setUp
方法負責初始化 fixture ,將它設定為Cart
類別的物件實體;而tearDown
方法則清除 fixture 所佔用的記憶體。將原有測試中的
$cart = new Cart();
移除,並將$cart
改為$this->cart
。
執行順序
每個測試方法執行之前,都會先執行 setUp
方法;而結束之後,則會執行 tearDown
方法。以此例來說,順序如下:
setUp
testUpdateQuantitiesAndGetTotal
tearDown
setUp
testUpdateQuantitiesAndGetTotal
tearDown
setUp
testUpdateQuantitiesWithException
tearDown
setUp
testGetProducts
tearDown
官方手冊參考
練習
解釋為什麼
$this->cart
可以在每個測試中使用?思考看看為什麼每次執行測試前,都要重新初始化 fixture ?