Black-box testing of shell scripts, including interactive scripts. Inherits from FileSystemTestCase and SvnTestCase.
getScript($command) - shell $command (no output redirecting allowed)
getInteractiveScript(
$command, - shell $command (redirecting is allowed)
$cwd = null) - pass a $cwd if you need to (see php manual, proc_open)dumpOutput($script) - print the $script object's STDERR & STDOUT to screen
Internally, SimpleScript objects need to redirect stderr to a file in order to read it. That's why the $command can't do any redirecting itself. There are no such restrictions with InteractiveScripts.
Both types of script object implement:
<?php
interface Scriptt {
function getStderr();
function getStdout();
function getExitCode();
}
A test might look something like this. You can assert whatever ought, or ought not, to be in the stdout/stderr output and you can also check the exit code.
<?php
class YourTestCase extends ShellTestCase {
function test() {
$script = $this->getScript(
'php greet.php',
$this->sandbox());
$this->assertPattern('/hello wurrld/i', $script->getStdout());
$this->assertEqual($script->getStderr(), '');
$this->assertequal($script->getExitCode(), 0);
}
The InteractiveScript class has an additional enter() method. The $input arg doesn't have to end in a newline char; this is added automatically if it doesn't exist.
<?php
class YourTestCase extends ShellTestCase {
function test() {
$script = $this->getInteractiveScript('php foo.php');
$this->assertPattern(
'/pick a colour: \(blue, green\)/i',
$script->getStdout());
$script->enter('blue');
$this->assertPattern(
'/you chose: blue/i',
$script->getStdout());
$script->enter('exit');
}
Note that, with multiple inputs, you can't get stdout/stderr back in chunks which correspond to each input. The getStdout() and getStderr() methods contain the full stderr/stdout output for the entire script. You can still do some useful testing though.
When testing an interactive script, you don't always know how many prompts you'll be faced with. The script might be malfunctioning or it might simply be impossible to predict. If you don't reply to each prompt with a valid enter() call, php will hang, waiting for an input which never arrives. Hence the extra $script->enter('exit') call. Assuming every prompt in the tested script does have an "exit" option, finishing off with an enter('exit') will guarantee termination of the script.
It's probably good practice always to give users an exit option in any case. Quite often they won't understand what is required from them at a prompt and will want to bail out - particularly when they are mucking about with an app for the first time.
The exit code returned by interactive scripts may not be reliable. I used to get odd, apparently random failures in the unit tests but I never figured out what was going on. It hasn't happened for some time now and I think I'm beginning to trust it. Run the aperiplus unit tests a few times on your own system and let me know if anything fails.
If it wasn't for this there would be no need for two script types. The proc_open based InteractiveScript should be able to do everything the exec based SimpleScript does and more.