Speeding up PHPUnit startup when code coverage is not required - phpunit

I am using PHPUnit in my Codeception unit tests. I am not interested in code coverage yet, so I would like to completely disable it, especially because it delays my tests by 8..12 seconds. This becomes annoying when tests are configured to be run automatically when files change.
I debugged PHPUnit code to see why it is starting up so long and found out that it spends up to 12 seconds inside getCodeCoverageFilter looping through getBlacklistedDirectories and collecting filenames calling addDirectoryToBlacklist.
Is there any way to disable processing getCodeCoverageFilterin Codeception or PHPUnit itself without directly hacking its code?
Here is my current phpunit.xml at the root of my Laravel 5 project:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="bootstrap/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false">
<testsuites>
<testsuite name="Application Test Suite">
<directory>./tests/</directory>
</testsuite>
</testsuites>
<filter>
<blacklist>
<directory>./vendor/</directory>
<directory>./database/</directory>
<directory>./public/</directory>
<directory>./resources/</directory>
<directory>./storage/</directory>
<directory>./tests/</directory>
</blacklist>
<whitelist>
<directory suffix=".php">app/</directory>
</whitelist>
</filter>
<php>
<env name="APP_ENV" value="testing"/>
<env name="CACHE_DRIVER" value="array"/>
<env name="SESSION_DRIVER" value="array"/>
<env name="QUEUE_DRIVER" value="sync"/>
</php>
</phpunit>

Just remove the line
<log type="coverage-html" target="coverage"/>
from your phpunit.xml
In fact, I use two xml files.
One standard phpunit.xml that is used on a remote code inspection service, and one that I specifically named phpunit_no_code_coverage.xml without code coverage, that I use locally while developing.
You can specify which xml file to use via phpunit's c flag, e.g:
./phpunit -c tests/phpunit_no_code_coverage.xml --testsuite suite_name
The result is rather huge, my testsuite runs now rather fast, on average taking ~15 seconds, whereas it before took 110 seconds.

According to codeception documentation, the code coverage is enabled in codeception.yml. Try:
coverage:
enabled: false
Or removing the key.

Related

CakePHP 2 Code Coverage now says "No files to generate coverage for"

My unit tests on CakePHP still run, but the code coverage has disappeared. All I get is "No files to generate coverage for".
Our application is currently running on CakePHP 2.10.15. I have PHPUnit 5.7 installed. Running PHP 7. I use the web runner for tests & coverage. I have XDebug 2.7.0beta1 running.
Did one of our recent upgrades break some sort of connection between Cake and PHPUnit?
Create a file phpunit.xml in your app folder:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/5.7/phpunit.xsd">
<logging>
<log type="coverage-text" target="tmp.txt" showOnlySummary="true"/>
</logging>
<testsuite name="default">
<directory suffix="Test.php">tests</directory>
</testsuite>
<filter>
<whitelist processUncoveredFilesFromWhitelist="false">
<!-- directories that you want in code coverage -->
<directory suffix=".php">app/</directory>
</whitelist>
</filter>
</phpunit>
For me just adding this file like this worked just fine. For more information about this xml: https://phpunit.de/manual/5.7/en/appendixes.configuration.html
Be aware to include only the files and directories you need, otherwise it will became very slow.

Why is PhpStorm running tests for only some tests with extra arguments (bootstrap, configuration)?

I am using PhpStorm and for some PHPUnit tests I can right click in the file menu on the left hand side and run some tests and it works.
In the console it shows
/usr/bin/php -dxdebug.coverage_enable=1 /srv/live/vendor/phpunit/phpunit/phpunit --coverage-clover /home/me/.PhpStorm2017.3/system/coverage/live$StringTest.coverage --bootstrap /srv/live/vendor/autoload.php --configuration /srv/live/phpunit.xml tests\src\CoreBundle\Helper\StringTest /srv/live/src/tests/src/CoreBundle/Helper/StringTest.php --teamcity
However, for other tests in another bundle when I right click and run it, the command is
/usr/bin/php /srv/live/src/tests/src/OtherBundle/Classes/Validator/StringLengthTest.php
and the test can't run. I get a class not found error, which I attribute to the command not having the extra arguments as that in the first version above. The other thing I noticed was that the 'Run test with coverage' was only available for the first test, when right clicking in the menu.
Where does this difference originate?
My phpunit.xml file is
<?xml version="1.0"?>
<phpunit cacheTokens="true"
colors="true"
stopOnError="false"
stopOnFailure="false"
stopOnIncomplete="false"
stopOnSkipped="false"
verbose="true"
bootstrap="/srv/live/vendor/autoload.php">
<php>
<server name="KERNEL_DIR" value="app/" />
</php>
<testsuites>
<testsuite name="Project Test Suite">
<directory>/srv/live/src/tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="false">
<directory suffix=".php">/srv/live/src/</directory>
</whitelist>
</filter>
<logging>
<log type="coverage-html" target="./web/phpunitLog/codeCoverage" charset="UTF-8"
yui="true" highlight="true"
lowUpperBound="50" highLowerBound="80"/>
<log type="testdox-html" target="./web/phpunitLog/testdox.html" />
</logging>
</phpunit>
In File -> Settings -> Languages & Frameworks -> PHP -> Test Frameworks it is
Do you have any ideas on why I can run one test ok but not the other - I mean why the difference in the arguments (e.g. -dxdebug.coverage_enable=1)?
The php.ini file hasn't changed.
I found a solution (not sure if it's the best).
If I click Run -> Edit Configurations
Then click the plus sign and add a new PHPUnit configuration, I can choose the bundle where the tests were not working.
Now phpunit runs with the extra arguments when I right click in the file menu.
The thing is, I never did this for the test that was working, so although I found a way to get the failing test to work, I am not totally clear on why I saw the difference in the first place.
Thanks HunterFrazier for putting the wheels in motion.

Phpunit tries to test all Symfony console commands

I'm working on a Symfony project. As I need to do unit testing, I downloaded and installed Phpunit 6.2.4 from its website.
However, when I tried to update my database, I got this output
php bin/console doctrine:schema:update --dump-sql
PHPUnit 6.2.4 by Sebastian Bergmann and contributors.
unrecognized option --dump-sql
bin/console doctrine:schema:update
Cannot open file "doctrine:schema:update.php".
I tried other console commands, but the result is the same. Basically, my guess was that somehow Phpunit tries to test every single file, so I edited the phpunit.xml file like this, using a previous one that worked in other project.
<?xml version="1.0" encoding="UTF-8"?>
<!-- http://phpunit.de/manual/4.1/en/appendixes.configuration.html -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
backupGlobals="false"
colors="true"
bootstrap="app/autoload.php"
>
<php>
<ini name="error_reporting" value="-1" />
<server name="KERNEL_DIR" value="app/" />
</php>
<testsuites>
<testsuite name="Project Test Suite">
<directory suffix=".php">tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">src</directory>
<exclude>
<directory>src/*Bundle/Resources</directory>
<directory>src/*/*Bundle/Resources</directory>
<directory>src/*/Bundle/*Bundle/Resources</directory>
</exclude>
</whitelist>
<blacklist>
<directory>bin</directory>
<directory>docker</directory>
</blacklist>
</filter>
</phpunit>
As far as I know, blacklisting both bin and docker directories should result in phpunit not running anything inside them, but it still doesn't work.
Then I checked my composer.json for the symfony/phpunit-bridge, removed it and tried again, but the problem continues.
Has anyone ever faced this?
Blacklisting appear to remove directories from the code-coverage generation whitelist - but if src/ does not contain those sub-directories, and so it is redundant - and also a great deal slower adding and discarding huge numbers of files. On one project, I tried to blacklist vendor/, it was taking a minute to even show the initial command banner, before starting to run the tests.
Remove the <blacklist/> section, and the rest should be fine - if you don't mention bin/ or docker/ then PHPunit won't need to read the files, it so won't run them either.

Phpunit starts all the tests or not starts all the tests, ignoring the config

My project contains 2 packages, and I want to run tests in only one of them. Used symfony 3.3 and phpunit 6.3.0
phpunit.xml.dist
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/6.3/phpunit.xsd"
backupGlobals="false"
colors="true"
bootstrap="./src/CoreBundle/Tests/autoloadWithIsolatedDatabase.php"
>
<php>
<ini name="error_reporting" value="-1" />
<server name="KERNEL_CLASS" value="AppKernel" />
</php>
<testsuites>
<testsuite name="App">
<directory>src/AppBundle/Tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>src</directory>
<exclude>
<directory>src/*Bundle/Resources</directory>
<directory>src/*Bundle/Tests</directory>
<directory>src/*/*Bundle/Resources</directory>
<directory>src/*/*Bundle/Tests</directory>
<directory>src/*/Bundle/*Bundle/Resources</directory>
<directory>src/*/Bundle/*Bundle/Tests</directory>
</exclude>
</whitelist>
</filter>
</phpunit>
And structure of the project
This configuration will run all the tests from AppBundle and CoreBundle (in the second there are no tests), and if you change
<directory>src/AppBundle/Tests</directory>
to
<directory>src/CoreBundle/Tests</directory>
then there will be no tests at all. I can not understand what's wrong
Let's start of by how your phpunit.xml.dist is configured. You have one test suite defined:
<testsuites>
<testsuite name="App">
<directory>src/AppBundle/Tests</directory>
</testsuite>
</testsuites>
This is the place phpunit will look into for tests. They have to conform to the usual conventions like having a file name ending in Test and each test method must be prefixed with a test.
Also from your screenshot I can gather that you have a top level tests/ folder (right next to app/, src/, etc.). This is probably where your other tests are placed in.
The second folder is where you should also place your tests from the AppBundle if you follow the best practices: https://symfony.com/doc/current/best_practices/tests.html
I think this was established sometime during the 3.x release cycle.
In theory you should be able to copy src/AppBundle/Tests to tests/AppBundle and hopefully everything still works. Now you can update your test suite configuration to:
<testsuites>
<testsuite name="App">
<directory>tests/</directory>
</testsuite>
</testsuites>
Your filter can stay in place as src/CoreBundle/Tests does not actually contain test-classes, only helpers used for tests.
Now that you have all tests in one big tests folder separated by bundle you might want to do a search on this folder for classes extending PHPUnit_Framework_TestCase. Since PHPUnit 6.0 introduced namespaces those need to be updated with PHPUnit\Framework\TestCase otherwise PHPUnit will ignore those tests.

How to exclude unused libraries from code coverage report?

There's something I apparently don't understand about PHPUnit's code coverage whitelisting.
I have the following filter for a couple of folders:
<filter>
<whitelist addUncoveredFilesFromWhitelist="true">
<directory suffix=".php">./app</directory>
</whitelist>
<whitelist addUncoveredFilesFromWhitelist="false">
<directory suffix=".php">./lib</directory>
</whitelist>
</filter>
"app" - I want to know about anything not covered in here so I've enabled addUncoveredFilesFromWhitelist for the core application. (this works as expected)
"lib" - I want to see what was covered in files used from here but there will be a lot that isn't used, so I've disabled addUncoveredFilesFromWhitelist for the library files. (this I have a problem with)
What happens is that library files not included at runtime show up in the reports as unexecuted code. I can verify the code is not included during test by adding lines that would throw fatal errors.
This result seems contradictory to what the PHPUnit docs say, but no doubt I'm doing it wrong. Can anyone explain how I can include my executed library code, but only that which was required during test?
You can use the filter node in the phpunit.xml. I have used the following file in a project. It whitelist's local files:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
syntaxCheck="false"
bootstrap="tests/bootstrap.php"
>
<php>
<includePath>lib/php</includePath>
</php>
<filter>
<whitelist>
<directory suffix=".php">lib/php/</directory>
</whitelist>
</filter>
<testsuites>
<testsuite name="Jm_Log">
<directory suffix="Test.php">tests</directory>
</testsuite>
</testsuites>
<logging>
<log type="coverage-html" target="build/coverage" title="jam"
charset="UTF-8" yui="true" highlight="true"
lowUpperBound="35" highLowerBound="70"/>
<log type="coverage-clover" target="build/logs/clover.xml"/>
<log type="junit" target="build/logs/junit.xml" logIncompleteSkipped="false"/>
</logging>
</phpunit>
Note: You can also use a blacklist.

Resources