it-swarm.cn

如何在执行期间在CLI中输出 PHP 单元测试?

在运行PHPUnit测试时,我希望能够转储输出,这样我就可以调试一两件事。

我尝试了以下(类似于 PHPUnit手册示例 );

class theTest extends PHPUnit_Framework_TestCase
{
    /**
     * @outputBuffering disabled
     */
    public function testOutput() {
        print_r("Hello World");
        print "Ping";
        echo "Pong";
        $out = "Foo";
        var_dump($out);
    }   
}

结果如下:

PHPUnit @[email protected] by Sebastian Bergmann.

.

Time: 0 seconds, Memory: 3.00Mb

OK (1 test, 0 assertions)

请注意,没有预期的输出。

我正在使用HEAD版本的 git repos 截至2011年9月19日。

输出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

有什么我做错了,或者这可能是一个PHPUnit错误?

121
Jess Telford

_ update _

刚刚意识到另一种方法可以比--verbose命令行选项更好地工作:

class TestSomething extends PHPUnit_Framework_TestCase {
    function testSomething() {
        $myDebugVar = array(1, 2, 3);
        fwrite(STDERR, print_r($myDebugVar, TRUE));
    }
}

这使您可以随时将任何内容转储到控制台,而不会出现--verbose CLI选项随附的所有不需要的输出。


正如其他答案所指出的那样,最好使用内置方法测试输出,例如:

$this->expectOutputString('foo');

但是,有时候调侃并在测试用例中看到一次性/临时调试输出是有帮助的。但是,不需要var_dump hack/workaround。这可以通过在运行测试套件时设置--verbose命令行选项来轻松完成。例如:

$ phpunit --verbose -c phpunit.xml

在CLI环境中运行时,这将显示测试方法内部的输出。

请参阅: 为PHPUnit编写测试 - 测试输出

151
rdlowrey

更新: 请参阅 rdlowrey下面的更新 关于使用fwrite(STDERR, print_r($myDebugVar, TRUE));作为一个更简单的工作


这种行为是故意的(如 jasonbar has 指出 )。手册的冲突状态已经 报告 到PHPUnit。

解决方法是让PHPUnit断言预期的输出为空(当存在输出时),这将触发显示的意外输出。

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

得到:

PHPUnit @[email protected] 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.

确保禁用任何其他用于测试的断言,因为它们可能在测试输出断言之前失败(因此您不会看到输出)。

32
Jess Telford

尝试使用--debug

如果您正在尝试获取包含或源数据文件的正确路径,则非常有用。

27
chim

这不是一个错误,而是非常有意的。最好的办法是写入某种日志文件并拖尾日志以观察输出。

如果您正在尝试测试输出,请检查 this out。

也:

注意 :请注意PHPUnit会吞下执行测试期间发出的所有输出。在严格模式下,发出输出的测试将失败。

9
jasonbar

我喜欢 VisualPHPUnit ,它确实有助于显示输出等等。

class TestHello extends PHPUnit_Framework_TestCase 
{
    public function test_Hello() 
    {
        print "hello world";
    }
}

TestHello results

7
Bob Stein

您应该考虑一下您的意图:如果您在调试时需要现在的信息来修复测试,那么当测试中断时,您将在下周再次需要它。

这意味着您将需要信息 总是 当测试失败时 - 并添加var_dump以找到原因是太多的工作。而是将数据放入您的断言中。

如果您的代码太复杂,请将其拆分,直到达到一个级别,其中一个断言(带有自定义消息)告诉您足以知道它在哪里损坏,为什么以及如何修复代码。

5
cweiske

Hackish,但有效:将调试输出作为消息抛出异常。

class theTest extends PHPUnit_Framework_TestCase
{
    public function testOutput() {
        throw new \Exception("hello");
    }   
}

产量:

...
There was 1 error:

1) theTest::testOutput
Exception: hello
3
Matthias Rella

在laravel 5中,您可以使用dump(),转储上一个响应中的内容。

class ExampleTest extends TestCase{
    public function test1()
    {
        $this->post('/user', ['name' => 'Gema']);
        $this->dump();
    }
}

3
Branny Bk

对于某些情况,可以使用类似的东西输出控制台的东西

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

只需在执行 phpunit 时使用 --verbose flag。

$ phpunit --verbose -c phpunit.xml 

这种方法的优点是你不需要改变测试代码,你可以打印字符串,var_dump是你想要的任何东西,只有在设置了 verbose mode时它才会显示在控制台中。

我希望这有帮助。

2
Fabricio

这取自 关于Fixtures的PHPUnit文档

这应该允许您在phpunit测试生命周期的任何时候转储信息。

只需将下面代码中的__METHOD__替换为您想要输出的内容即可

示例4.2:显示所有可用模板方法的示例

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

我输出我的Testresults HTML,在这种情况下,刷新内容是有帮助的:

var_dump($array);
ob_flush();

还有第二个PHP方法

flush() 

我没试过。

1
Sudo

以下是几种用于在PHPUnit 4.x中打印调试消息的方法:

  • syslog(LOG_DEBUG, "Debug: Message 1!");

    更实际的例子:

    syslog(LOG_DEBUG, sprintf("%s: Value: %s", __METHOD__, var_export($_GET, TRUE)));
    

    调用 syslog() 将生成系统日志消息(请参阅:man syslog.conf)。

    注意:可能的级别:LOG_DEBUGLOG_INFOLOG_NOTICELOG_WARNINGLOG_ERR等。

    在macOS上,要实时流式传输syslog消息,请运行:

    log stream --level debug --predicate 'processImagePath contains "php"'
    
  • fwrite(STDERR, "LOG: Message 2!\n");

    注意:如果从 stdin 读取PHP脚本,则STDERR常量不可用。这是 解决方法

    注意:您也可以指定文件名,而不是STDERR

  • file_put_contents('php://stderr', "LOG: Message 3!\n", FILE_APPEND);

    注意:如果没有 STDERR constant defined,请使用此方法。

  • register_shutdown_function('file_put_contents', 'php://stderr', "LOG: Message 4!\n", FILE_APPEND);

    注意:如果您想在最后打印一些内容而不影响测试,请使用此方法。

要转储变量,请使用var_export(),例如"Value: " . var_export($some_var, TRUE) . "\n"

要仅在详细或调试模式下打印上述消息,请参阅: 有没有办法判断--debug或--verbose是否在测试中传递给PHPUnit?


虽然如果测试输出是测试的一部分,请查看: 测试输出 docs页面。

0
kenorb