Follow up to #2105583: Add some sane strictness to phpunit tests to catch risky tests
Problem/Motivation
Checking for unintentionally covered code is useful for identifying weakness in coverage reports and making them more useful. However, checkForUnintentionallyCoveredCode's current behavior causes some problems because it doesn't recursively check parent classes for @uses information. This means any code run in our UnitTestCase::setUp() method will always be "unintentionally covered."
Proposed resolution
Obviously we don't want to work around this by adding the @uses to _every_ unit test we implement so we either need to
1) Remove that code from the setUp
2) Allow usage of phpunit's testcase and convert most tests to use it. add @uses to tests that do user Drupal's UnitTestCase.
3) Work upstream to support recursive @uses resolution.
I don't think 1 or 2 are likely so we'll probably need to work with phpunit to get this feature added.
Remaining tasks
| Comment | File | Size | Author |
|---|---|---|---|
| #19 | 2626832-19.patch | 1.05 KB | vijaycs85 |
| #19 | 2626832-diff-17-19.txt | 712 bytes | vijaycs85 |
Comments
Comment #2
neclimdulOpened https://github.com/sebastianbergmann/php-code-coverage/issues/408
Comment #3
mile231+2 is the correct answer.
::mad scientist:: I TRIED TO TELL THEM BUT THEY WOULDN'T LISTEN!!1!!
Anyway.
Option #4 is to kill
\Drupal. Which I would endorse. I'm pretty sure it's less practical than any of the other options, however.The example code on the github issue has a
@uses \Drupal(analogue) for the base class, whereasUnitTestCaseis not annotated that way.The problem in that case would be that it's impossible to get coverage for
\Drupalusing that test case. So the solution would be that all tests of\Drupalwould have to be from another base class.That's much more doable than converting *all* tests.
So:
@uses \DrupaltoUnitTestCase.\Drupalto subclass\PHPUnit_Framework_TestCase(or add another suitable subclass if it's needed).I'm pretty sure the
\Drupaltests don't need the container or what-have-you.Comment #4
mile23And a patch. :-)
Which, I now realize, is against 8.0.x, not 8.1.x, but hopefully it will apply.
Comment #7
mile23Comment #8
mile23Patch still applies to 8.3.x. Re-running tests.
Comment #9
mile23Thinking @neclimdul might have an opinion on this: #2824313: All unit tests should use UnitTestCase base class
Comment #12
lendudecheckForUnintentionallyCoveredCode has been deprecated in PHPUnit 5, see https://github.com/sebastianbergmann/phpunit/wiki/Release-Announcement-f...
so combined with #2795317: Allow PHPUnit 6+ support for object mocking, not sure what this means for the future of this issue, but thought I'd ask.
Comment #14
borisson_I think #12 means that we close this issue as won't fix.
Comment #15
borisson_Closing this issue based on #12.
Comment #16
e0ipsoDo we want to remove this line?
<!-- TODO set checkForUnintentionallyCoveredCode="true" once https://www.drupal.org/node/2626832 is resolved. -->Comment #17
vijaycs85Reached here from
core/phpunit.xml.dist. Let's remove it.Comment #18
tstoecklerWait, but shouldn't we add
beStrictAboutCoversAnnotationtophpunit.xml.distthen, instead?Comment #19
vijaycs85Did not know we have an alternative. @tstoeckler++
Comment #20
neclimdulMakes sense. Lets just do it.
Comment #21
mile23This yields results like this:
If you look at
PostgresqlConnectionTestyou see that it has@coversDefaultClassand@coversannotations. But it lacks@usefor code paths that aren't within that default class and its methods. Like this:This means that even though our test is annotated to cover
\Drupal\Core\Database\Driver\pgsql\Connection, our report says that it is not covered, because we setbeStrictAboutCoversAnnotation.In that report you'll also see that
\Drupal::unsetContainer()and file cache management are still a problem and that's what the code changes in #4 try to fix.Also, if you limit to
--group Database(for brevity's sake) you see this result:That means roughly half of the existing
@coversannotations are being ignored because of the wayUnitTestCaseworks, and because we don't have perfect isolation in the tests themselves.I won't set this to NW but I'll add the 'needs followup' tag because if we commit to this, it means we need a followup to modify at least
UnitTestCase(and maybe KTB) to@use \Drupaland so forth (or add the changes from #4), and also to explicitly mark functional tests as@coversNothing.I think that'd be a good change, but I'm not sure any actual maintainer wants to go down that path at this stage.
Comment #22
mile23BTW the issue in #2 is closed due to lack of feedback, but was referenced by another very similar issue: https://github.com/sebastianbergmann/php-code-coverage/issues/629
Comment #23
alexpottI dunno this one feels a weird one for me. This only has an effect if xdebug is on so no tests on DrupalCI are going to fail because of it. I think until we've got code coverage reports being generated somewhere this setting is not very useful for us. If you are running code coverage locally and you want to do this there is nothing to stop you setting this up in your local phpunit.xml as you see fit. I think out phpunit.xml.dist should contain how DrupalCI runs the tests and not anything else. If people want to do advance PHPUnit configuration they should be using PHPUnit docs and examples not ours.
Comment #24
borisson_I'm not sure if we want to have #19, even as a goal later down the line. I do think that #17 is something we should do, as it removes a reference to a setting that will no longer work.
Comment #27
teknorahFound related issue
Comment #30
catchMarked #2893232: Deprecated configuration setting "checkForUnintentionallyCoveredCode" used as duplicate.
Comment #33
mile23Given #23 let's call this issue postponed on #2974911: Allow run-tests.sh to generate coverage reports. We currently don't do a coverage report for core for the project CI, AFAICT.