Reputation: 13200
When running a PHPUnit test, I would like to be able to dump output so I can debug one or two things.
I have tried the following (similar to the PHPUnit Manual example);
class theTest extends PHPUnit_Framework_TestCase
{
/**
* @outputBuffering disabled
*/
public function testOutput() {
print_r("Hello World");
print "Ping";
echo "Pong";
$out = "Foo";
var_dump($out);
}
}
With the following result:
PHPUnit @package_version@ by Sebastian Bergmann.
.
Time: 0 seconds, Memory: 3.00Mb
OK (1 test, 0 assertions)
Notice there is none of the expected output.
I'm using the HEAD versions of the git repos as of September 19th, 2011.
Output of php -version
:
$ php -version
PHP 5.2.9 (cli) (built: Dec 8 2010 11:36:37)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2009 Zend Technologies
with Xdebug v2.1.0, Copyright (c) 2002-2010, by Derick Rethans
Is there anything I'm doing wrong, or is this potentially a PHPUnit bug?
Upvotes: 233
Views: 207608
Reputation: 1479
ob_flush()
after outputting textExample code:
public function testDebugOutputToCli() {
var_dump(new DateTime());
ob_flush();
}
Screenshot of code and output:
I was struggling with all the answers above, especially because the selected answer –using codecept_debug()
with --debug
as the manual says– caused a huge wave of debug output that made it impossible to use for me.
I was reading the PHPUnit manual like a good nerd and stumbled onto this, which I think explains what causes this whole issue across all of PHPUnit, not just Codeception:
PHPUnit manual, Testing Output: “Sometimes you want to assert that the execution of a method, for instance, generates an expected output (via echo or print, for example). The PHPUnit\Framework\TestCase class uses PHP’s Output Buffering feature to provide the functionality that is necessary for this.”
This makes total sense and explains why we don't see the output. PHPUnit is saving it up in case we want to examine the comments! This is how it should always work in our actual tests, we of course don't want random stuff getting to the screen just because we called a function that uses echo
.
But when we're debugging, we just want to see the text right away, and understanding all this, the solution is clear: Just use ob_flush()
to print the contents of the output buffer on demand!
Three cheers for reading the fun manuals!
P.S. Also found this tip hidden in How to show var_dumps in phpunit or codeception by Julian on dev.to
Upvotes: 22
Reputation: 9
it's a paid product, but I find it does the job well: Ray from Spatie https://spatie.be/products/ray
just use it like this:
ray('message')
and the message will show up in Ray output window
Upvotes: 0
Reputation: 982
It is possible to use Symfony\Component\Console\Output\TrimmedBufferOutput
and then test the buffered output string like this:
use Symfony\Component\Console\Output\TrimmedBufferOutput;
//...
public function testSomething()
{
$output = new TrimmedBufferOutput(999);
$output->writeln('Do something in your code with the output class...');
//test the output:
$this->assertStringContainsString('expected string...', $output->fetch());
}
Upvotes: 1
Reputation: 67
You can use PHPunit default way of showing messages to debug your variables inside your test like this:
$this->assertTrue(false,$your_variable);
Upvotes: -1
Reputation: 11185
In short, phpunit supresses STDOUT. It writes to STDERR by default, unless you add --verbose
or --debug
. You can do one of those things:
var_dump
your debug as usual but add --verbose
to the phpunit command linevar_dump
your debug as usual but add a line ob_flush();
beneath itObviously, the last thing is the Good Thing to do, and the rest are quick temporary hacks.
Upvotes: 1
Reputation: 1275
If you use Laravel, then you can use logging functions such as info() to log to the Laravel log file under storage/logs. So it won't appear in your terminal but in the log file.
Upvotes: -1
Reputation: 1217
PHPUnit is hiding the output with ob_start()
. We can disable it temporarily.
public function log($something = null)
{
ob_end_clean();
var_dump($something);
ob_start();
}
Upvotes: 6
Reputation: 3297
Just use the --verbose flag when execute phpunit.
$ phpunit --verbose -c phpunit.xml
The advantage of this method is that you don't need to change the test code, you can print strings, var_dump's o anything you wish always and it will be shown in the console only when verbose mode is set.
I hope this helps.
Upvotes: 7
Reputation: 31
Hackish, but works: Throw an exception with the debug output as its message.
class theTest extends PHPUnit_Framework_TestCase
{
public function testOutput() {
throw new \Exception("hello");
}
}
Yields:
...
There was 1 error:
1) theTest::testOutput
Exception: hello
Upvotes: 3
Reputation: 166359
Here are few methods useful for printing debug messages in PHPUnit 4.x:
syslog(LOG_DEBUG, "Debug: Message 1!");
More practical example:
syslog(LOG_DEBUG, sprintf("%s: Value: %s", __METHOD__, var_export($_GET, TRUE)));
Calling syslog()
will generate a system log message (see: man syslog.conf
).
Note: Possible levels: LOG_DEBUG
, LOG_INFO
, LOG_NOTICE
, LOG_WARNING
, LOG_ERR
, etc.
On macOS, to stream the syslog messages in realtime, run:
log stream --level debug --predicate 'processImagePath contains "php"'
fwrite(STDERR, "LOG: Message 2!\n");
Note: The STDERR
constant is not available if reading the PHP script from stdin. Here is the workaround.
Note: Instead of STDERR
, you can also specify a filename.
file_put_contents('php://stderr', "LOG: Message 3!\n", FILE_APPEND);
Note: Use this method, if you don't have STDERR
constant defined.
register_shutdown_function('file_put_contents', 'php://stderr', "LOG: Message 4!\n", FILE_APPEND);
Note: Use this method, if you'd like to print something at the very end without affecting the tests.
To dump the variable, use var_export()
, e.g. "Value: " . var_export($some_var, TRUE) . "\n"
.
To print above messages only during verbose or debug mode, see: Is there a way to tell if --debug or --verbose was passed to PHPUnit in a test?
Although if testing the output is part of the test it-self, check out: Testing Output docs page.
Upvotes: 0
Reputation: 2446
This was taken from PHPUnit Docs about Fixtures.
This should allow you to dump information at any point durring the phpunit test life cycle.
Just replace __METHOD__
in the code below with whatever you want to output
Example 4.2: Example showing all template methods available
<?php
class TemplateMethodsTest extends PHPUnit_Framework_TestCase
{
public static function setUpBeforeClass()
{
fwrite(STDOUT, __METHOD__ . "\n");
}
protected function setUp()
{
fwrite(STDOUT, __METHOD__ . "\n");
}
protected function assertPreConditions()
{
fwrite(STDOUT, __METHOD__ . "\n");
}
public function testOne()
{
fwrite(STDOUT, __METHOD__ . "\n");
$this->assertTrue(TRUE);
}
public function testTwo()
{
fwrite(STDOUT, __METHOD__ . "\n");
$this->assertTrue(FALSE);
}
protected function assertPostConditions()
{
fwrite(STDOUT, __METHOD__ . "\n");
}
protected function tearDown()
{
fwrite(STDOUT, __METHOD__ . "\n");
}
public static function tearDownAfterClass()
{
fwrite(STDOUT, __METHOD__ . "\n");
}
protected function onNotSuccessfulTest(Exception $e)
{
fwrite(STDOUT, __METHOD__ . "\n");
throw $e;
}
}
?>
Upvotes: 4
Reputation:
UPDATE
Just realized another way to do this that works much better than the --verbose
command line option:
class TestSomething extends PHPUnit_Framework_TestCase {
function testSomething() {
$myDebugVar = array(1, 2, 3);
fwrite(STDERR, print_r($myDebugVar, TRUE));
}
}
This lets you dump anything to your console at any time without all the unwanted output that comes along with the --verbose
CLI option.
As other answers have noted, it's best to test output using the built-in methods like:
$this->expectOutputString('foo');
However, sometimes it's helpful to be naughty and see one-off/temporary debugging output from within your test cases. There is no need for the var_dump
hack/workaround, though. This can easily be accomplished by setting the --verbose
command line option when running your test suite. For example:
$ phpunit --verbose -c phpunit.xml
This will display output from inside your test methods when running in the CLI environment.
See: Writing Tests for PHPUnit - Testing Output.
Upvotes: 272
Reputation: 13461
It's not a bug, but very much intentional. Your best bet is to write to a log file of some kind and tail the log to watch for output.
If you are trying to TEST output, check this out.
Also:
Note: Please note that PHPUnit swallows all output that is emitted during the execution of a test. In strict mode, a test that emits output will fail.
Upvotes: 10
Reputation: 107
I output my Testresults HTML based, in this case it was helpfull to flush the content:
var_dump($array);
ob_flush();
There is a second PHP Method
flush()
which i not has tried.
Upvotes: 1
Reputation: 8573
Try using --debug
Useful if you're trying to get the right path to an include or source data file.
Upvotes: 45
Reputation: 41
In laravel 5 you can use dump(), Dump the content from the last response.
class ExampleTest extends TestCase{
public function test1()
{
$this->post('/user', ['name' => 'Gema']);
$this->dump();
}
}
Upvotes: 4
Reputation: 3538
For some cases one could use something like that to output something to the console
class yourTests extends PHPUnit_Framework_TestCase
{
/* Add Warnings */
protected function addWarning($msg, Exception $previous = null)
{
$add_warning = $this->getTestResultObject();
$msg = new PHPUnit_Framework_Warning($msg, 0, $previous);
$add_warning->addWarning($this, $msg, time());
$this->setTestResultObject($add_warning);
}
/* Add errors */
protected function addError($msg, Exception $previous = null)
{
$add_error = $this->getTestResultObject();
$msg = new PHPUnit_Framework_AssertionFailedError($msg, 0, $previous);
$add_error->addError($this, $msg, time());
$this->setTestResultObject($add_error);
}
/* Add failures */
protected function addFailure($msg, Exception $previous = null)
{
$add_failure = $this->getTestResultObject();
$msg = new PHPUnit_Framework_AssertionFailedError($msg, 0, $previous);
$add_failure->addFailure($this, $msg, time());
$this->setTestResultObject($add_failure);
}
public function test_messages()
{
$this->addWarning("Your warning message!");
$this->addError("Your error message!");
$this->addFailure("Your Failure message");
}
/* Or just mark test states! */
public function test_testMarking()
{
$this->markTestIncomplete();
$this->markTestSkipped();
}
}
Upvotes: 4
Reputation: 13200
Update: See rdlowrey's update below regarding the use of fwrite(STDERR, print_r($myDebugVar, TRUE));
as a much simpler work around
This behaviour is intentional (as jasonbar has pointed out). The conflicting state of the manual has been reported to PHPUnit.
A work-around is to have PHPUnit assert the expected output is empty (when infact there is output) which will trigger the unexpected output to be shown.
class theTest extends PHPUnit_Framework_TestCase
{
/**
* @outputBuffering disabled
*/
public function testOutput() {
$this->expectOutputString(''); // tell PHPUnit to expect '' as output
print_r("Hello World");
print "Ping";
echo "Pong";
$out = "Foo";
var_dump($out);
}
}
gives:
PHPUnit @package_version@ by Sebastian Bergmann.
F
Time: 1 second, Memory: 3.50Mb
There was 1 failure:
1) theTest::testOutput
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-''
+'Hello WorldPingPongstring(4) "Foo"
+'
FAILURES!
Tests: 1, Assertions: 1, Failures: 1.
Be certain to disable any other assertions you have for the test as they may fail before the output assertion is tested (and hence you wont see the output).
Upvotes: 38
Reputation: 1087
I had to modify source code for this code to work so you need to add URL for this forked repos to composer for this will work
class TestCase extends \PHPUnit_Framework_TestCase
{
/**
* Save last response
* @var Response|null A Response instance
*/
static $lastResponse;
/**
* Modify to save response
*
* @param string $method
* @param string $uri
* @param array $parameters
* @param array $files
* @param array $server
* @param string $content
* @param bool $changeHistory
* @return \Illuminate\Http\Response
*/
final public function call(
$method,
$uri,
$parameters = [],
$files = [],
$server = [],
$content = null,
$changeHistory = true
) {
$response = parent::call($method, $uri, $parameters, $files, $server, $content, $changeHistory);
static::$lastResponse = $this->client->getResponse();
return $response;
}
/**
* Modify message to add response text
*
* @param mixed $value
* @param PHPUnit_Framework_Constraint $constraint
* @param string $message
* @since Method available since Release 3.0.0
*/
final public static function assertThat($value, PHPUnit_Framework_Constraint $constraint, $message = '')
{
$message .= PHP_EOL . static::$lastResponse . PHP_EOL;
parent::assertThat($value, $constraint, $message);
}
}
Upvotes: 0
Reputation: 17204
I'm having some luck with VisualPHPUnit, and it does helpfully show output, among other things.
class TestHello extends PHPUnit_Framework_TestCase
{
public function test_Hello()
{
print "hello world";
}
}
Upvotes: 7
Reputation: 31078
You should really think about your intentions: If you need the information now when debugging to fix the test, you will need it next week again when the tests break.
This means that you will need the information always when the test fails - and adding a var_dump
to find the cause is just too much work. Rather put the data into your assertions.
If your code is too complex for that, split it up until you reach a level where one assertion (with a custom message) tells you enough to know where it broke, why and how to fix the code.
Upvotes: 7