PHPUnit code coverage for abstract class at 0% even though it's clearly tested

I just posted a StackOverflow question about testing.

In short - the test for an abstract class goes through its code, but doesn’t mark the code as covered. Can you help get to the bottom of the problem and tell me what I’m doing wrong?

Full question with source code and details here.

For the lazy, here is the body of the question. If you can drop a hint, do so here or there, doesn’t matter (but you get more valuable upvotes there) :smile:


Writing a PHP package here, TDD with PhpUnit 4+.

Writing tests for all my regular classes works fine, and they’re covered in the report. But when I test the mock of an abstract class, even though the test clearly runs through the method (it fails if I fail to implement it, or if I put some breakpoints in there), the code coverage is 0%.

I’ve extracted the offending code into a repo here, if you’d like to give it a whirl. All you need to do is clone, composer install, and run phpunit, it’s all configured.

This is being run on a Vagrant box, so an isolated environment that has nothing in particular to do with my PHP version or available extensions, and was tested by other people, too, on their installations, producing the same results.

The abstract class being tested is here, while its test can be seen here.

Any hints on what I may be doing wrong here would be greatly appreciated.


See answer on Stackoverflow. Have fun! :wink:

Was that you? Thanks! Now to figure out why :smile:

Yes :smile:

yet another example of case-sensitivity in autoloaders causing problems. There’s zero benefit in a making an autloader case sensitive and several drawbacks, it’s a rather awful trend that needs to be reversed.

I’d rather say this is another case of PHP inconsistency.

Identifier have to uniquely identify “things” whatever those things are. There is absolutely no reason, and I mean none whatsoever, to let some identifiers be case sensitive and others not. I think Java and many other languages got it right: identifiers must be case sensitive. Otherwise you end up creating multiple identifiers every time you name something: an identifier foo is not unique since there are 2^3=8 possible spellings of it. What’s the point? It’s just a source of bugs.

While I agree with that, the identifier of arbitrary piece of code (in this case a class) should not be coupled to something as far removed from code as the filesystem. The fact that a class is in a “file” really is well outside the scope of OOP or constructs within the language. By coupling your code to the filesystem by having an autoloader that works differently to the the way PHP works internally is asking for trouble (This is a perfect example). It causes all kinds of action-at-a-distance and bugs that are hard to track down.

The fact that PHP does allow lowercase class names should be respected by the autoloader until such a time as php no longer does. Consider this code

new MyClass;
new myclass;

This will work perfectly

new myclass;
new MyClass;

does not, is backwards and causes all kinds of weird and unpredictable bugs… especially in larger systems where the autoloader is correctly triggered in a method that is then refactored out, breaking something in some other part of the system which was working perfectly until the method that was successfully triggering the autoloader was removed.

Case-sensitive autoloaders introduce subtle bugs, whereas there is zero disadvantage in making an autoloader case-insensitive.

1 Like

The problem is that neither PHP nor the autoloader do have anything to do with this problem here. The project’s configuration explicitly states that it uses PSR-4 standard. PSR-4 is nothing more than a set of coding style rules. Composer autoloader just enforces this contract, nothing more nothing less. If you don’t like to use it you can define your own coding conventions as every team does or should do.

From IRC by dstockto:

I believe the issue is because when phpunit is collecting the code coverage information, it’s in PHP arrays. The keys are case sensitive and so even though you have covered that, the coverage was for a differently cased file which PHPunit doesn’t match up to the files that were loaded

This is an interesting explanation that makes sense.

PhpUnit does not collect code coverage information, XDebug does.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.