Почему провайдеры данных PhpUnit снижают показатели покрытия?

Я использую PhpUnit с хорошими результатами, тестируя мой код только с утверждениями. Недавно я решил попробовать PhpUnit с анализом отчетов о покрытии, но заметил, что тесты, использующие методы dataProvider, имеют тенденцию уменьшать мои оценки покрытия кода. Интересно, что я могу делать неправильно или это является следствием методов тестирования dataProvider? Я использую PhpUnit 6 с Php 7.

Я включил исходный класс, Foo, с тремя тестовыми классами ниже, которые тестируют его. FooTest использует обычные методы тестирования, без dataProviders. BarTest использует методы dataProvider с аннотациями @codeCoverageIgnore, а BazTest использует методы dataProvider без аннотаций.

Вы можете увидеть, как ниже оценка покрытия кода с BazTest.

Терминальный скриншот вызова phpunit.

Скриншот отчета о покрытии кода со всеми тестовыми классами.

Снимок экрана отчета о покрытии кода с подробностями BazTest.

foo.php

namespace phpunittestproject\src;/**
* Foo
*
* This is a simple class to be used as a source file
* in unit test experiments. It gets and sets a name
* string and date object.
*
*/
class Foo
{/**
* Name
*
* String characters other than numeric.
*
* @var string
*/
private $name = null;

/**
* Date
*
* Date no older than 2000.
*
* @var \DateTime
*/
private $date = null;/**
* Constructor
*
* Sets instance vars.
*
*/
public function __construct()
{

$this->name = '';
$this->date = new \DateTime('now');

}/**
* Get Date
*
* @return DateTime
*/
public function getDate()
{
return $this->date;
}

/**
* Get Name
*
* @return string
*/
public function getName()
{
return $this->name;
}

/**
* Set Date
*
* This method accepts a DateTime object that corresponds
* to a date no earlier than 2000.
*
* @param \DateTime $value Date after 2000.
* @return boolean Result of operation.
*/
public function setDate(\DateTime $value)
{
if($value < new \DateTime('2000-01-01 00:00:00')){
return false;
} else {
$this->date = $value;
return true;
}
}

/**
* Set Name
*
* This method accepts a string that does not contain numeric
* characters.
*
* @param string $value String without numeric characters.
* @return boolean Result of operation.
*/
public function setName(string $value)
{
if(preg_match('/\\d/', $value)){
return false;
} else {
$this->name = $value;
return true;
}
}

}

FooTest.php:

declare(strict_types = 1);

namespace phpunittestproject\test;

use \phpunittestproject\src\Foo;

/**
*
* Foo Test
*
* This test class does not use dataProvider methods. All
* test assertions are being done in test metods.
*
*/
class FooTest extends \PHPUnit\Framework\TestCase
{/**
*
*
*/
public function testGetDate()
{
$foo = new Foo();

// Good date:
$date = new \DateTime('2011-01-01 11:11:11');
$foo->setDate($date);
$this->assertEquals($date, $foo->getDate());

// Bad date:
$date = new \DateTime('1990-01-01 11:11:11');
$foo->setDate($date);
$this->assertNotEquals($date, $foo->getDate());

}

/**
*
*
*/
public function testGetName()
{
$foo = new Foo();

// Good name:
$foo->setName('A Good Name');
$this->assertEquals('A Good Name', $foo->getName());

// Bad name:
$foo->setName('Bad Name 666');
$this->assertNotEquals('Bad Name 666', $foo->getName());

}

/**
* Test setDate()
*
* This test method tests the date property when it is
* set with good and bad data using method setDate().
*
*/
public function testSetDate()
{
$foo = new Foo();

// Good date:
$date = new \DateTime('2011-01-01 11:11:11');
$foo->setDate($date);
$this->assertAttributeEquals($date, 'date', $foo);

// Bad date:
$date = new \DateTime('1990-01-01 11:11:11');
$foo->setDate($date);
$this->assertAttributeNotEquals($date, 'date', $foo);

}

/**
*
* Test setName()
*
* This test method tests the name property when it is
* set with good and bad data using method setName().
*
*
*/
public function testSetName()
{
$foo = new Foo();

// Good name:
$foo->setName('Good Name');
$this->assertAttributeEquals('Good Name', 'name', $foo);

// Bad name:
$foo->setName('Bad Name 666');
$this->assertAttributeNotEquals('', 'name', $foo);

}

}

BarTest.php:

declare(strict_types = 1);

namespace phpunittestproject\test;

use \phpunittestproject\src\Foo;

/**
*
* Bar Test
*
* This test class utilizes dataProvider methods to feed
* test methods. The dataProvider methods are annotated
* with codeCoverageIgnore.
*
*/
class BarTest extends \PHPUnit\Framework\TestCase
{/**
*
* @codeCoverageIgnore
*/
public function providerTestSetDateWithInvalidData()
{
return array(
array(new \DateTime('1990-01-01 11:11:11')),
);
}

/**
*
* @codeCoverageIgnore
*/
public function providerTestSetDateWithValidData()
{
return array(
array(new \DateTime('2011-01-01 11:11:11')),
);
}

/**
*
* @codeCoverageIgnore
*/
public function providerTestSetNameWithInvalidData()
{
return array(
array('Bad Name 666'),
);
}

/**
*
* @codeCoverageIgnore
*/
public function providerTestSetNameWithValidData()
{
return array(
array('Good Name'),
);
}

/**
*
*
*/
public function testGetDate()
{
$foo = new Foo();
$date = new \DateTime('2001-01-01 11:11:11');
$foo->setDate($date);
$this->assertEquals($date, $foo->getDate());
}

/**
*
*
*/
public function testGetName()
{
$foo = new Foo();
$foo->setName('A Good Name');
$this->assertEquals('A Good Name', $foo->getName());
}

/**
*
* @dataProvider providerTestSetDateWithInvalidData
*
*
*/
public function testSetDateWithInvalidData($value)
{
$foo = new Foo();
$foo->setDate($value);
$this->assertAttributeNotEquals($value, 'date', $foo);
}

/**
*
* @dataProvider providerTestSetDateWithValidData
*
*
*/
public function testSetDateWithValidData($value)
{
$foo = new Foo();
$foo->setDate($value);
$this->assertAttributeEquals($value, 'date', $foo);
}

/**
*
* @dataProvider providerTestSetNameWithInvalidData
*
*
*/
public function testSetNameWithInvalidData($value)
{
$foo = new Foo();
$foo->setName($value);
$this->assertAttributeNotEquals($value, 'name', $foo);
}

/**
*
* @dataProvider providerTestSetNameWithValidData
*
*
*/
public function testSetNameWithValidData($value)
{
$foo = new Foo();
$foo->setName($value);
$this->assertAttributeEquals($value, 'name', $foo);
}

}

BazTest.php:

declare(strict_types = 1);

namespace phpunittestproject\test;

use \phpunittestproject\src\Foo;/**
*
* Baz Test
*
* This test class utilizes dataProvider methods to feed
* test methods. The dataProvider methods are not annotated
* with codeCoverageIgnore.
*
*/
class BazTest extends \PHPUnit\Framework\TestCase
{/**
*
*
*/
public function providerTestSetDateWithInvalidData()
{
return array(
array(new \DateTime('1990-01-01 11:11:11')),
);
}

/**
*
*
*/
public function providerTestSetDateWithValidData()
{
return array(
array(new \DateTime('2011-01-01 11:11:11')),
);
}

/**
*
*
*/
public function providerTestSetNameWithInvalidData()
{
return array(
array('Bad Name 666'),
);
}

/**
*
*
*/
public function providerTestSetNameWithValidData()
{
return array(
array('Good Name'),
);
}

/**
*
*
*/
public function testGetDate()
{
$foo = new Foo();
$date = new \DateTime('2001-01-01 11:11:11');
$foo->setDate($date);
$this->assertEquals($date, $foo->getDate());
}

/**
*
*
*/
public function testGetName()
{
$foo = new Foo();
$foo->setName('A Good Name');
$this->assertEquals('A Good Name', $foo->getName());
}

/**
*
* @dataProvider providerTestSetDateWithInvalidData
*
*
*/
public function testSetDateWithInvalidData($value)
{
$foo = new Foo();
$foo->setDate($value);
$this->assertAttributeNotEquals($value, 'date', $foo);
}

/**
*
* @dataProvider providerTestSetDateWithValidData
*
*
*/
public function testSetDateWithValidData($value)
{
$foo = new Foo();
$foo->setDate($value);
$this->assertAttributeEquals($value, 'date', $foo);
}

/**
*
* @dataProvider providerTestSetNameWithInvalidData
*
*
*/
public function testSetNameWithInvalidData($value)
{
$foo = new Foo();
$foo->setName($value);
$this->assertAttributeNotEquals($value, 'name', $foo);
}

/**
*
* @dataProvider providerTestSetNameWithValidData
*
*
*/
public function testSetNameWithValidData($value)
{
$foo = new Foo();
$foo->setName($value);
$this->assertAttributeEquals($value, 'name', $foo);
}

}

phpunit.xml:

<?xml version="1.0" encoding="UTF-8"?>
<phpunit colors="true" bootstrap="./vendor/autoload.php">
<testsuites>
<testsuite name="DataProviderTestSuite">
<file>phpunittestproject/test/FooTest.php</file>
<file>phpunittestproject/test/BarTest.php</file>
<file>phpunittestproject/test/BazTest.php</file>
</testsuite>
</testsuites>
<filter>
<whitelist>
<file>phpunittestproject/test/FooTest.php</file>
<file>phpunittestproject/test/BarTest.php</file>
<file>phpunittestproject/test/BazTest.php</file>
</whitelist>
</filter>
</phpunit>

1

Решение

Спасибо @Christopher за решение! Неправильно настроенный файл phpunit.xml заставлял PhpUnit тестировать тесты. Редактирование элементов белого списка фиксировало низкий показатель покрытия кода. Методы dataProvider не нужно аннотировать с помощью @codeCoverageIgnore!

<?xml version="1.0" encoding="UTF-8"?>
<phpunit colors="true" bootstrap="./vendor/autoload.php">
<testsuites>
<testsuite name="DataProviderTestSuite">
<!-- Test files go here: -->
<file>phpunittestproject/test/FooTest.php</file>
<file>phpunittestproject/test/BarTest.php</file>
<file>phpunittestproject/test/BazTest.php</file>
</testsuite>
</testsuites>
<filter>
<whitelist>
<!-- Source files to be tested go here: -->
<file>phpunittestproject/src/Foo.php</file>
</whitelist>
</filter>
</phpunit>

Код покрытия HTML-отчет со 100% баллом.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]