Using #covers for a class - php

I am using php for testing my code. Here is an example:
/**
* #covers Calculator::
*/
class CalculatorTest extends PHPUnit_Framework_TestCase {
protected function setUp() { /* ... */ }
/**
* #covers Calculator::add
*/
public function testAddTwoIntegers() { /* ... */ }
/**
* #covers Calculator::multiply
*/
public function testMultiplyTwoIntegers() { /* ... */ }
}
However, my code is complicated and I want to get rid of #covers over individual test methods. How does php treat the following class when generating coverage reports:
/**
* #covers Calculator
*/
class CalculatorTest extends PHPUnit_Framework_TestCase {
protected function setUp() { /* ... */ }
public function testAddTwoIntegers() { /* ... */ }
public function testMultiplyTwoIntegers() { /* ... */ }
}
Notice that the #covers annotation over a class is still there but I have removed it from every method.
I am able to get coverage reports using this approach too but I have not seen an example of it anywhere, so I want to know if this is not a correct use.
Code Coverage Report:
2016-01-18 08:57:50
Summary:
Classes: 17.67% (56/317)
Methods: 0.33% (5/1520)
Lines: 0.60% (109/18094)
Class1:
Methods: 66.67% ( 2/ 3) Lines: 95.45% ( 21/ 22)
Class2:
Methods: 50.00% ( 3/ 6) Lines: 96.70% ( 88/ 91)

Indeed, setting the classname without the method name is the recommended #covers syntax.
Documentation here:
https://phpunit.readthedocs.io/en/8.5/annotations.html#covers
Annotation
#covers ClassName::methodName (not recommended)
#covers ClassName (recommended)
#covers ClassName<extended> (not recommended)
#covers ClassName::<public> (not recommended)
#covers ClassName::<protected> (not recommended)
#covers ClassName::<private> (not recommended)
#covers ClassName::<!public> (not recommended)
#covers ClassName::<!protected> (not recommended)
#covers ClassName::<!private> (not recommended)
#covers ::functionName (recommended)
When you ask:
How does php treat the following class when generating coverage reports
The answer is: Every line of the class mentioned in #covers executed during "any" of the tests in that TestCase will compute a +1 in the execution.
If you do real TDD and start first by writing the test, then writing the class, this is a perfect approach. Some of your lines in your public methods with branches will count 2 or more executions, and probably the lines inside each of the branches will count 1 execution.
Private methods will also count +n executions, while you won't write named tests for those methods, they will be called as a result of being helpers to the public methods.
When you say:
but I have not seen an example of it anywhere
I can tell that 90% of our tests use a #covers MyNiceClass annotation without specifying any method.
If you start by the test first, you normally won't mess up things. If you "need" that "MyNiceClass" is able to get something, you start by doing testGetSomething() in the test and set a basic expectation, then you write the public function getSomething() in the class and you end up having a one-to-one test for each method in 80% of the cases. The rest of the cases normally are multiple tests for the same method like for example testGetSomething() (happy path) and testGetSomethingThrowsExceptionWithInvalidParameter() (sad path).
In short
Yes, what you propose is correct, normal, usual and it is the recommended way to go according to the documentation.

Another reason (which was the reason in my case) is not using the complete class-name including the namespace.
// Should be like
#covers \App\Module\MyClass::doSomething

Why not simply run the test case and see the coverage with your changes? You risk getting down-voted as you are asking a question without trying anything.
From the PHPUnit manual:
The #covers annotation (see Table B.1) can be used in the test code to specify
which method(s) a test method wants to test. If provided, only the code
coverage information for the specified method(s) will be considered. Example
11.2 shows an example.
Table B1 Referenced above

Related

Unit-Test code coverage not determined correctly

When using the #covers-annotation, it's not been taken into account when displaying the code coverage.
No matter if I just "cover" the class, or the method, or both.
Test:
/**
* #covers \App\Controller\UserEditController
*/
class UserEditWebTest extends WebTestCase
{
/**
* #covers ::edit
*/
public function testEdit():void
{
//...
$this->assertSomething();
}
}
And the tested Controller:
namespace App\Controller;
class UserEditController
{
public function edit() {
//..
}
protected function someOtherFn():void
{
//..
}
}
Now UnitTest says on code-coverate output:
$ utest --coverage-text
Classes: 23.41% (125/534)
Methods: 32.75% (1091/3331)
Lines: 31.58% (4799/15198)
App\Controller\Admin\User\UserEditController
Methods: 0.00% ( 0/ 2) Lines: 44.78% ( 30/ 67)
Q: What am I doing wrong?
Why is Methods on 0/2 ?
I also tried removing the #covers-Annotation from the test-method docblock, or adding the full namespace of the controller before the ::edit - nothing works.
I cleared the cache of the test-environment
Solution
I found out, that using the #covers-annotation is not required at all, actually. If everything is configured correctly, the tested classes, methods and lines should automatically being registered correctly.
In PhpStorm, you can run a "coverage test" which is an xdebug run that shows all code covered.
The annotation was not been taken into account, so I had to actually change my test so that more of the code is truly being tested - e.g. adding tests for each possible case inside a method.

Calculate code coverage on phpunit test classes

We are using phpunit to unit-test our classes like this
namespace VendorName/SystemName {
final class TestableClass { /** ... */ }
}
namespace VendorName/SystemName/Tests {
/**
* #group unit
* #covers /VendorName/SystemName/TestableClass
*/
final class TestableClassTest extends TestCase { /** ... */ }
}
When we run these test the TestableClass get covered correctly, but we also want to see, whether every line of code in TestableClassTest was actually exectued, as we deal with dead code sometimes like
/**
* #expectedException /InvalidArgumentException
*/
public function testSomeMethodThrowsException(): void
{
// do some arrangement
// call the tested method
$testable->someMethod();
// do some post-call assertions
self::assertBar($baz);
self::assertFoo($baz);
// lines above are actually dead code
// if test goes right and throws exception
}
So we wan't to grab coverage statistics for our tests also.
The straightforward way is to add #covers /VendorName/SystemName/Tests/TestableClassTest to each test class, but this requires a lot of manual work.
Is there a correct way to automatically get test cases coverage (maybe listener or config or other phpunit hacks)

Execute tests declared in a trait before tests declared in test case using that trait

I have a Symfony WebTestCase-extending PHP Test class and a DRY-trait. The test functions in my class #depend on the test functions in my trait, however I can't manage to execute the trait tests before the class tests. Is that possible?
trait TestTrait
{
/**
* #beforeClass
*/
public function testBeforeAnythingElseHappens()
{
/*...*/
}
/* more functions */
}
Test Class
class Test extends WebTestCase
{
use TestTrait;
/**
* #depends testBeforeAnythingElseHappens
*/
function testClassSpecificStuff()
{
/* ... */
}
}
First, see PHPUnit Manual - Appendix B. Annotations:
#beforeClass
The #beforeClass annotation can be used to specify static methods that should be called before any test methods in a test class are run to set up shared fixtures.
So, you should not use #beforeClass here - it is intended to allow setting up fixtures. In addition, the methods annotated as such should be static.
Second, see PHPUnit Manual - Appendix B. Annotations:
#depends
PHPUnit supports the declaration of explicit dependencies between test methods. Such dependencies do not define the order in which the test methods are to be executed but they allow the returning of an instance of the test fixture by a producer and passing it to the dependent consumers.
So yes, you could use the #depends annotation to declare dependencies between tests. Just remove the #beforeClass annotation:
trait TestTrait
{
public function testBeforeAnythingElseHappens()
{
}
}
class Test extends WebTestCase
{
use TestTrait;
/**
* #depends testBeforeAnythingElseHappens
*/
public function testClassSpecificStuff()
{
}
}
Third, a few words of advice (from my own experience):
Do not require tests to be run in a certain order.
If you arrange something in one test and need the same thing in another, just do it multiple times, do not worry too much about repeating yourself.
For reference, see:
http://blog.ploeh.dk/2011/05/24/DesignSmellTemporalCoupling/
What does “DAMP not DRY” mean when talking about unit tests?

PHPUnit Placeholder for empty tests

I like to have empty functions on occasion for placeholders (primarily empty constructors, since it helps avoid accidental duplication of constructors since my team knows there must always be one somewhere).
I also like to have at least one test for every method of a class (largely because it is a nice easy rule to hold my team against).
My question is simple: what should we put in these empty test methods to prevent the "no tests" warning.
We could just do $this->assertTrue(true), which I know will work just fine. However, I was wondering if there was anything a touch more official and proper (preferably something which makes it so the method isn't counted in the number of tests run, artificially inflating it a bit).
Thanks.
try this :
/**
* #covers Controllers\AdminController::authenticate
* #todo Implement testAuthenticate().
*/
public function testAuthenticate()
{
// Remove the following lines when you implement this test.
$this->markTestIncomplete(
'This test has not been implemented yet.'
);
}
You try a reflection class on the function and ensure that the method is there. Then the test could simply be that the method exists (empty or not), which will pass without a warning.
class MethodExistsTest extends \PHPUnit_Framework_TestCase
{
protected $FOO;
protected function setUp()
{
$this->FOO = new \FOO();
}
/**
* #covers \FOO::Bar
*/
public function testEmptyMethodBarExists()
{
$ReflectionObject = new \ReflectionObject($this->FOO);
$this->assertTrue($ReflectionObject->getMethod('Bar'));
}
/**
* #covers \FOO::__construct
*/
public function testConstructorExists()
{
$ReflectionObject = new \ReflectionObject($this->FOO);
$this->assertNotNull($ReflectionObject->getConstructor());
}
}

phpunit - #covers tag not working

Maybe I missed out on a detail, but I wrote a small test case for a singleton _clone method yet it is not showing up as tested in the code coverage report.
/**
* #covers ErrorHandling::__clone
*/
public function test__cloneNotCloneable(){
$class = new ReflectionClass('ErrorHandling');
$method = $class->getMethod('__clone');
self::assertTrue($method->isFinal(), '__clone method is not final.');
self::assertTrue($method->isPrivate(), '__clone method is not private.');
}
The __clone method is the usual private/final __clone() of a regular (evil) singleton.
/**
* Define __clone as final and private to dissallow cloning.
*/
private final function __clone(){}
I know it's probably overkill testing for this, but the code-coverage report is sort of the graphical representation of a job 'well done'. Is there a way to have this method marked as covered in the code coverage report?
The #covers tag tells PHPUnit that you intend to test the named method; it does not mark the method as having been tested. Since you cannot call the method, Xdebug won't tell PHPUnit that its code has been executed, and it will never be covered in your report.
Your best bet is to tell PHPUnit to ignore the method in the report by using the #codeCoverageIgnore docblock tag.
/**
* Define __clone as final and private to dissallow cloning.
*
* #codeCoverageIgnore
*/
private final function __clone() { }
You can ignore any range of lines by enclosing them in a pair of one-line start/stop comments.
// #codeCoverageIgnoreStart
private final function __clone() { }
// #codeCoverageIgnoreEnd
Finally, you can ignore a single line by adding a one-line comment to it.
private final function __clone() { } // #codeCoverageIgnore

Categories