Проблема с PHPUnit и поставщиками данных
У меня есть следующий тестовый пример:
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);
}
}
Когда я запускаю его в PHPUnit, я получаю:
PHPUnit 3.4.14 by Sebastian Bergmann.
..........
Time: 0 seconds, Memory: 5.75Mb
OK (1 tests, 0 assertions)
Тест должен завершиться неудачно, но это не так. Я пробовал:
public function providerLogger() {
return array(new Logger);
}
Но я получаю:
The data provider specified for LoggerTest::testAddStream is invalid.
Я попробовал объявить его static
(как говорится в руководстве), но все равно никакой разницы.
Я помню, что раньше он работал аналогичным образом, но я мог ошибаться. Что мне не хватает?
Заранее благодарим за помощь.
PHPUnit 3.4.14 (взято из PEAR) на PHP 5.3.3
Ответы
Ответ 1
Незначительное обновление: использовать методы экземпляров в качестве поставщика с версии 3.2 (или где-то рядом). Взгляните на комментарии
Поставщик должен выглядеть так.
public static function providerLogger() {
return array(
array(new Logger)
);
}
Прежде всего: метод должен быть статическим
Массив s важен. Его не так сложно понять. Внешний массив имеет одно значение для каждой итерации, которую должен получить вызов. Здесь тест просто вызывается один раз. Внутренние массивы - это параметры (по порядку), с которыми вызывается тест. В вашем тесте ожидается только один параметр, поэтому для внутренних массивов всегда требуется ровно одно значение. Еще один маленький пример
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);
}
Здесь testAdd запускается 3 раза, по одному для каждого массива второго уровня, и он получает значения из внутреннего массива s. Вы можете заметить, что тест завершится с ошибкой и предоставит вам сообщение, в котором итерация набора данных (здесь # 3, потому что 5 + 5 не 6;)) утверждение не выполнено.
Ответ 2
У меня была та же проблема, и она была решена, когда я удалил пустой конструктор, который был сгенерирован автоматически. Я не уверен, почему это решает проблему. У меня также не было метода тестирования, называемого классом. Метод провайдера не обязательно должен быть статичным, пока мой тест не запускается без статичности. Но также запускайте, когда я делаю метод поставщика static
Ответ 3
<?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)
);
}
}
- это полный набор кода
Ответ 4
Я также обнаружил, что вы не можете напрямую связывать поставщиков данных:
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);
}
}
По-видимому, 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);
}
}
}
Ответ 5
Удалите параметр из публичной функции testAddStream ($ logger) и повторите попытку. Я не верю, что PHPUnit вызовет тест, который требует параметров, которые он не может передать.
Ответ 6
Вот, я достиг шаблона для получения тестовых зависимостей для 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);
}
}
Второй набор данных не позволяет выполнить 1 тест.