使用PHPUnit测试输出到php:// stdout

时间:2016-09-30 04:41:09

标签: php phpunit stdout

我正在使用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://stdoutConsoleOutput默认使用的输出):

// 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中运行。

提前谢谢。

2 个答案:

答案 0 :(得分:9)

捕获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,以阻止正常输出流。

答案 1 :(得分:1)

有一种方法可以将STDOUT替换为任何其他资源:关闭它。下一个打开的资源将具有文件描述符" 1" (STDOUT)因为这是第一个免费的。

fclose(STDOUT);
$fakestdout = fopen('php://memory', 'r+');

现在任何输出都转到$fakestdout,你可以在测试用例中读取它。

唯一的问题是此操作无法恢复。因此,从现在起,每次尝试写入STDOUT(包括" echo")都会在关闭之后转到$fakestdout或其他地方。 关闭后无法重新打开STDOUT。

但是如果你运行带有--stderr参数的PHPUnit来为PHPUnit输出使用STDERR,那么这应该可行。