function DrupalStandardsListenerTrait::checkValidCoversForTest
Same name and namespace in other branches
- 8.9.x core/tests/Drupal/Tests/Listeners/DrupalStandardsListenerTrait.php \Drupal\Tests\Listeners\DrupalStandardsListenerTrait::checkValidCoversForTest()
Check an individual test run for valid @covers annotation.
This method is called from $this::endTest().
Parameters
\PHPUnit\Framework\TestCase $test: The test to examine.
1 call to DrupalStandardsListenerTrait::checkValidCoversForTest()
- DrupalStandardsListenerTrait::doEndTest in core/
tests/ Drupal/ Tests/ Listeners/ DrupalStandardsListenerTrait.php - Reacts to the end of a test.
File
-
core/
tests/ Drupal/ Tests/ Listeners/ DrupalStandardsListenerTrait.php, line 58
Class
- DrupalStandardsListenerTrait
- Listens for PHPUnit tests and fails those with invalid coverage annotations.
Namespace
Drupal\Tests\ListenersCode
private function checkValidCoversForTest(TestCase $test) {
// If we're generating a coverage report already, don't do anything here.
if ($test->getTestResultObject() && $test->getTestResultObject()
->getCollectCodeCoverageInformation()) {
return;
}
// Gather our annotations.
$annotations = Test::parseTestMethodAnnotations(static::class, $test->getName());
// Glean the @coversDefaultClass annotation.
$default_class = '';
$valid_default_class = FALSE;
if (isset($annotations['class']['coversDefaultClass'])) {
if (count($annotations['class']['coversDefaultClass']) > 1) {
$this->fail($test, '@coversDefaultClass has too many values');
}
// Grab the first one.
$default_class = reset($annotations['class']['coversDefaultClass']);
// Check whether the default class exists.
$valid_default_class = $this->classExists($default_class);
if (!$valid_default_class && interface_exists($default_class)) {
$this->fail($test, "@coversDefaultClass refers to an interface '{$default_class}' and those can not be tested.");
}
elseif (!$valid_default_class) {
$this->fail($test, "@coversDefaultClass does not exist '{$default_class}'");
}
}
// Glean @covers annotation.
if (isset($annotations['method']['covers'])) {
// Drupal allows multiple @covers per test method, so we have to check
// them all.
foreach ($annotations['method']['covers'] as $covers) {
// Ensure the annotation isn't empty.
if (trim($covers) === '') {
$this->fail($test, '@covers should not be empty');
// If @covers is empty, we can't proceed.
return;
}
// Ensure we don't have ().
if (strpos($covers, '()') !== FALSE) {
$this->fail($test, "@covers invalid syntax: Do not use '()'");
}
// Glean the class and method from @covers.
$class = $covers;
$method = '';
if (strpos($covers, '::') !== FALSE) {
[
$class,
$method,
] = explode('::', $covers);
}
// Check for the existence of the class if it's specified by @covers.
if (!empty($class)) {
// If the class doesn't exist we have either a bad classname or
// are missing the :: for a method. Either way we can't proceed.
if (!$this->classExists($class)) {
if (empty($method)) {
$this->fail($test, "@covers invalid syntax: Needs '::' or class does not exist in {$covers}");
return;
}
elseif (interface_exists($class)) {
$this->fail($test, "@covers refers to an interface '{$class}' and those can not be tested.");
}
else {
$this->fail($test, '@covers class does not exist ' . $class);
return;
}
}
}
else {
// The class isn't specified and we have the ::, so therefore this
// test either covers a function, or relies on a default class.
if (empty($default_class)) {
// If there's no default class, then we need to check if the global
// function exists. Since this listener should always be listening
// for endTest(), the function should have already been loaded from
// its .module or .inc file.
if (!function_exists($method)) {
$this->fail($test, '@covers global method does not exist ' . $method);
}
}
else {
// We have a default class and this annotation doesn't act like a
// global function, so we should use the default class if it's
// valid.
if ($valid_default_class) {
$class = $default_class;
}
}
}
// Finally, after all that, let's see if the method exists.
if (!empty($class) && !empty($method)) {
$ref_class = new \ReflectionClass($class);
if (!$ref_class->hasMethod($method)) {
$this->fail($test, '@covers method does not exist ' . $class . '::' . $method);
}
}
}
}
}
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.