Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Getting exit code from runCommand() #329

Closed
IwfY opened this issue Jul 23, 2017 · 6 comments
Closed

Getting exit code from runCommand() #329

IwfY opened this issue Jul 23, 2017 · 6 comments

Comments

@IwfY
Copy link

IwfY commented Jul 23, 2017

For some command testing I want to evaluate the exit code returned by it. With the current implementation of runCommand() in WebTestCase this is not possible.

So I basically copied the function and used a reference parameter to pass the command's exit code.

/**
 * Builds up the environment to run the given command.
 *
 * alternative to self::runCommand
 *
 * $reuseKernel defaults to true compared to Liip/WebTestCase
 *
 * @param string $name
 * @param array  $params
 * @param bool   $reuseKernel
 * @param int    $runExitCode pointer to be filled with exit code of run command
 *
 * @return string
 */
protected function runCommandWithExitCode($name, array $params = array(), $reuseKernel = true, &$runExitCode)
{
    array_unshift($params, $name);

    if (!$reuseKernel) {
        if (null !== static::$kernel) {
            static::$kernel->shutdown();
        }

        $kernel = static::$kernel = $this->createKernel(array('environment' => $this->environment));
        $kernel->boot();
    } else {
        $kernel = $this->getContainer()->get('kernel');
    }

    $application = new Application($kernel);
    $application->setAutoExit(false);

    // @codeCoverageIgnoreStart
    if ('203' === substr(Kernel::VERSION_ID, 0, 3)) {
        $params = $this->configureVerbosityForSymfony203($params);
    }
    // @codeCoverageIgnoreEnd

    $input = new ArrayInput($params);
    $input->setInteractive(false);

    $fp = fopen('php://temp/maxmemory:' . $this->maxMemory, 'r+');
    $output = new StreamOutput($fp, $this->getVerbosityLevel(), $this->getDecorated());

    $runExitCode = $application->run($input, $output);

    rewind($fp);

    return stream_get_contents($fp);
}

I'd be willing to create a pull request for such functionality if it is wanted in this bundle. I just need some advice how to integrate this feature. Expanding the interface of the current runCommand in the way seen above might not be wanted as it would break backwards compatibility. But having this much duplicate code feels bad too.

Any interest in the feature or preferences how you'd like to have it implemented?

@alexislefebvre
Copy link
Collaborator

We may add a variable in order to store the value:

$this->lastExitCode = $application->run($input, $output);

And a method in order to check the exit code:

public function assertSameLastExitCode($expectedExitCode) {
    // the following code has to be rewritten
    PHPUnit::assertSame($expectedExitCode, $this->lastExitCode);
}

@Jean85
Copy link
Contributor

Jean85 commented Sep 15, 2017

If we can consider BCs (due to #332), we could do a cleaner solution, changing the return value to an object containing both the output and the exit code as gettable properties.

@soullivaneuh
Copy link
Contributor

changing the return value to an object containing both the output and the exit code as gettable properties.

Also, as the current result is a string, we may implement __toString method to the object returning the same thing with backward compatibility keeping.

@fsevestre
Copy link
Contributor

Using the CommandTester class may solve the issue (see also #219):

This is what I do as a replacement of runCommand for the moment:

protected function executeCommand(Command $command, array $arguments = [], $reuseKernel = false)
{
    if (!$reuseKernel) {
        if (null !== static::$kernel) {
            static::$kernel->shutdown();
        }

        $kernel = static::$kernel = static::createKernel(['environment' => $this->environment]);
        $kernel->boot();
    } else {
        $kernel = $this->getContainer()->get('kernel');
    }

    $application = new Application($kernel);
    $application->add($command);

    $command = $application->find($command->getName());
    $commandTester = new CommandTester($command);
    $commandTester->execute(
        array_merge(['command' => $command->getName()], $arguments),
        [
            'interative' => false,
            'decorated' => $this->getDecorated(),
            'verbosity' => $this->getVerbosityLevel(),
        ]
    );

    return $commandTester;
}

And to use it:

$commandTester = $this->executeCommand(new MyCommand());

static::assertSame(0, $commandTester->getStatusCode());
static::assertSame($display, $commandTester->getDisplay());

Maybe something like this could be implemented for v2 as replacement of the current implementation of runCommand?

@magnetik
Copy link
Contributor

@alexislefebvre what do you think about flagging it for 2.0 as we have seen that it requires some BC break.

@alexislefebvre
Copy link
Collaborator

This has been fixed in #460.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants