Как написать юнит-тесты для интерактивного консольного приложения - PullRequest
6 голосов
/ 06 февраля 2012

У меня есть консольное приложение (написанное как команда Symfony2), которое читает ввод от пользователя через STDIN и с помощью readline пользовательский ввод затем передается в eval()

Все дело только в том, что у вас есть "оболочка отладки" (что-то вроде php -a), но в пределах env проекта и доступа к контейнеру Dependency Injection.

Я хотел бы написать юнит-тесты для этой команды, но я попал в стену о том, как (и возможно ли) написать тесты PHPUnit для этого поведения?

1 Ответ

7 голосов
/ 06 февраля 2012

Я не знаком с командой Sf2 Command, но в документации Sf2 есть пример о тестировании ее на http://symfony.com/doc/2.0/components/console.html#testing-commands

В общем, вы могли бы отделить STDIN и STDOUT от вашей консолиприложение, чтобы вы могли заменить его другим ресурсом потока, например fopen(php://memory).Вместо readline вы используете

fwrite($outputStream, 'Prompt');
$line = stream_get_line($inputStream, 1024, PHP_EOL);

Идея состоит в том, чтобы сделать ваш компонент тестируемым, не требуя реальной консольной среды.Использование этого подхода позволяет в любой момент проверить содержимое потока в вашем тесте. Так что, если вы запускаете Command «foo» в своем консольном приложении и хотите проверить, что вывод «bar», вы просто перематываете соответствующий ресурс и читаете его содержимое .Альтернативой может быть использование SplTempFileObject.

class ConsoleApp
…
    public function __construct($inputStream, $outputStream)
    {
        $this->inputStream = $inputStream;
        $this->outputStream = $outputStream;
    }
}

. В сценарии реального мира вы создадите консольное приложение с

$app = new ConsoleApp(STDIN, STDOUT);

Но в своем тесте вы можете настроить ConsoleApp с выбранным вами потоком:

public function setup()
{
    $i = fopen('php://memory', 'w');
    $o = fopen('php://memory', 'w');
    $this->consoleApp = new ConsoleApp($i, $o);
}

Примером UnitTest, использующим этот метод для передачи, будет

...