PHPUnit9.0 编写PHPUnit测试-数据供给器
测试方法可以接受任意参数。这些参数由一个或多个数据供给器方法(在示例 2.5 中,是 additionProvider()
方法)提供。用 @dataProvider
标注来指定要使用的数据供给器方法。
数据供给器方法必须声明为 public
,其返回值要么是一个数组,其每个元素也是数组;要么是一个实现了 Iterator
接口的对象,在对它进行迭代时每步产生一个数组。每个数组都是测试数据集的一部分,将以它的内容作为参数来调用测试方法。
示例 2.5 使用返回数组的数组的数据供给器
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
final class DataTest extends TestCase
{
/**
* @dataProvider additionProvider
*/
public function testAdd(int $a, int $b, int $expected): void
{
$this->assertSame($expected, $a + $b);
}
public function additionProvider(): array
{
return [
[0, 0, 0],
[0, 1, 1],
[1, 0, 1],
[1, 1, 3]
];
}
}
$ phpunit DataTest
PHPUnit latest.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 is identical to 3.
/home/sb/DataTest.php:9
FAILURES!
Tests: 4, Assertions: 4, Failures: 1.
当使用到大量数据集时,最好逐个用字符串键名对其命名,避免用默认的数字键名。这样输出信息会更加详细些,其中将包含打断测试的数据集所对应的名称。
示例 2.6 将数据供给器与命名数据集一起使用
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
final class DataTest extends TestCase
{
/**
* @dataProvider additionProvider
*/
public function testAdd(int $a, int $b, int $expected): void
{
$this->assertSame($expected, $a + $b);
}
public function additionProvider(): array
{
return [
'adding zeros' => [0, 0, 0],
'zero plus one' => [0, 1, 1],
'one plus zero' => [1, 0, 1],
'one plus one' => [1, 1, 3]
];
}
}
$ phpunit DataTest
PHPUnit latest.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 is identical to 3.
/home/sb/DataTest.php:9
FAILURES!
Tests: 4, Assertions: 4, Failures: 1.
示例 2.7 使用返回 Iterator 对象的数据供给器
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
final class DataTest extends TestCase
{
/**
* @dataProvider additionProvider
*/
public function testAdd(int $a, int $b, int $expected): void
{
$this->assertSame($expected, $a + $b);
}
public function additionProvider(): CsvFileIterator
{
return new CsvFileIterator('data.csv');
}
}
$ phpunit DataTest
PHPUnit latest.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 is identical to 3.
/home/sb/DataTest.php:11
FAILURES!
Tests: 4, Assertions: 4, Failures: 1.
示例 2.8 CsvFileIterator 类
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
final class CsvFileIterator implements Iterator
{
private $file;
private $key = 0;
private $current;
public function __construct(string $file)
{
$this->file = fopen($file, 'r');
}
public function __destruct()
{
fclose($this->file);
}
public function rewind(): void
{
rewind($this->file);
$this->current = fgetcsv($this->file);
$this->key = 0;
}
public function valid(): bool
{
return !feof($this->file);
}
public function key(): int
{
return $this->key;
}
public function current(): array
{
return $this->current;
}
public function next(): void
{
$this->current = fgetcsv($this->file);
$this->key++;
}
}
如果测试同时从 @dataProvider
方法和一个或多个 @depends
测试接收数据,那么来自于数据供给器的参数将先于来自所依赖的测试的。来自于所依赖的测试的参数对于每个数据集都是一样的。参见示例 2.9
示例 2.9 在同一个测试中组合 @depends
和 @dataProvider
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
final class DependencyAndDataProviderComboTest extends TestCase
{
public function provider(): array
{
return [['provider1'], ['provider2']];
}
public function testProducerFirst(): void
{
$this->assertTrue(true);
return 'first';
}
public function testProducerSecond(): void
{
$this->assertTrue(true);
return 'second';
}
/**
* @depends testProducerFirst
* @depends testProducerSecond
* @dataProvider provider
*/
public function testConsumer(): void
{
$this->assertSame(
['provider1', 'first', 'second'],
func_get_args()
);
}
}
$ phpunit --verbose DependencyAndDataProviderComboTest
PHPUnit latest.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 identical.
--- Expected
+++ Actual
@@ @@
Array &0 (
- 0 => 'provider1'
+ 0 => 'provider2'
1 => 'first'
2 => 'second'
)
/home/sb/DependencyAndDataProviderComboTest.php:32
FAILURES!
Tests: 4, Assertions: 4, Failures: 1.
示例 2.10 对单个测试使用多个数据供给器
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
final class DataTest extends TestCase
{
/**
* @dataProvider additionWithNonNegativeNumbersProvider
* @dataProvider additionWithNegativeNumbersProvider
*/
public function testAdd(int $a, int $b, int $expected): void
{
$this->assertSame($expected, $a + $b);
}
public function additionWithNonNegativeNumbersProvider(): void
{
return [
[0, 1, 1],
[1, 0, 1],
[1, 1, 3]
];
}
public function additionWithNegativeNumbersProvider(): array
{
return [
[-1, 1, 0],
[-1, -1, -2],
[1, -1, 0]
];
}
}
$ phpunit DataTest
PHPUnit latest.0 by Sebastian Bergmann and contributors.
..F... 6 / 6 (100%)
Time: 0 seconds, Memory: 5.75Mb
There was 1 failure:
1) DataTest::testAdd with data set #3 (1, 1, 3)
Failed asserting that 2 is identical to 3.
/home/sb/DataTest.php:12
FAILURES!
Tests: 6, Assertions: 6, Failures: 1.
如果一个测试依赖于另外一个使用了数据供给器的测试,仅当被依赖的测试至少能在一组数据上成功时,依赖于它的测试才会运行。使用了数据供给器的测试,其运行结果是无法注入到依赖于此测试的其他测试中的。
所有数据供给器方法的执行都是在对 setUpBeforeClass()
静态方法的调用和第一次对 setUp()
方法的调用之前完成的。因此,无法在数据供给器中使用创建于这两个方法内的变量。这是必须的,这样 PHPUnit 才能计算测试的总数量。
更多建议: