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

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?

This question is related to php unit-testing phpunit

The answer is


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


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


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.


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

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.


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.


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.


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

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

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

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

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

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.


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


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

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.


Try using --debug

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


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.


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

Examples related to php

I am receiving warning in Facebook Application using PHP SDK Pass PDO prepared statement to variables Parse error: syntax error, unexpected [ Preg_match backtrack error Removing "http://" from a string How do I hide the PHP explode delimiter from submitted form results? Problems with installation of Google App Engine SDK for php in OS X Laravel 4 with Sentry 2 add user to a group on Registration php & mysql query not echoing in html with tags? How do I show a message in the foreach loop?

Examples related to unit-testing

Deprecated Gradle features were used in this build, making it incompatible with Gradle 5.0 How to test the type of a thrown exception in Jest Unit Tests not discovered in Visual Studio 2017 Class Not Found: Empty Test Suite in IntelliJ Angular 2 Unit Tests: Cannot find name 'describe' Enzyme - How to access and set <input> value? Mocking HttpClient in unit tests Example of Mockito's argumentCaptor How to write unit testing for Angular / TypeScript for private methods with Jasmine Why is the Visual Studio 2015/2017/2019 Test Runner not discovering my xUnit v2 tests

Examples related to phpunit

How do I get HTTP Request body content in Laravel? How to run single test method with phpunit? How to output in CLI during execution of PHP Unit tests? PHPUnit assert that an exception was thrown? Best practices to test protected methods with PHPUnit