FilterIterator should be instance of PHPUnit\Framework\TestSuiteIterator - phpunit

When I activate Xdebug and run a PHPUnit unittest this error occurs: ❌
Warning: assert(): assert($iterator instanceof FilterIterator) failed in [...]/vendor/phpunit/phpunit/src/Runner/Filter/Factory.php on line 57
[... some stack trace information ...]
Return value of PHPUnit\Runner\Filter\Factory::factory() must be an instance of FilterIterator, instance of PHPUnit\Framework\TestSuiteIterator returned
I'm using
PHPUnit 9.5.6 by Sebastian Bergmann and contributors.
Runtime: PHP 7.4.21 with Xdebug 2.8.0
The PHPUnit execution call (clued together with PhpStorm) looks like:
/usr/bin/php74.bin.cli
-dzend_extension=/usr/local/php74/lib/php/extensions/xdebug.so
-dxdebug.collect_params=5
-dxdebug.profiler_enable=on
-dxdebug.auto_trace=1 -dxdebug.trace_format=1
-dxdebug.collect_return=1 -ddisplay_errors=1
-ddisplay_startup_errors=1 -derror_reporting=E_ALL
-dmemory_limit=512M
[...]/vendor/phpunit/phpunit/phpunit
--coverage-filter [...]/src/
--bootstrap [...]/utils/unittest/bootstrap.php
--configuration [...]/utils/unittest/phpunit.xml
--filter "/(BasicsTest::testReturnBytes)( .*)?$/"
--test-suffix BasicsTest.php [...]/utils/unittest/basics --teamcity
Calling a simple php script with Xdebug activated works well. ✔️
/usr/bin/php74.bin.cli
-dzend_extension=/usr/local/php74/lib/php/extensions/xdebug.so
-dxdebug.collect_params=5
-dxdebug.profiler_enable=on -dxdebug.auto_trace=1
-dxdebug.trace_format=1 -dxdebug.collect_return=1
-ddisplay_errors=1 -ddisplay_startup_errors=1
-derror_reporting=E_ALL -dmemory_limit=512M ./test.php
Calling the unittests without Xdebug activated works well. ✔️
/usr/bin/php74.bin.cli
-dallow_url_fopen=1
[...]/vendor/phpunit/phpunit/phpunit
--no-coverage
--bootstrap [...]/utils/unittest/bootstrap.php
--configuration [...]/utils/unittest/phpunit.xml
--filter "/(BasicsTest::testReturnBytes)( .*)?$/"
--test-suffix BasicsTest.php [...]/utils/unittest/basics --teamcity
My phpunit.xml
<?xml version="1.0"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.5/phpunit.xsd"
bootstrap="bootstrap.php"
colors="true"
verbose="true">
<coverage>
<include>
<directory suffix=".php">../../../src/*</directory>
<directory suffix=".php">../../../some other dirs/*</directory>
</include>
<exclude>
<directory suffix=".php">../../../some other dirs/*</directory>
</exclude>
<report>
<html outputDirectory="./x_testresults" lowUpperBound="35" highLowerBound="70"/>
</report>
</coverage>
<php>
<ini name="allow_url_fopen" value="On"/>
<ini name="memory_limit" value="5G"/>
<ini name="include_path" value="."/>
</php>
</phpunit>
The unittest
<?php
declare(strict_types = 1);
class BasicsTest extends PHPUnit\Framework\TestCase
{
function testReturnBytes(): void {
$this->assertSame(1, 1);
}
}
The docs say in https://phpunit.readthedocs.io/en/9.5/code-coverage-analysis.html#including-files that
It is mandatory to configure a filter for telling PHPUnit which source code files to include in the code coverage report. This can either be done using the --coverage-filter command line option or via the configuration file (see The Element).
This is what I did, see above. Also without setting a --coverage-filter parameter PHPUnit complains about missing filter information, so I added it.
For me it feels like the issue is related to the --coverage-filter parameter. The error message (see first code paragraph) says FilterIterator should be instance of PHPUnit\Framework\TestSuiteIterator but I don't know where to adjust this.

I found some mistakes in my setup and I found a kind of workaround to get the tests to be running with Xdebug.
The mistakes:
the includes and excludes tags in the phpunit.xml had wrong relative paths
the settings "-dxdebug.auto_trace=1" for xdebug on the command line command were outdated, see docs. Actually its strange that the test.php did run well.
The workaround:
set a testsuite to "." in the phpunit.xml and call it via --testsuite default
set a "#group dummy" to the specific class I want to test and call it via --group dummy to just call that test.
The testsuite setting in phpunit.xml in detail:
<testsuites>
<testsuite name="default">
<directory>./</directory>
</testsuite>
</testsuites>
The commandline call now:
/usr/bin/php74.bin.cli
-dzend_extension=/usr/local/php74/lib/php/extensions/xdebug.so
-dxdebug.collect_params=5
-dxdebug.profiler_enable=on
-dxdebug.trace_format=1
-dxdebug.collect_return=1
../../vendor/bin/phpunit
--group no-db
--verbose
--debug
--testsuite default
--group dummy

Related

Is it possible to debug API requests on localhost while testing using PHPUnit and PhpStorm?

I have configuration that tests my localhost API succesfully in PhpStorm using PHPUnit. Also I can stop on breakpoints but only inside my TestCase classes.
I need to stop on breakpoints that are set inside logic that are tested, but it does not stop there.
Testing command:
/usr/bin/php -dxdebug.remote_enable=1 -dxdebug.remote_mode=req -dxdebug.remote_port=9000 -dxdebug.remote_host=127.0.0.1 /foo/vendors/composer/phpunit/phpunit/phpunit --configuration /foo/_stuff/phpunit/config-api2.xml --teamcity
My config xml:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
bootstrap="../../foo/tests/app_test_case.php"
colors="true"
stopOnFailure="false"
>
<testsuites>
<testsuite name="foo">
<file>../../foo.php</file>
</testsuite>
Added to php.ini:
xdebug.remote_autostart = 1
Added to requested route:
?XDEBUG_SESSION_START=PHPSTORM
And added cookie in index.php:
header('Cookie: XDEBUG_SESSION=PHPSTORM');
Yes, you can.
The question here is how you are going to start a debug session for those API calls.
The most usual way would be adding xdebug.remote_autostart=1 to php.ini for the interpreter running the calls, so that a debug session would start for every single PHP call, API or not.
If you are not happy with it, you can add the XDEBUG_SESSION_START GET-parameter to HTTP requests of the calls, but that would obviously require code modification.

Symfony2 - Execution order of test cases

I'm using Symfony Functional Tests in NETBEANS. Is it possible to define the order in which order will the test cases be executed?
For example: I have "UserTestCase" case for testing registration of users, changing their profiles etc, and "ForumTestCase" for testing creation of forum posts etc. I want to run UserTestCase before ForumTestCase. Now the order is according to file names (F.. before U..)
You need to define order of tests in your phpunit.xml as described in docs
example:
<phpunit>
<testsuites>
<testsuite name="Object_Freezer">
<file>Tests/Freezer/HashGenerator/NonRecursiveSHA1Test.php</file>
<file>Tests/Freezer/IdGenerator/UUIDTest.php</file>
<file>Tests/Freezer/UtilTest.php</file>
<file>Tests/FreezerTest.php</file>
<file>Tests/Freezer/StorageTest.php</file>
<file>Tests/Freezer/Storage/CouchDB/WithLazyLoadTest.php</file>
<file>Tests/Freezer/Storage/CouchDB/WithoutLazyLoadTest.php</file>
</testsuite>
</testsuites>
</phpunit>
I'm using Netbeans for the development and I was wondering for a long time, why this didn't work for me.
Then I found out, that Netbeans simply ignores folder definitions and the order of execution defined in phpunit.xml
See here: https://netbeans.org/bugzilla/show_bug.cgi?id=199072

symfony 2.1 phpunit Swift_Message class not found

I've an issue with symfony and phpunit. Our peoject is growing bigger and bigger. So we decided to activate process isolation for phpunit because the server couldn't stand the amount of tests anymore (Not enough RAM). Since then all test which send mails aren't working anymore. Could someone please help us? The test below works perfectly fine if processIsolation="false" but it fails if processIsolation="true"
Versions:
symfony 2.1.8-dev
phpunit 3.7.9
ERROR Message
Project\AppBundle\Tests\MailTest::testSendMail
PHPUnit_Framework_Exception: PHP Fatal error: Class 'Swift_Message' not found in /var/www/project/src/Project/AppBundle/Tests/MailTest.php
Test
public function testSendMail()
{
$client = static::createClient();
$message = \Swift_Message::newInstance();
$message->setFrom('example#example.com')
->setTo('example#example.com')
->setSubject('Subject')
->setBody('Hello World')
->setContentType('text/html');
$client->getContainer()->get('mailer')->send($message);
$this->assertTrue(true);
}
phpunit.xml
<phpunit
backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
bootstrap="./autoload.php"
processIsolation="true"
stopOnFailure="false"
syntaxCheck="false" >
<testsuites>
<testsuite name="Project Test Suite">
<directory>../src/Project/AppBundle/Tests/MailTest.php</directory>
</testsuite>
</testsuites>
</phpunit>
This error is caused because Switfmailer defines a constant
SWIFT_REQUIRED_LOADED after it installs it's autoloader. The
autoloader checks this constant, and if it's already defined, refuses
to install the autoloader. In process isolation, PHPUnit ensures that
all defined constants are re-defined in the processs that gets spawned
to run the test. Unfortunately, this means that SWIFT_REQUIRED_LOADED
is defined in the test process, so the autoloader doesn't load (see
"swift_required.php" in the swiftmailer source directory). Note that
if you turn off include global state for the test via annotations your
tests still won't work, because the bootstrap file is passed to the
test process via the __PHPUNIT_BOOTSTRAP global variable (see
TestCaseMethod.tpl in the PHPUnit directory). Without the globals,
this global is undefined in the test process and the bootstrap file is
not included breaking the tests.
The only work around that I found that works was to replace the line
$constants = PHPUnit_Util_GlobalState::getConstantsAsString();
with
$constants = '';
in the run method of TestCase.php in the PHPUnit source distribution. If your code
relies on global constants to be defined before your test cases run
this fix obviously won't work for you (class constants are a
different story); unless said constants will be redefined safely in the
course of running your test cases.
This is caused by a problem related to the swiftmailer autoloader.
I encountered the same problem and fixed it in a forked repository of swiftmailer.
Here you can find the PR for the fix: https://github.com/swiftmailer/swiftmailer/pull/416.
If you do not wish to wait until this is merged you can use my repository by adding this to your composer.json.
"require": {
"swiftmailer/swiftmailer": "dev-master as 5.0.x-dev"
},
"repositories": [
{
"type": "vcs",
"url": "https://github.com/NickStemerdink/swiftmailer.git"
}
]
UPDATE: The PR has been merged in the meanwhile, so you can just update to the latest swiftmailer version.
Does it work if you first instantiate $message and call static::createClient afterwards?

PHPUnit TestListener does not work in PhpStorm

I'm using Symfony 2, PHPUnit 3.7.10 and PhpStorm 5.0.4.
I have a class MyTestListener (implements PHPUnit_Framework_TestListener) in the namespace Acme\DemoBundle\Tests.
When I call phpunit from CLI with vendor/bin/phpunit.bat -c app/
The listener work, the test is successful.
I found this: PHPUnit, PHPUnit_Framework_TestListener, Netbeans and the PHPUnit xml config but it seems to be another problem.
But when I start the test in PhpStorm the, the listener does not load, some objects should be injected into an abstract test class, which are null in this case. I also notices, that when I debug with a breakpoint in the MyTestListener class the debugger doesn't stop in this class, others breakpoints work fine.
the phpunit.xml entry:
<listeners>
<listener class="Acme\DemoBundle\Tests\MyTestListener" file="../src/Acme/DemoBundle/Tests/MyTestListener.php">
</listener>
</listeners>
I also try to add a empty element, it doesn't help.
In my Run/Debug Configuration of PhpStorm I specify phpunit.xml and the bootstrap file.
I also add this option for the Command Line/Interpreter: -d auto_prepend_file=vendor/autoload.php
The listener configuration in phpunit.xml seems to be parsed, but not work. When I change the class name to an invalid file/class, I get an error, that the file can't open the stream. I also try to use a absolute file path or change the slashes into backslashes, nothing works.
What a shame... I found my own error
I do all tests from CLI, but in PhpStorm only one test class, so the suite name was different and in my listener class I do the stuff only if the suite name match:
if ($suite->getName() == "db-tests") {...}
So the solution was to extends the expression to
$name = $suite->getName();
if ($name == "db-tests" ||
strpos($name, 'Acme\DemoBundle\Tests\Database') !== false) {...}

PHPUnit reports a PHPUnit_Framework_Exception

I added a simple test to a bundle.
As suggested in the manual I tried to have PHPUnit load the configuration with:
phpunit -c /app
phpunit.xml looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<!-- http://www.phpunit.de/manual/current/en/appendixes.configuration.html -->
<phpunit
backupGlobals = "false"
backupStaticAttributes = "false"
colors = "true"
convertErrorsToExceptions = "true"
convertNoticesToExceptions = "true"
convertWarningsToExceptions = "true"
processIsolation = "false"
stopOnFailure = "false"
syntaxCheck = "false"
bootstrap = "bootstrap.php.cache" >
<testsuites>
<testsuite name="Project Test Suite">
<directory>../src/*Bundle/Tests</directory>
</testsuite>
</testsuites>
</phpunit>
The error message I get is:
root#h0x03:/var/www/fi/FrontendIntegrator# phpunit -c app/
PHP Fatal error: Uncaught exception 'PHPUnit_Framework_Exception' with message 'Neither "Project Test Suite.php" nor "Project Test Suite.php" could be opened.' in /usr/share/php/PHPUnit/Util/Skeleton/Test.php:102
Stack trace:
#0 /usr/share/php/PHPUnit/TextUI/Command.php(157): PHPUnit_Util_Skeleton_Test->__construct('Project Test Su...', '')
#1 /usr/share/php/PHPUnit/TextUI/Command.php(129): PHPUnit_TextUI_Command->run(Array, true)
#2 /usr/bin/phpunit(49): PHPUnit_TextUI_Command::main()
#3 {main}
thrown in /usr/share/php/PHPUnit/Util/Skeleton/Test.php on line 102
PHPUnit apparently loads the file and tries to find a PHP-file named after the test suites name. I cannot find any information on why it does so or how such a file should look like.
It seems like PHPUnit tries to find a file named after the name-attribute of the testsuite-tag
if it either cannot find any tests (wrong naming or wrong directory) or
if there is a fatal error occuring in a test-script; which occures so early that PHPUnit cannot identify the content of that file as a test - as no class could be loaded up until that point.
I had the same problem today testing my controllers. Turns out just following the Book's command for it doesn't work, since PHPUnit can't find the test classes. I managed to find a workaround, just specify the test file you'd like tested, and it'll work.
phpunit -c app src/Acme/DemoBundle/Tests/Utility/CalculatorTest.php
It happened to me that I had one extra directory level in my bundles. Instead of MyVendorName\MyBundleNameBundle I had MyVendorName\MyProject\MyBundleNameBundle
The default directories within phpunit.xml.dist, in the section testsuites are those:
<testsuites>
<testsuite name="Project Test Suite">
<directory>../src/*/*Bundle/Tests</directory>
<directory>../src/*/Bundle/*Bundle/Tests</directory>
</testsuite>
</testsuites>
but none did match my bundle namespace: Xmontero\Emperors\AdminBundle whose tests, in turn, were in the directory src/Xmontero/Emperors/AdminBundle/Tests.
In addition ALL my bundles had that syntax and I removed any bundle with the other syntax (like Acme\DemoBundle). As a result, phpunit did not find any test.
I solved like this: just below this line in phpunit.xml.dist
<directory>../src/*/*Bundle/Tests</directory>
I added this line
<directory>../src/*/*/*Bundle/Tests</directory>
so it reads:
<testsuites>
<testsuite name="Project Test Suite">
<directory>../src/*/*Bundle/Tests</directory>
<directory>../src/*/*/*Bundle/Tests</directory>
<directory>../src/*/Bundle/*Bundle/Tests</directory>
</testsuite>
</testsuites>
...and everything worked fine ;)
-- EDIT 1 day later --
It gives me now report on coverage about the test itself, when running phpunit -c app --coverage-html myNiceDir - when I expect it to give me only the coverage of the system under test.
This is because there is a whitelist that follows the same pattern, and there is something to be added in the exclude list:
Where it read this:
<exclude>
<directory>../src/*/*Bundle/Resources</directory>
<directory>../src/*/*Bundle/Tests</directory>
<directory>../src/*/Bundle/*Bundle/Resources</directory>
<directory>../src/*/Bundle/*Bundle/Tests</directory>
</exclude>
I changed into this:
<exclude>
<directory>../src/*/*Bundle/Resources</directory>
<directory>../src/*/*/*Bundle/Resources</directory>
<directory>../src/*/*Bundle/Tests</directory>
<directory>../src/*/*/*Bundle/Tests</directory>
<directory>../src/*/Bundle/*Bundle/Resources</directory>
<directory>../src/*/Bundle/*Bundle/Tests</directory>
</exclude>
I hope now it's correct ;)
I had the same exact error, and I solved by just upgrading my phpunit version, I had 3.6.10 and now I have 4.0.17 and it works perfectly and as expected.
The Synfony book is not completely wrong, it just states the wrong phpunit version as the needed one.

Resources