php PHPUnit 和数据提供者的问题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4262309/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Problem with PHPUnit and Data Providers
提问by netcoder
I have the following test case:
我有以下测试用例:
include_once('../Logger.php');
class LoggerTest extends PHPUnit_Framework_TestCase {
public function providerLogger() {
return new Logger;
}
/**
* @dataProvider providerLogger
*/
public function testAddStream($logger) {
$this->assertTrue(false);
}
}
When I run it in PHPUnit, I get:
当我在 PHPUnit 中运行它时,我得到:
PHPUnit 3.4.14 by Sebastian Bergmann.
..........
Time: 0 seconds, Memory: 5.75Mb
OK (1 tests, 0 assertions)
Test should fail, but it doesn't. I tried having:
测试应该失败,但事实并非如此。我试过有:
public function providerLogger() {
return array(new Logger);
}
But I get:
但我得到:
The data provider specified for LoggerTest::testAddStream is invalid.
I tried declaring it static
(like the manual says), but still no difference.
我尝试声明它static
(如手册所说),但仍然没有区别。
I remember having it working in a similar fashion before, but I could be wrong. What am I missing?
我记得以前它以类似的方式工作,但我可能是错的。我错过了什么?
Thanks in advance for your help.
在此先感谢您的帮助。
PHPUnit 3.4.14 (taken from PEAR) on PHP 5.3.3
PHPUnit 3.4.14(取自 PEAR)在 PHP 5.3.3 上
回答by KingCrunch
Minor update: It's OK to use instance methods as provider since version 3.2 (or somewhere around that). Have a look at the comments
次要更新:从 3.2 版(或附近的某个地方)开始,可以使用实例方法作为提供者。看看评论
The provider must look like this.
提供者必须看起来像这样。
public static function providerLogger() {
return array(
array(new Logger)
);
}
First of all: The method must be staticif you are using phpunit version lower than 3.3 .
首先:如果您使用的 phpunit 版本低于 3.3 ,则该方法必须是静态的。
The arrays are important. Its not that hard to understand. The outer array has one value for each iteration the test should get called. Here the test just get called once. The inner arrays are the parameters (in order) the test is invoked with. Your test expects exactly one parameter, so the inner arrays always needs exactly one value. Another little example
该阵列的人非常重要。它并不难理解。对于应该调用测试的每次迭代,外部数组都有一个值。这里测试只被调用一次。内部数组是调用测试的参数(按顺序)。您的测试只需要一个参数,因此内部数组始终只需要一个值。另一个小例子
public static function addTestProvider () {
return array(
/* First + Second = third? */
array(1,4,5),
array(3,3,6),
array(5,5,6)
);
}
public function testAdd ($a, $b, $result) {
$this->assertEquals($result, $a + $b);
}
Here testAddgets executed 3 times, one for every second-level array, and it will receive the values from the inner arrays. You may notice, that the test will fail and provides you a message in which iteration of the dataset (here #3, because 5+5 is not 6 ;)) the assertion failed.
这里testAdd被执行 3 次,每个二级数组执行一次,它将接收来自内部数组s的值。您可能会注意到,测试将失败并为您提供一条消息,其中数据集的迭代(此处为 #3,因为 5+5 不是 6 ;))断言失败。
回答by Christian Steinmann
I had the same problem, and it was solved, when i deleted the empty constructor,that was auto generated. Iam not sure why this solves the problem. I also had no test method named like the class. The provider method doesnt need to be static, so far my test run without static. But also run when i make the provider method static
我有同样的问题,当我删除自动生成的空构造函数时,它解决了。我不知道为什么这解决了这个问题。我也没有像类一样命名的测试方法。provider 方法不需要是静态的,到目前为止我的测试运行没有静态。但也会在我将提供者方法设为静态时运行
回答by Karkotagan
<?php
require_once 'calculator.php';
/**
* Calculator test case.
*/
class CalculatorTest extends PHPUnit_Framework_TestCase {
/**
* @var Calculator
*/
private $Calculator;
/**
* Prepares the environment before running a test.
*/
protected function setUp() {
parent::setUp ();
// TODO Auto-generated CalculatorTest::setUp()
$this->Calculator = new Calculator(/* parameters */);
}
/**
* Cleans up the environment after running a test.
*/
protected function tearDown() {
// TODO Auto-generated CalculatorTest::tearDown()
$this->Calculator = null;
parent::tearDown ();
}
/**
* Constructs the test case.
*/
public function __construct() {
// TODO Auto-generated constructor
}
/**
* Tests Calculator->add()
*
* @dataProvider provider
*/
public function testAdd($a, $b, $c) {
// TODO Auto-generated CalculatorTest->testAdd()
//$this->markTestIncomplete ( "add test not implemented" );
//$this->Calculator->add(/* parameters */);
$this->assertEquals($this->Calculator->add($a, $b), $c);
}
public static function provider()
{
return array(
array(1, 1, 1),
array(1, 1, -1),
array(4, 2, 2),
array(1, 1, 1)
);
}
}
is the complete set of code
是完整的代码集
回答by Jonathon Hill
I have also found that you cannot directly chain data providers:
我还发现您不能直接链接数据提供者:
class ProviderTest extends PHPUnit_Framework_TestCase {
public function provider() {
return array(array('test'));
}
/**
* @dataProvider provider
*/
public function providerTest1($test) {
$this->assertTrue($test);
return array(array($test));
}
/**
* @dataProvider providerTest1
*/
public function providerTest2($test) {
$this->assertEquals('test', $test);
}
}
Apparently, PHPUnit calls all the provider functions before running any tests, so you can't even use separate provider functions to feed test result data to other tests. The best you can do is to simulate:
显然,PHPUnit 在运行任何测试之前调用所有提供程序函数,因此您甚至不能使用单独的提供程序函数将测试结果数据提供给其他测试。您可以做的最好的事情是模拟:
class ProviderTest extends PHPUnit_Framework_TestCase {
private $provider_data = array();
public function provider() {
return array(array('test'));
}
/**
* @dataProvider provider
*/
public function testProvider1($test) {
$this->assertFalse(empty($test));
array_push($this->provider_data, array($test));
}
/**
* @depends testProvider1
*/
public function testProvider2($test = NULL) {
if(is_null($test)) {
// simulate a provider
foreach($this->provider_data as $row) {
call_user_func_array(array($this, __METHOD__), $row);
}
} else {
$this->assertEquals('test', $test);
}
}
}
回答by Josh Woodcock
Behold I have achieved a pattern to achieve test dependencies for dataProviders! In this way you can chain dataProviders.
看哪,我已经实现了一种模式来实现 dataProviders 的测试依赖项!通过这种方式,您可以链接 dataProviders。
class ProviderDependencyTest extends PHPUnit_Framework_TestCase
{
private static $dataSet;
public function provideData()
{
self::$dataSet = array(
array(2,2,4),
array(1,0,2),
array(0,0,0)
);
//use static storage so you don't have to call the dataProvider again
return self::$dataSet;
}
public function testProvideAdd()
{
$data = self::$dataSet;
$this->assertEquals(3,count($data[0]));
return $data[0];
}
/**
* @depends testProvideAdd
*/
public function testAdd($data)
{
$sum = $data[0] + $data[1];
$this->assertEquals($data[2], $sum);
return array($sum,$data[0],$data[1]);
}
/**
* @depends testAdd
*/
public function testSubtract($data)
{
$difference = $data[0] - $data[1];
$this->assertEquals($data[2], $difference);
return array($difference,$data[0],$data[1]);
}
/**
* @depends testSubtract
*/
public function testMultiply($data)
{
$product = $data[0] * $data[2];
$this->assertEquals($data[1], $product);
return $product;
}
/**
* @depends testMultiply
*
* @dataProvider provideData
*/
public function testMath($a,$b,$c)
{
//don't redo the first set of tests
if(array($a,$b,$c) == self::$dataSet[0])
{
return;
}
$sum = $this->testAdd(array($a,$b,$c));
$difference= $this->testSubtract($sum);
$product = $this->testMultiply($difference);
$this->assertInternalType('integer', $product);
}
}
The 2nd data set fails 1 test to illustrate.
第二个数据集未能通过 1 次测试来说明。
回答by Macy Abbey
Remove the parameter from public function testAddStream($logger) and try again. I don't believe PHPUnit will invoke a test which requires parameters it is unable to pass.
从公共函数 testAddStream($logger) 中删除参数并重试。我不相信 PHPUnit 会调用需要它无法传递的参数的测试。