简体   繁体   English

当在Behat上下文中作为Symfony Process运行时,Expect的早期交互式CLI命令退出时为0

[英]Spawning interactive CLI command with Expect exits with 0 early, when run as Symfony Process in Behat context

This is quite an advanced question, perhaps knowledge of Symfony and Behat may not be necessary to understand the problem. 这是一个非常先进的问题,也许没有必要了解Symfony和Behat来理解这个问题。

So in order to test the input and output of an interactive CLI app bin/albumgrab I've written in PHP using the Symfony Console component, I've set up my Behat feature context to build an expect script, run via exec . 因此,为了测试我使用Symfony控制台组件用PHP编写的交互式CLI应用程序bin/albumgrab的输入和输出,我已经设置了我的Behat特性上下文来构建一个expect脚本,通过exec运行。

This exec command is run in PHP via Symfony Process . exec命令通过Symfony Process在PHP中运行。

$expect = <<<BASH
exec expect -c '
    set timeout 180
    spawn bin/albumgrab
    expect "Please enter the name of the directory"
    send "/tmp/php-london\n"
    expect "Please enter the URL to the first image"
    send "https://www.facebook.com/PeeHPLondon/photos/pb.7119218495.-2207520000.1430669248./10153559172718496/?type=3&src=https%3A%2F%2Ffbcdn-sphotos-g-a.akamaihd.net%2Fhphotos-ak-xfp1%2Fv%2Ft1.0-9%2F10986697_10153559172718496_5727444485530442900_n.jpg%3Foh%3Dc47770f4cd15fecc6888bcd504899087%26oe%3D55DA9CB0%26__gda__%3D1439174101_7c78a93bf247dbad6c56681b6db5309c&size=960%2C959&fbid=10153559172718496\\n"
    interact
'

BASH;

$process = new Symfony\Component\Process\Process($expect);

$process->mustRun();

However, when it gets past the second input, it seems to exit but successfully. 但是,当它超过第二个输入时,它似乎退出但成功。

Calling: 呼叫:

$process->setTty(true);

Makes it run all the way through, but will print straight to stdout and I can no longer capture the output to make an assertion, not even with PHP's output buffering. 使它一直运行,但会直接打印到stdout,我不能再捕获输出来进行断言,即使使用PHP的输出缓冲也是如此。

I figured PTY would be more suitable anyway: 我认为PTY无论如何都会更合适:

$process->setPty(true);

As it was the solution to this StackOverflow question . 因为它是StackOverflow问题的解决方案。 However, this is not supported everywhere, at least not on Mac OS X. 但是,这在任何地方都不受支持,至少在Mac OS X上不支持。

You can see what I've attempted so far in Github: https://github.com/adamelso/albumgrab/pull/13/files and the Travis output for the last attempt https://travis-ci.org/adamelso/albumgrab/jobs/61137499 您可以在Github中看到我到目前为止所尝试的内容: https//github.com/adamelso/albumgrab/pull/13/files和最后一次尝试的Travis输出https://travis-ci.org/adamelso/ albumgrab /职位/ 61137499

So my main question is why it keeps exiting with 0 early and how to prevent it? 所以我的主要问题是它为什么一直提前退出0以及如何防止它?

In order to be able receive an answer to a question - you definitely need a Terminal (TTY) or a Pseudo-Terminal (PTY) to obtain any user-input. 为了能够接收问题的答案 - 您肯定需要终端(TTY)或伪终端(PTY)来获得任何用户输入。

That's why - without $process->setTty(true) or setPty(true) - the QuestionHelper silently falls back to the default value and the command succeeds with exit code 0. 这就是为什么 - 没有$process->setTty(true)setPty(true) - QuestionHelper默默地回退到默认值,命令成功,退出代码为0。

Now - to test your command with example user input - you should make use of the symfony's console helper components instead of using expect. 现在 - 使用示例用户输入来测试命令 - 您应该使用symfony的控制台助手组件而不是使用expect。

Symfony\Component\Console\Helper\HelperSet 
Symfony\Component\Console\Tester\CommandTester

How to use these helpers is described in the cookbook chapter Testing a Command that expects input . 如何使用这些助手在烹饪书章节测试期望输入的命令中进行了描述。

As per the answer to Expect Script wait Command Hangs you need to wait for EOF instead of using the interact command: 根据Expect Script wait命令挂起的答案,您需要等待EOF而不是使用interact命令:

set timeout 180
spawn ./bin/albumgrab
expect "Please enter the name of the directory"
send "/tmp/php-london\n"
expect "Please enter the URL to the first image"
send "https://www.facebook.com/PeeHPLondon/photos/pb.7119218495.-2207520000.1430669248./10153559172718496/\n"
expect EOF

Here's a full script I've used to test it on an OS X: 这是我用来在OS X上测试它的完整脚本:

<?php

require_once __DIR__.'/vendor/autoload.php';

use Symfony\Component\Process\Process;

$expect = <<<BASH
exec expect -c '
    set timeout 180
    spawn ./bin/albumgrab
    expect "Please enter the name of the directory"
    send "/tmp/php-london\n"
    expect "Please enter the URL to the first image"
    send "https://www.facebook.com/PeeHPLondon/photos/pb.7119218495.-2207520000.1430669248./10153559172718496/?type=3&src=https%3A%2F%2Ffbcdn-sphotos-g-a.akamaihd.net%2Fhphotos-ak-xfp1%2Fv%2Ft1.0-9%2F10986697_10153559172718496_5727444485530442900_n.jpg%3Foh%3Dc47770f4cd15fecc6888bcd504899087%26oe%3D55DA9CB0%26__gda__%3D1439174101_7c78a93bf247dbad6c56681b6db5309c&size=960%2C959&fbid=10153559172718496\\n"
    expect EOF
'

BASH;

$process = new Process($expect);
$process->setPty(true);
$process->start();

$process->wait(function ($type, $buffer) {
    if (Process::ERR === $type) {
        echo 'ERR > '.$buffer;
    } else {
        echo 'OUT > '.$buffer;
    }
});

if (!$process->isSuccessful()) {
    throw new \RuntimeException($process->getErrorOutput());
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM