Проверьте вывод в php: // stdout с помощью 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,

Есть ли способ проверить вывод php://stdout с PHPUnit?

Или есть какой-либо другой способ записать вывод в php://stdout в строку (и так проверить в PHPUnit)?

Вышеуказанные тесты выполнялись в PHPUnit 5.5.5.

Заранее спасибо.

5

Решение

Быстрый и грязный способ захвата 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 если хочешь.

8

Другие решения

Есть способ заменить STDOUT любым другим ресурсом: закройте его. Следующий открытый ресурс будет иметь файловый дескриптор «1» (STDOUT), потому что это первый свободный ресурс.

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

Теперь любой вывод идет в $fakestdout и вы можете прочитать из него в вашем тестовом случае.

Единственная проблема заключается в том, что эту операцию нельзя отменить. Таким образом, теперь каждая попытка записи в STDOUT (включая «эхо») будет $fakestdoutили никуда, после того как ты его закроешь. Вы не можете открыть STDOUT после закрытия.

Но если вы запустите PHPUnit с --stderr аргумент для использования STDERR для вывода PHPUnit, это должно работать.

1

По вопросам рекламы [email protected]