Data Providers (數據提供者)
類似的斷言太多寫起來感覺很麻煩,可以用數據提供者 (Data Providers) 來提供測試數據。
改用數據提供者
我們可以在測試方法的 DocBlock 上使用 @dataProvider
註記來告訴測試方法從何處取得測試數據,然後再一一代入測試方法的參數中。原來的程式修改如下:
<?php
/* tests/CartTest.php */
require __DIR__ . '/../Cart.php';
class CartTest extends PHPUnit_Framework_TestCase
{
/**
* @dataProvider provider
*/
public function testUpdateQuantitiesAndGetTotal($quantities, $expected)
{
$cart = new Cart();
$cart->updateQuantities($quantities);
$this->assertEquals($expected, $cart->getTotal());
return $cart;
}
public function provider()
{
return [
[ [ 1, 0, 0, 0, 0, 0 ], 199 ],
[ [ 1, 0, 0, 2, 0, 0 ], 797 ],
];
}
/**
* @depends testUpdateQuantitiesAndGetTotal
*/
public function testGetProducts($cart)
{
$products = $cart->getProducts();
$this->assertEquals(6, count($products));
$this->assertEquals(2, $products[3]['quantity']);
}
}
主要修改的部份有:
加入
provider
方法,它將提供一個包含多組測試數據的數據集。每一組數據即表示要傳到testUpdateQuantitiesAndGetTotal
方法的參數。在
testUpdateQuantitiesAndGetTotal
方法的 DocBlock 加入@dataProvider provider
來取得測試數據。
執行結果如下:
C:\project> phpunit tests/CartTest
PHPUnit 4.2.5 by Sebastian Bergmann.
..PHP Fatal error: Call to a member function getProducts() on a non-object in C:\project\tests\CartTest.php on line 34
結果發生錯誤,因為使用了 Data Provider 的測試,它的輸出將無法注入到其他相依於它的測試。
我們暫時把相依性拿掉,並修改斷言的預期結果:
<?php
/* tests/CartTest.php */
require __DIR__ . '/../Cart.php';
class CartTest extends PHPUnit_Framework_TestCase
{
/**
* @dataProvider provider
*/
public function testUpdateQuantitiesAndGetTotal($quantities, $expected)
{
$cart = new Cart();
$cart->updateQuantities($quantities);
$this->assertEquals($expected, $cart->getTotal());
}
public function provider()
{
return [
[ [ 1, 0, 0, 0, 0, 0 ], 199 ],
[ [ 1, 0, 0, 2, 0, 0 ], 797 ],
];
}
public function testGetProducts()
{
$cart = new Cart();
$products = $cart->getProducts();
$this->assertEquals(6, count($products));
$this->assertEquals(0, $products[3]['quantity']);
}
}
再次執行測試就成功了:
C:\project> phpunit tests/CartTest
PHPUnit 4.2.5 by Sebastian Bergmann.
...
Time: 25 ms, Memory: 3.00Mb
OK (3 tests, 4 assertions)
使用數據提供者的注意事項
Data Providers 的參數將優先於來自所依賴的測試的參數,而非 DocBlock 上定義的順序。
來自於所依賴的測試的參數對於每個數據集都是一樣的。
當一個測試依賴於另外一個使用了 Data Provider 的測試時,僅當被依賴的測試至少能在一組數據上成功時,依賴於它的測試才會運行。
官方手冊參考
練習
試著在
provider
方法中加入一些數據組,然後測試看看是否符合預期。在官方手冊的
Data Provider
一節提到了使用 PHP Iterator 來做為數據提供者,試著實作看看。