使用 PHPUnit 测试输出到 php://stdout
Test output to php://stdout with PHPUnit
我正在使用 Symfony\Component\Console\Output\ConsoleOutput
写入控制台。
明确地说,我正在写信给 php://stdout
。
在我的单元测试中,我希望能够检查控制台的输出。
使用 PHPUnit 方法 expectOutputString()
,我可以检查输出:
// Passes, as expected
public function testOutputBufferingEcho()
{
$this->expectOutputString('Hello');
echo 'Hello';
}
这也适用于 php://output
的输出:
// Passes, as expected
public function testOutputBufferingOutput()
{
$this->expectOutputString('Hello');
$out = fopen('php://output', 'w');
fputs ($out, 'Hello');
fclose($out);
}
但是,它不适用于 php://stdout
的输出(ConsoleOutput
作为默认值使用):
// Failed asserting that two strings are equal.
// --- Expected
// +++ Actual
// @@ @@
// -'Hello'
// +''
public function testOutputBufferingStdOut()
{
$this->expectOutputString('Hello');
$out = fopen('php://stdout', 'w');
fputs ($out, 'Hello');
fclose($out);
}
此外,似乎无法使用 ob_*
函数将输出直接捕获到 php://stdout
。
有没有用 PHPUnit 测试到 php://stdout
的输出?
或者是否有任何其他方法可以将 php://stdout
的输出捕获到字符串中(并在 PHPUnit 中进行测试)?
以上测试 运行 在 PHPUnit 5.5.5.
提前致谢。
有一种方法可以用任何其他资源替换 STDOUT:关闭它。下一个打开的资源将具有文件描述符“1”(STDOUT),因为这是第一个空闲资源。
fclose(STDOUT);
$fakestdout = fopen('php://memory', 'r+');
现在任何输出都进入 $fakestdout
,您可以在测试用例中读取它。
唯一的问题是此操作无法还原。所以从现在开始,每次尝试写入 STDOUT(包括 "echo")都将转到 $fakestdout
,或者在您关闭它之后无处可去。 STDOUT 一旦关闭就无法重新打开。
但是,如果您 运行 PHPUnit 使用 --stderr
参数将 STDERR 用于 PHPUnit 输出,这应该有效。
捕获 php://stdout
(或任何其他流)的一种快速而肮脏的方法是使用更快且更脏的流过滤器。
示例:
class Intercept extends php_user_filter
{
public static $cache = '';
public function filter($in, $out, &$consumed, $closing)
{
while ($bucket = stream_bucket_make_writeable($in)) {
self::$cache .= $bucket->data;
$consumed += $bucket->datalen;
stream_bucket_append($out, $bucket);
}
return PSFS_PASS_ON;
}
}
stream_filter_register("intercept", "Intercept");
$stdout = fopen('php://stdout', 'w'); // or $yerSymfonyThingy->getStream()
stream_filter_append($stdout, "intercept");
fwrite($stdout, "Hello\n");
var_dump(Intercept::$cache);
输出:
Hello
string(6) "Hello
"
写入流的所有内容都会收集到 Intercept::$cache
中供您阅读。
如果愿意,您也可以通过将 PSFS_PASS_ON
替换为 PSFS_FEED_ME
来阻止流的正常输出。
我正在使用 Symfony\Component\Console\Output\ConsoleOutput
写入控制台。
明确地说,我正在写信给 php://stdout
。
在我的单元测试中,我希望能够检查控制台的输出。
使用 PHPUnit 方法 expectOutputString()
,我可以检查输出:
// Passes, as expected
public function testOutputBufferingEcho()
{
$this->expectOutputString('Hello');
echo 'Hello';
}
这也适用于 php://output
的输出:
// Passes, as expected
public function testOutputBufferingOutput()
{
$this->expectOutputString('Hello');
$out = fopen('php://output', 'w');
fputs ($out, 'Hello');
fclose($out);
}
但是,它不适用于 php://stdout
的输出(ConsoleOutput
作为默认值使用):
// Failed asserting that two strings are equal.
// --- Expected
// +++ Actual
// @@ @@
// -'Hello'
// +''
public function testOutputBufferingStdOut()
{
$this->expectOutputString('Hello');
$out = fopen('php://stdout', 'w');
fputs ($out, 'Hello');
fclose($out);
}
此外,似乎无法使用 ob_*
函数将输出直接捕获到 php://stdout
。
有没有用 PHPUnit 测试到 php://stdout
的输出?
或者是否有任何其他方法可以将 php://stdout
的输出捕获到字符串中(并在 PHPUnit 中进行测试)?
以上测试 运行 在 PHPUnit 5.5.5.
提前致谢。
有一种方法可以用任何其他资源替换 STDOUT:关闭它。下一个打开的资源将具有文件描述符“1”(STDOUT),因为这是第一个空闲资源。
fclose(STDOUT);
$fakestdout = fopen('php://memory', 'r+');
现在任何输出都进入 $fakestdout
,您可以在测试用例中读取它。
唯一的问题是此操作无法还原。所以从现在开始,每次尝试写入 STDOUT(包括 "echo")都将转到 $fakestdout
,或者在您关闭它之后无处可去。 STDOUT 一旦关闭就无法重新打开。
但是,如果您 运行 PHPUnit 使用 --stderr
参数将 STDERR 用于 PHPUnit 输出,这应该有效。
捕获 php://stdout
(或任何其他流)的一种快速而肮脏的方法是使用更快且更脏的流过滤器。
示例:
class Intercept extends php_user_filter
{
public static $cache = '';
public function filter($in, $out, &$consumed, $closing)
{
while ($bucket = stream_bucket_make_writeable($in)) {
self::$cache .= $bucket->data;
$consumed += $bucket->datalen;
stream_bucket_append($out, $bucket);
}
return PSFS_PASS_ON;
}
}
stream_filter_register("intercept", "Intercept");
$stdout = fopen('php://stdout', 'w'); // or $yerSymfonyThingy->getStream()
stream_filter_append($stdout, "intercept");
fwrite($stdout, "Hello\n");
var_dump(Intercept::$cache);
输出:
Hello
string(6) "Hello
"
写入流的所有内容都会收集到 Intercept::$cache
中供您阅读。
如果愿意,您也可以通过将 PSFS_PASS_ON
替换为 PSFS_FEED_ME
来阻止流的正常输出。