# 數據供給器
測試方法可以接受任意參數。這些參數由數據供給器方法(在 [Example?2.5, “使用返回數組的數組的數據供給器”](# "Example?2.5.?使用返回數組的數組的數據供給器")中,是 `additionProvider()` 方法)提供。用 `@dataProvider` 標注來指定使用哪個數據供給器方法。
數據供給器方法必須聲明為 `public`,其返回值要么是一個數組,其每個元素也是數組;要么是一個實現了 `Iterator` 接口的對象,在對它進行迭代時每步產生一個數組。每個數組都是測試數據集的一部分,將以它的內容作為參數來調用測試方法。
**Example?2.5.?使用返回數組的數組的數據供給器**
~~~
<?php
class DataTest extends PHPUnit_Framework_TestCase
{
/**
* @dataProvider additionProvider
*/
public function testAdd($a, $b, $expected)
{
$this->assertEquals($expected, $a + $b);
}
public function additionProvider()
{
return array(
array(0, 0, 0),
array(0, 1, 1),
array(1, 0, 1),
array(1, 1, 3)
);
}
}
?>
~~~
~~~
phpunit DataTest
PHPUnit 5.0.0 by Sebastian Bergmann and contributors.
...F
Time: 0 seconds, Memory: 5.75Mb
There was 1 failure:
1) DataTest::testAdd with data set #3 (1, 1, 3)
Failed asserting that 2 matches expected 3.
/home/sb/DataTest.php:9
FAILURES!
Tests: 4, Assertions: 4, Failures: 1.
~~~
當使用到大量數據集時,最好逐個用字符串鍵名對其命名,避免用默認的數字鍵名。這樣輸出信息會更加詳細些,其中將包含打斷測試的數據集所對應的名稱。
**Example?2.6.?使用帶有命名數據集的數據供給器**
~~~
<?php
class DataTest extends PHPUnit_Framework_TestCase
{
/**
* @dataProvider additionProvider
*/
public function testAdd($a, $b, $expected)
{
$this->assertEquals($expected, $a + $b);
}
public function additionProvider()
{
return array(
'adding zeros' => array(0, 0, 0),
'zero plus one' => array(0, 1, 1),
'one plus zero' => array(1, 0, 1),
'one plus one' => array(1, 1, 3)
);
}
}
?>
~~~
~~~
phpunit DataTest
PHPUnit 5.0.0 by Sebastian Bergmann and contributors.
...F
Time: 0 seconds, Memory: 5.75Mb
There was 1 failure:
1) DataTest::testAdd with data set "one plus one" (1, 1, 3)
Failed asserting that 2 matches expected 3.
/home/sb/DataTest.php:9
FAILURES!
Tests: 4, Assertions: 4, Failures: 1.
~~~
**Example?2.7.?使用返回迭代器對象的數據供給器**
~~~
<?php
require 'CsvFileIterator.php';
class DataTest extends PHPUnit_Framework_TestCase
{
/**
* @dataProvider additionProvider
*/
public function testAdd($a, $b, $expected)
{
$this->assertEquals($expected, $a + $b);
}
public function additionProvider()
{
return new CsvFileIterator('data.csv');
}
}
?>
~~~
~~~
phpunit DataTest
PHPUnit 5.0.0 by Sebastian Bergmann and contributors.
...F
Time: 0 seconds, Memory: 5.75Mb
There was 1 failure:
1) DataTest::testAdd with data set #3 ('1', '1', '3')
Failed asserting that 2 matches expected '3'.
/home/sb/DataTest.php:11
FAILURES!
Tests: 4, Assertions: 4, Failures: 1.
~~~
**Example?2.8.?CsvFileIterator 類**
~~~
<?php
class CsvFileIterator implements Iterator {
protected $file;
protected $key = 0;
protected $current;
public function __construct($file) {
$this->file = fopen($file, 'r');
}
public function __destruct() {
fclose($this->file);
}
public function rewind() {
rewind($this->file);
$this->current = fgetcsv($this->file);
$this->key = 0;
}
public function valid() {
return !feof($this->file);
}
public function key() {
return $this->key;
}
public function current() {
return $this->current;
}
public function next() {
$this->current = fgetcsv($this->file);
$this->key++;
}
}
?>
~~~
如果測試同時從 `@dataProvider` 方法和一個或多個 `@depends` 測試接收數據,那么來自于數據供給器的參數將先于來自所依賴的測試的。來自于所依賴的測試的參數對于每個數據集都是一樣的。參見[Example?2.9, “在同一個測試中組合使用 @depends 和 @dataProvider”](# "Example?2.9.?在同一個測試中組合使用 @depends 和 @dataProvider")
**Example?2.9.?在同一個測試中組合使用 @depends 和 @dataProvider**
~~~
<?php
class DependencyAndDataProviderComboTest extends PHPUnit_Framework_TestCase
{
public function provider()
{
return array(array('provider1'), array('provider2'));
}
public function testProducerFirst()
{
$this->assertTrue(true);
return 'first';
}
public function testProducerSecond()
{
$this->assertTrue(true);
return 'second';
}
/**
* @depends testProducerFirst
* @depends testProducerSecond
* @dataProvider provider
*/
public function testConsumer()
{
$this->assertEquals(
array('provider1', 'first', 'second'),
func_get_args()
);
}
}
?>
~~~
~~~
phpunit --verbose DependencyAndDataProviderComboTest
PHPUnit 5.0.0 by Sebastian Bergmann and contributors.
...F
Time: 0 seconds, Memory: 3.50Mb
There was 1 failure:
1) DependencyAndDataProviderComboTest::testConsumer with data set #1 ('provider2')
Failed asserting that two arrays are equal.
--- Expected
+++ Actual
@@ @@
Array (
- 0 => 'provider1'
+ 0 => 'provider2'
1 => 'first'
2 => 'second'
)
/home/sb/DependencyAndDataProviderComboTest.php:31
FAILURES!
Tests: 4, Assertions: 4, Failures: 1.
~~~
>[info] ### Note
> 如果一個測試依賴于另外一個使用了數據供給器的測試,僅當被依賴的測試至少能在一組數據上成功時,依賴于它的測試才會運行。使用了數據供給器的測試,其運行結果是無法注入到依賴于此測試的其他測試中的。
>
> 所有的數據供給器方法的執行都是在對 `setUpBeforeClass` 靜態方法的調用和第一次對 `setUp` 方法的調用之前完成的。因此,無法在數據供給器中使用創建于這兩個方法內的變量。這是必須的,這樣 PHPUnit 才能計算測試的總數量。
- PHPUnit 手冊
- 1. 安裝 PHPUnit
- 需求
- PHP 檔案包 (PHAR)
- Composer
- 可選的組件包
- 2. 編寫 PHPUnit 測試
- 測試的依賴關系
- 數據供給器
- 對異常進行測試
- 對 PHP 錯誤進行測試
- 對輸出進行測試
- 錯誤相關信息的輸出
- 3. 命令行測試執行器
- 命令行選項
- 4. 基境(fixture)
- setUp() 多 tearDown() 少
- 變體
- 基境共享
- 全局狀態
- 5. 組織測試
- 用文件系統來編排測試套件
- 用 XML 配置來編排測試套件
- 6. 有風險的測試
- 無用測試
- 意外的代碼覆蓋
- 測試執行期間產生的輸出
- 測試執行時長的超時限制
- 全局狀態篡改
- 7. 未完成的測試與跳過的測試
- 未完成的測試
- 跳過測試
- 用 @requires 來跳過測試
- 8. 數據庫測試
- 數據庫測試所支持的供應商
- 數據庫測試的難點
- 數據庫測試的四個階段
- PHPUnit 數據庫測試用例的配置
- 理解 DataSet(數據集)和 DataTable(數據表)
- 數據庫連接 API
- 數據庫斷言 API
- 常見問題(FAQ)
- 9. 測試替身
- Stubs (樁件)
- 仿件對象(Mock Object)
- Prophecy
- 對特質(Trait)與抽象類進行模仿
- 對 Web 服務(Web Services)進行上樁或模仿
- 對文件系統進行模仿
- 10. 測試實踐
- 在開發過程中
- 在調試過程中
- 11. 代碼覆蓋率分析
- 用于代碼覆蓋率的軟件衡量標準
- 包含與排除文件
- 略過代碼塊
- 指明要覆蓋的方法
- 邊緣情況
- 12. 測試的其他用途
- 敏捷文檔
- 跨團隊測試
- 13. Logging (日志記錄)
- 測試結果 (XML)
- 測試結果 (TAP)
- 測試結果 (JSON)
- 代碼覆蓋率 (XML)
- 代碼覆蓋率 (TEXT)
- 14. 擴展 PHPUnit
- 從 PHPUnit_Framework_TestCase 派生子類
- 編寫自定義斷言
- 實現 PHPUnit_Framework_TestListener
- 從 PHPUnit_Extensions_TestDecorator 派生子類
- 實現 PHPUnit_Framework_Test
- A. 斷言
- assertArrayHasKey()
- assertClassHasAttribute()
- assertArraySubset()
- assertClassHasStaticAttribute()
- assertContains()
- assertContainsOnly()
- assertContainsOnlyInstancesOf()
- assertCount()
- assertEmpty()
- assertEqualXMLStructure()
- assertEquals()
- assertFalse()
- assertFileEquals()
- assertFileExists()
- assertGreaterThan()
- assertGreaterThanOrEqual()
- assertInfinite()
- assertInstanceOf()
- assertInternalType()
- assertJsonFileEqualsJsonFile()
- assertJsonStringEqualsJsonFile()
- assertJsonStringEqualsJsonString()
- assertLessThan()
- assertLessThanOrEqual()
- assertNan()
- assertNull()
- assertObjectHasAttribute()
- assertRegExp()
- assertStringMatchesFormat()
- assertStringMatchesFormatFile()
- assertSame()
- assertStringEndsWith()
- assertStringEqualsFile()
- assertStringStartsWith()
- assertThat()
- assertTrue()
- assertXmlFileEqualsXmlFile()
- assertXmlStringEqualsXmlFile()
- assertXmlStringEqualsXmlString()
- B. 標注
- @author
- @after
- @afterClass
- @backupGlobals
- @backupStaticAttributes
- @before
- @beforeClass
- @codeCoverageIgnore*
- @covers
- @coversDefaultClass
- @coversNothing
- @dataProvider
- @depends
- @expectedException
- @expectedExceptionCode
- @expectedExceptionMessage
- @expectedExceptionMessageRegExp
- @group
- @large
- @medium
- @preserveGlobalState
- @requires
- @runTestsInSeparateProcesses
- @runInSeparateProcess
- @small
- @test
- @testdox
- @ticket
- @uses
- C. XML 配置文件
- PHPUnit
- 測試套件
- 分組
- 為代碼覆蓋率包含或排除文件
- Logging (日志記錄)
- 測試監聽器
- 設定 PHP INI 設置、常量、全局變量
- 為 Selenium RC 配置瀏覽器
- D. 升級
- E. 索引
- F. 參考書目
- G. 版權