I'm trying a basic UnitTest with Codeception. No frameworks are used.
My working root is as:
tests |
|-unit
|-Test.php
includes|
|-general
|-Custom.php
In Custom.php
<?php
namespace Custom;
class General {
public static function check(){}
}
My test case is:
<?php
use Custom\General;
use PHPUnit\Framework\TestCase;
final class Test extends TestCase
{
public function testPushAndPop(): void
{
General::check();
}
}
I also have in my composer.json:
"autoload": {
"psr-4":{
"Custom\\":"includes/general"
}
},
When I run
php vendor/bin/codecept run unit
...
1) Test: Push and pop
Test tests/unit/Test.php:testPushAndPop
[Error] Class 'DB\General' not found
#1 /var/www/html/prj/tests/unit/Test.php:9
Codeception Simple Unit Test Not Work To Find My Namespaces
This is less about Codeception but how PHP autoloading works in general and what the configuration of autoloading in Composer is in specific:
{
"autoload": {
"psr-4":{
"Custom\\":"includes/general"
}
}
}
Even the path-segment includes/general does map on the file-system path includes/general/ (composer should have told you to add / at the end of the path-segment), the error message
[Error] Class 'DB\General' not found
#1 /var/www/html/prj/tests/unit/Test.php:9
shows that the namespace of Custom\\ in the Composer configuration is different to the namespace of the class that is not found (which is DB\\).
So even the framework you have in use (you have one and that is the testing framework) may load the composer auto-loader (highly likely), its just that the class is not found.
As #Naktibalda already highlighted in a comment, it is just a plain autoloader configuration issue.
You are right, but why? The IDE does not claim any error... (your reaction)
These are two pair of shoes.
Your IDE most likely does not rely on the autoloader and just guesses the file from the file-system.
Depending how well maintained and configured your IDE is, it perhaps should and could have highlighted you that.
On the other hand, PHP can only rely on the autoloader, in your case you delegate the autoloading to composer(1), not to your IDE.
So maybe improve on that end as well, composer is more central for your projects development than the IDE can be.
So a suggestion:
Whenever changing the composer.json file, I suggest to run composer validate --strict to check your status, then follow with a composer update.
Run this automatically before running your tests. You may not want to run composer update, then run composer install before running the test-runner if you have it as a development dependency.
Example to bind this for a single test run command within your composer.json:
{
"scripts": {
"test": [
"#composer --no-plugins --version",
"#composer validate --strict",
"#composer --no-plugins -q install --no-scripts --no-progress",
"codecept run unit"
]
}
}
you then have a single call to run all the important things in your Composer based project:
$ composer test
...
Running unit-tests is a good way to verify the autoload configuration by the way. With the composer test-script you ensure it is always up-to-date when running the test-suite, too.
You don't need an IDE for this technically, which makes it more portable and stable giving you the peace of mind for your composer based project to grow.
I am trying to get the results of a php unit tests folder , but not using the CLI, and instead using a php file.
I would like to get the answer ( OK, 4 tests passed ) in a variable or something so I can decide whether the script should execute or not, what's the best way to do this? i don't want to use batch files, I want to force the execution of the tests, inside the library itself.
I started with
require_once 'PHPUnit/Autoload.php';
When I included the tests, don't know how to start them thought.
Any advice?
You can check PHPUnits exit code, 0 means no test failed.
To run the tests from a php file, then to check the exit code, try something like this:
//Composer installs phpunit to /vendor/bin/phpunit
exec('/vendor/bin/phpunit', $result, $exitCode);
if ($exitCode == 0) {
// continue exiting the script
} else {
// there was a test failure, more info will be in $result
}
If you're looking for an enterprise quality solution, look into a Continuous Integration product like Jenkins or Bamboo.
I am aware that code is optimized when built in release mode and should always be deployed to production as such, but I wanted to know if there was a way to find out if your code has been deployed with a debug build vs. a release build.
Would a PowerShell cmdlet be a potential route for this type of query?
Try a function like this:
function Test-DebugAssembly($path) {
$assembly = [Reflection.Assembly]::LoadFile("$path")
$attr = $assembly.GetCustomAttributes([Diagnostics.DebuggableAttribute], $false)
if (!$attr) {
$false
}
else {
$attr.IsJITTrackingEnabled
}
}
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?
Sorry for another 'phpunit doesn't work' question. It used to work for years now. Today I reinstalled PEAR and phpunit for reasons not connected to this problem. Now when I run phpunit as I usually did. Nothing happens. The cli just shows me a new line, no output whatsoever.
Has anyone encountered this problem or has an idea what could have caused it.
PHPUnit Version: 3.5.15
PEAR Version: 1.9.4
PHP Version: 5.3.8
Windows 7
I'm on OSX and MAMP. To get error messages I had to adjust the following entries in php.ini:
display_errors = On
display_startup_errors = On
Please not that this has to go into /Applications/MAMP/bin/php/php5.3.6/conf/php.ini .
For future reference, for those who are facing any problem with PHPUnit, and PHPUnit is failing silently, just add this three lines inside phpunit.xml:
<phpunit ....... >
...
...
<php>
<ini name="display_errors" value="true"/>
</php>
</phpunit>
After that run the tests again, and now you can see why PHPUnit is failing,
AND ... ENJOY UNIT TESTING :)
I know the orignal poster's question is already answered, but just for any people searching in the future: one thing that can cause PHPUnit to fail silently (i.e. it just stops running tests without telling you why) is that it has an error handler that it set up before each test run, which is intended to capture errors and display them at the end of the test run. The problem is that certain errors halt execution of the whole test run.
What I generally do when this happens, as a first step, is reset the error handler to something that will immediately output the error message. In my base test class I have a method called setVerboseErrorHandler, which I'll call at the top of the test (or in setUp) when this happens. The below requires php 5.3 or higher (due to the closure), so if you're on 5.2 or lower you can make it a regular function.
protected function setVerboseErrorHandler()
{
$handler = function($errorNumber, $errorString, $errorFile, $errorLine) {
echo "
ERROR INFO
Message: $errorString
File: $errorFile
Line: $errorLine
";
};
set_error_handler($handler);
}
Create the simplest test class you can without a bootstrap.php or phpunit.xml to first verify that your new installation works. PHPUnit will stop without any message if it cannot instantiate all of the test cases--one for each test method and data provider--before running any tests.
You have already figured out how to get it to work, but my solution was a little different.
First thing you can do is check the exit status. If it's not 0, then PHP exited and because of the INI configuration settings set, none of the PHP error messages were outputted. What I did was to enable the "display_errors" INI setting, and set "error_reporting" to E_ALL. I was then able to identify errors such as PHP not being able to parse a certain script. Once I fixed that, PHPUnit ran properly.
I managed to spectacularly paint myself in a corner with a custom "fatal error handler" that in certain rare conditions turned out to output nothing. Those conditions, in accordance with Murphy's Law, materialized once I had forgotten the handler was in place.
Since it wasn't really a "PHPunit problem", none of the other answers helped [although #David's problem was at the bottom the same thing], even though the symptoms were the same - phpunit terminating with no output, no errors, no log and no clue.
In the end I had to resort to a step-by-step tracing of the whole test suite by adding this in the bootstrap code:
register_shutdown_function(function() {
foreach ($GLOBALS['lastStack'] as $i => $frame) {
print "{$i}. {$frame['file']} +{$frame['line']} in function {$frame['function']}\n";
}
});
register_tick_function(function() {
$GLOBALS['lastStack'] = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 8);
});
declare(ticks=1);
If anyone ever manages to do worse than this, and somehow block stdout as well, this modification should work:
register_shutdown_function(function() {
$fp = fopen("/tmp/path-to-debugfile.txt", "w");
foreach ($GLOBALS['lastStack'] as $i => $frame) {
fwrite($fp, "{$i}. {$frame['file']} +{$frame['line']} in function {$frame['function']}\n");
}
fclose($fp);
});
an old thread this one, but one I stumbled across when having the same problem.
I had the same problem, nothing being returned to console including print, print_r, echo etc.
solved it by using --stderr as a test-runner option.
Check that you haven't written any logic into your code that just dies, with no output. For example,
<?php
if (!array_key_exists('SERVER_NAME', $_SERVER)) {
die();
}
This was exactly my case; I'd made some assumptions about the environment which were correct when running the code via Apache, but weren't fulfilled when running from CLI and the code did not echo any output.
PHPUnit tried to include the bootstrap file before giving the usual init output, but died during the bootstrapping proccess, hence exiting with status 0 and no output.
If when you run from command line a recent version of phpunit like this
> php phpunit
or
> ./phpunit
or
> php ./phpunit.phar
or
> ./phpunit.phar
And you immediatly return to the prompt with no messages, this is probably due to a "suhosin secutiry" setup.
phpunit is now a "phar" package including all libraries. To be able to run such file when php has the suhosin security module enabled, you must first set this
suhosin.executor.include.whitelist = phar
into you php.ini file (for example, with debian/ubuntu, you may have to edit file /etc/php5/conf.d/suhosin.ini
i tried everything here, but nothing worked until i tried phpunit --no-configuration simpletest.php. that finally gave me some output, which implies that my phpunit.xml.dist file is broken. (i'll come back and update this once i debug it.)
the contents of simpletest.php are below, but any test file should work.
<?php
use PHPUnit\Framework\TestCase;
final class FooTest extends TestCase
{
public function testFoo()
{
$this->assertEquals('x', 'y');
}
}
Check if the phpunit you're running and the one you installed are the same:
$ pear list phpunit/phpunit
...
script /path/to/phpunit
...
Try to execute exactly that phpunit with the full path.
Then check your PATH variable and see if the correct directory is in it. If not, fix that.
If that does not help, use write something into the phpunit executable, e.g. "echo 123;" and run phpunit. Check if you see that.
For me the conflict was with Xdebug's directive
xdebug.remote_enable=1
If you are using composer, check to make sure your included PHP files are not ending the code executions. The same goes for when you included certain PHP files explicitly.
In my case, I was working on a WordPress plugin and one of the PHP files I included directly in composer.json (which I don't want to load through PSR-4 because WordPress's coding standards don't support it yet) had this code on top;
if (!defined('ABSPATH')) {
exit(); // exit if accessed directly
}
And since ABSPATH will not be defined when I run the tests directly, the code was exiting.
This is because, since I told Composer to always load these files each time, this part of the code will execute, while the other files included though autoload PSR will load on demand.
So check to make sure any of the files you included are not stopping the code execution. If it happens, then even when you run phpunit --info the code will still exit and you won't see any output.
I was facing a seems problem. I could run phpunit from root directory but not from anywhere else. so I put the "--configuration" tag, and point it to my xml configuration.
$ ./<path_to_phpunit>phpunit --configuration <path_to_phpunitxml>/phpunit.xml
The path to phpunit is optinal, I used it because I installed locally by composer.
In /composer/vendor/phpunit/phpunit/src/TextUI/Command.php in main() function in catch (Throwable $t) {} block var_dump (echo / print_r) exception. If an exception exists, you, probably, will solve the current problem.