运行PHPUnit测试时,我希望能够转储输出,这样我就可以调试一两件事。
我尝试了以下内容(类似于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);
}
}
具有以下结果:
PHPUnit @package_version@ by Sebastian Bergmann.
.
Time: 0 seconds, Memory: 3.00Mb
OK (1 test, 0 assertions)
请注意,没有预期的输出。
截至2011年9月19日,我正在使用git repos的HEAD版本。
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的错误吗?
答案 0 :(得分:152)
<强>更新强>
刚刚意识到另一种方法可以比--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
黑客/解决方法。通过在运行测试套件时设置--verbose
命令行选项,可以轻松完成此操作。例如:
$ phpunit --verbose -c phpunit.xml
在CLI环境中运行时,这将显示测试方法内部的输出。
答案 1 :(得分:32)
更新:有关使用fwrite(STDERR, print_r($myDebugVar, TRUE));
作为更简单的解决方法,请参阅rdlowrey's update below
此行为是故意的(因为jasonbar有pointed out)。手册的冲突状态为PHPUnit reported。
解决方法是让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 @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.
确保禁用测试中的任何其他断言,因为它们在测试输出断言之前可能会失败(因此您不会看到输出)。
答案 2 :(得分:27)
尝试使用--debug
如果您正在尝试获取包含或源数据文件的正确路径,则非常有用。
答案 3 :(得分:9)
这不是一个错误,而是非常有意的。最好的办法是写入某种日志文件并拖尾日志以观察输出。
如果您尝试测试输出,请检查this输出。
此外:
注意:请注意,PHPUnit会吞下所有发出的输出 在执行测试期间。在严格模式下,发出的测试 输出将失败。
答案 4 :(得分:7)
我对VisualPHPUnit感到很幸运,除了其他方面,它确实有助于显示输出。
class TestHello extends PHPUnit_Framework_TestCase
{
public function test_Hello()
{
print "hello world";
}
}
答案 5 :(得分:5)
你应该考虑一下你的意图:如果你现在在调试时需要这些信息来修复测试,那么当测试中断时你将在下周再次需要它。
这意味着当测试失败时,您将需要始终的信息 - 并且添加var_dump
以找到原因是太多的工作。而是将数据放入您的断言中。
如果您的代码过于复杂,请将其拆分,直至达到一个级别,其中一个断言(带有自定义消息)告诉您足以知道它在哪里损坏,为什么以及如何修复代码。
答案 6 :(得分:3)
在某些情况下,人们可以使用类似的东西向控制台输出内容
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();
}
}
答案 7 :(得分:3)
在laravel 5中,您可以使用dump(),转储上一个响应中的内容。
class ExampleTest extends TestCase{
public function test1()
{
$this->post('/user', ['name' => 'Gema']);
$this->dump();
}
}
答案 8 :(得分:3)
Hackish,但有效:将调试输出作为消息抛出异常。
class theTest extends PHPUnit_Framework_TestCase
{
public function testOutput() {
throw new \Exception("hello");
}
}
收率:
...
There was 1 error:
1) theTest::testOutput
Exception: hello
答案 9 :(得分:2)
这取自PHPUnit Docs about Fixtures。
这应该允许您在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;
}
}
?>
答案 10 :(得分:2)
执行 phpunit 时,只需使用 - verbose 标志。
$ phpunit --verbose -c phpunit.xml
这种方法的优点是你不需要更改测试代码,你可以打印字符串,var_dump&#39;所以你想要的任何东西,它只会在时显示在控制台中设置了详细模式。
我希望这会有所帮助。
答案 11 :(得分:2)
PHPUnit用ob_start()
隐藏了输出。我们可以暂时禁用它。
public function log($something = null)
{
ob_end_clean();
var_dump($something);
ob_start();
}
答案 12 :(得分:1)
我输出我的Testresults HTML,在这种情况下,刷新内容是有帮助的:
var_dump($array);
ob_flush();
还有第二个PHP方法
flush()
我没试过。
答案 13 :(得分:1)
这是一款付费产品,但我发现它的效果很好:来自 Spatie 的 Ray https://spatie.be/products/ray
就这样使用它:
<块引用>ray('message')
并且消息将显示在 Ray 输出窗口中
答案 14 :(得分:1)
您可以使用PHPunit默认的显示消息的方式来在测试中调试变量,如下所示:
$this->assertTrue(false,$your_variable);
答案 15 :(得分:0)
简而言之,phpunit禁止STDOUT。默认情况下,它将写入STDERR,除非您添加--verbose
或--debug
。您可以执行以下操作之一:
var_dump
像往常一样进行调试,但是将--verbose
添加到phpunit命令行中var_dump
像往常一样进行调试,但在其下面添加一行ob_flush();
很明显,最后一件事情就是要做的事,其余的都是快速的临时黑客。
答案 16 :(得分:0)
以下是几种在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_DEBUG
,LOG_INFO
,LOG_NOTICE
,LOG_WARNING
,LOG_ERR
等
在macOS上,要实时流式传输系统日志消息,请运行:
log stream --level debug --predicate 'processImagePath contains "php"'
fwrite(STDERR, "LOG: Message 2!\n");
注意:如果从 stdin 读取PHP脚本,则STDERR
常量不可用。这是workaround。
注意:您也可以指定文件名而不是STDERR
。
file_put_contents('php://stderr', "LOG: Message 3!\n", FILE_APPEND);
注意:如果您没有定义STDERR
constant,请使用此方法。
register_shutdown_function('file_put_contents', 'php://stderr', "LOG: Message 4!\n", FILE_APPEND);
注意:如果您想在最后打印一些内容而不影响测试,请使用此方法。
要转储变量,请使用var_export()
,例如"Value: " . var_export($some_var, TRUE) . "\n"
。
要仅在详细或调试模式下打印上述消息,请参阅:Is there a way to tell if --debug or --verbose was passed to PHPUnit in a test?
虽然测试输出是测试的一部分,但请查看:Testing Output docs页面。
答案 17 :(得分:0)
可以使用Symfony\Component\Console\Output\TrimmedBufferOutput
然后测试缓冲的输出字符串,如下所示:
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());
}
答案 18 :(得分:0)
ob_flush()
示例代码:
public function testDebugOutputToCli() {
var_dump(new DateTime());
ob_flush();
}
代码和输出截图:
我一直在为上面的所有答案而苦苦挣扎,尤其是因为所选的答案——使用 codecept_debug()
和 --debug
,如手册所述——导致了大量调试输出,使我无法使用.
我像个书呆子一样阅读 PHPUnit 手册并偶然发现了这一点,我认为这解释了导致整个 PHPUnit 整个问题的原因,而不仅仅是 Codeception:
<块引用>PHPUnit manual, Testing Output:“有时你想断言一个方法的执行,例如,产生一个预期的输出(例如,通过 echo 或 print)。 PHPUnit\Framework\TestCase 类使用 PHP 的输出缓冲功能来提供所需的功能。”
这完全有道理并解释了为什么我们看不到输出。 PHPUnit 正在保存它,以防我们要检查注释!这就是它在我们的实际测试中应该始终工作的方式,我们当然不希望随机的东西仅仅因为我们调用了一个使用 echo
的函数而出现在屏幕上。
但是在调试的时候,我们只想马上看到文字,明白了这一切,解决办法很明确:只要使用ob_flush()
按需打印输出缓冲区的内容!
为阅读有趣的手册而喝三声!
附言还发现此提示隐藏在 How to show var_dumps in phpunit or codeception by Julian on dev.to
答案 19 :(得分:-1)
如果使用Laravel,则可以使用诸如info()之类的日志记录功能来记录到storage / logs下的Laravel日志文件。因此它不会显示在您的终端中,而是显示在日志文件中。
答案 20 :(得分:-1)
我必须modify source code才能使此代码正常工作,因此您需要将this forked repos的网址添加到编辑器中才能实现此功能
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);
}
}