Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write unit-tests for interactive console app

I have a console app, (written as a Symfony2 command) that is reading input from user via STDIN and with help of readline, user input is then passed to eval()

The whole thing is just for having "debug shell" (something like a php -a) but within project env and Dependency Injection container access.

I would like to write unit-tests for this command but I'm hitting wall, on how (and is it possible) write PHPUnit tests for this behavior?

like image 726
canni Avatar asked Feb 06 '12 09:02

canni


1 Answers

I'm not familiar with the Sf2 Command thing, but the Sf2 docs have an example about testing it at http://symfony.com/doc/2.0/components/console.html#testing-commands

In general, you could decouple STDIN and STDOUT from your console app so you can replace it with another stream resource, like fopen(php://memory). Instead of readline, you use

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

The idea is to make your component testable without requiring the real console environment. Using this approach allows you to check the contents of the Stream at any time in your test. So if you run Command "foo" in your console app and want to test that the output is "bar" you simply rewind the appropriate resource and read it's content. An alternative would be to use SplTempFileObject.

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

In your real world scenario you'd create the Console App with

$app = new ConsoleApp(STDIN, STDOUT);

But in your test you can setup the ConsoleApp with a stream of your choice:

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

An example of a UnitTest using this method for the outstream would be

  • https://github.com/gooh/InterfaceDistiller/blob/master/tests/unit/Controller/CommandLineTest.php
like image 178
Gordon Avatar answered Oct 05 '22 21:10

Gordon