How to output in CLI during execution of PHP Unit tests?

PhpUnit TestingPhpunit

Php Problem Overview


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?

Php Solutions


Solution 1 - Php

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.

Solution 2 - Php

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).

Solution 3 - Php

Try using --debug

Useful if you're trying to get the right path to an include or source data file.

Solution 4 - Php

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.

Solution 5 - Php

Just call ob_flush() after outputting text

Example code:

	public function testDebugOutputToCli() {
		var_dump(new DateTime());
		ob_flush();
	}

Screenshot of code and output:

Screenshot of using ob_flush to echo out content that would otherwise have been hidden by PHPUnit

Why? PHPUnit is always output buffering, so we need to dump the buffer when debugging

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

Solution 6 - Php

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.

Solution 7 - Php

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";
    }
}

TestHello results

Solution 8 - Php

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.

Solution 9 - Php

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();
    }
}

gives

Solution 10 - Php

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;
    }
}
?>

Solution 11 - Php

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();
    }
}

Solution 12 - Php

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

Solution 13 - Php

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();
	}

Solution 14 - Php

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.

Solution 15 - Php

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

Solution 16 - Php

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);
    }
}

Solution 17 - Php

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: <https://stackoverflow.com/q/12610605/55075>


Although if testing the output is part of the test it-self, check out: Testing Output docs page.

Solution 18 - Php

In short, phpunit supresses STDOUT. It writes to STDERR by default, unless you add --verbose or --debug . You can do one of those things:

  • print your debug output to STDERR instead
  • var_dump your debug as usual but add --verbose to the phpunit command line
  • var_dump your debug as usual but add a line ob_flush(); beneath it
  • use the correct commands in phpunit for testing exactly what you're trying to test here

Obviously, the last thing is the Good Thing to do, and the rest are quick temporary hacks.

Solution 19 - Php

You can use PHPunit default way of showing messages to debug your variables inside your test like this:

$this->assertTrue(false,$your_variable);

Solution 20 - Php

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());   
}

Solution 21 - Php

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJess TelfordView Question on Stackoverflow
Solution 1 - PhprdlowreyView Answer on Stackoverflow
Solution 2 - PhpJess TelfordView Answer on Stackoverflow
Solution 3 - PhpchimView Answer on Stackoverflow
Solution 4 - PhpjasonbarView Answer on Stackoverflow
Solution 5 - PhpjerclarkeView Answer on Stackoverflow
Solution 6 - PhpcweiskeView Answer on Stackoverflow
Solution 7 - PhpBob SteinView Answer on Stackoverflow
Solution 8 - PhpFabricioView Answer on Stackoverflow
Solution 9 - PhpBranny BkView Answer on Stackoverflow
Solution 10 - PhpChrisView Answer on Stackoverflow
Solution 11 - PhpmkunglaView Answer on Stackoverflow
Solution 12 - PhpMatthias RellaView Answer on Stackoverflow
Solution 13 - PhpSlawaView Answer on Stackoverflow
Solution 14 - PhpSudoView Answer on Stackoverflow
Solution 15 - PhpiteratorXView Answer on Stackoverflow
Solution 16 - PhpGadelkareemView Answer on Stackoverflow
Solution 17 - PhpkenorbView Answer on Stackoverflow
Solution 18 - PhpcommonpikeView Answer on Stackoverflow
Solution 19 - PhpMohsen ShamohamadiView Answer on Stackoverflow
Solution 20 - PhpgpupoView Answer on Stackoverflow
Solution 21 - PhpleoView Answer on Stackoverflow