tit*_*tel 87 php phpunit unit-testing output-buffering
我正在尝试使用PHPunit来测试输出一些自定义标头的类.
问题是在我的机器上这个:
<?php
class HeadersTest extends PHPUnit_Framework_TestCase {
public function testHeaders()
{
ob_start();
header('Location: foo');
$headers_list = headers_list();
header_remove();
ob_clean();
$this->assertContains('Location: foo', $headers_list);
}
}
Run Code Online (Sandbox Code Playgroud)
甚至这个:
<?php
class HeadersTest extends PHPUnit_Framework_TestCase {
public function testHeaders()
{
ob_start();
header('Location: foo');
header_remove();
ob_clean();
}
}
Run Code Online (Sandbox Code Playgroud)
返回此错误:
name@host [~/test]# phpunit --verbose HeadersTest.php
PHPUnit 3.6.10 by Sebastian Bergmann.
E
Time: 0 seconds, Memory: 2.25Mb
There was 1 error:
1) HeadersTest::testHeaders
Cannot modify header information - headers already sent by (output started at /usr/local/lib/php/PHPUnit/Util/Printer.php:173)
/test/HeadersTest.php:9
FAILURES!
Tests: 1, Assertions: 0, Errors: 1.
Run Code Online (Sandbox Code Playgroud)
这看起来好像在测试运行之前还有其他东西输出到终端,即使没有包含其他文件且在PHP标记开头之前没有其他字符.它可能是PHPunit中导致这种情况的东西吗?
问题可能是什么?
Sam*_*ssy 114
问题是PHPUnit会在屏幕上打印标题,此时您无法添加更多标题.
解决方法是在一个独立的过程中运行测试.这是一个例子
<?php
class FooTest extends PHPUnit_Framework_TestCase
{
/**
* @runInSeparateProcess
*/
public function testBar()
{
header('Location : http://foo.com');
}
}
Run Code Online (Sandbox Code Playgroud)
这将导致:
$ phpunit FooTest.php
PHPUnit 3.6.10 by Sebastian Bergmann.
.
Time: 1 second, Memory: 9.00Mb
OK (1 test, 0 assertions)
Run Code Online (Sandbox Code Playgroud)
关键是@runInSeparateProcess注释.
如果您使用PHPUnit~4.1或其他东西并得到错误:
PHP Fatal error: Uncaught Error: Class 'PHPUnit_Util_Configuration' not found in -:378
Stack trace:
#0 {main}
thrown in - on line 378
Fatal error: Uncaught Error: Class 'PHPUnit_Util_Configuration' not found in - on line 378
Error: Class 'PHPUnit_Util_Configuration' not found in - on line 378
Call Stack:
0.0013 582512 1. {main}() -:0
Run Code Online (Sandbox Code Playgroud)
尝试将此添加到您的引导程序文件以修复它:
<?php
if (!defined('PHPUNIT_COMPOSER_INSTALL')) {
define('PHPUNIT_COMPOSER_INSTALL', __DIR__ . '/path/to/composer/vendors/dir/autoload.php');
}
Run Code Online (Sandbox Code Playgroud)
Jon*_*rns 101
尽管在单独的进程中运行测试确实解决了问题,但在运行大量测试时会出现明显的开销.
我的修复是将phpunit的输出定向到stderr,如下所示:
phpunit --stderr <options>
Run Code Online (Sandbox Code Playgroud)
这应该可以解决问题,这也意味着您不必创建包装函数并替换代码中的所有实例.
正如评论中已经提到的,我认为在 XML 配置文件中定义 processIsolation 是一个更好的解决方案,例如
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
processIsolation = "true"
// ...
>
</phpunit>
Run Code Online (Sandbox Code Playgroud)
像这样,您不必传递 --stderr 选项,这可能会激怒您的同事。