25

Is there a way to run a console command from a Symfony 2 test case? I want to run the doctrine commands for creating and dropping schemas.

j0k
  • 22,600
  • 28
  • 79
  • 90
vinnylinux
  • 7,050
  • 13
  • 61
  • 127

4 Answers4

76

This documentation chapter explains how to run commands from different places. Mind, that using exec() for your needs is quite dirty solution...

The right way of executing console command in Symfony2 is as below:

Option one

use Symfony\Bundle\FrameworkBundle\Console\Application as App;
use Symfony\Component\Console\Tester\CommandTester;

class YourTest extends WebTestCase
{
    public function setUp()
    {
        $kernel = $this->createKernel();
        $kernel->boot();

        $application = new App($kernel);
        $application->add(new YourCommand());

        $command = $application->find('your:command:name');
        $commandTester = new CommandTester($command);
        $commandTester->execute(array('command' => $command->getName()));
    }
}

Option two

use Symfony\Component\Console\Input\StringInput;
use Symfony\Bundle\FrameworkBundle\Console\Application;

class YourClass extends WebTestCase
{
    protected static $application;

    public function setUp()
    {
        self::runCommand('your:command:name');
        // you can also specify an environment:
        // self::runCommand('your:command:name --env=test');
    }

    protected static function runCommand($command)
    {
        $command = sprintf('%s --quiet', $command);    

        return self::getApplication()->run(new StringInput($command));
    }

    protected static function getApplication()
    {
        if (null === self::$application) {
            $client = static::createClient();

            self::$application = new Application($client->getKernel());
            self::$application->setAutoExit(false);
        }

        return self::$application;
    }
}

P.S. Guys, don't shame Symfony2 with calling exec()...

Community
  • 1
  • 1
Vitalii Zurian
  • 17,858
  • 4
  • 64
  • 81
  • 1
    This is the right answer as mentioned on the official Symfony2 documentantion under "Testing Commands": http://symfony.com/doc/current/components/console/introduction.html#testing-commands – Francesco Casula Jan 03 '14 at 15:51
  • 1
    @FrancescoCasula link is broken - new location: http://symfony.com/doc/current/console.html#testing-commands – Jeff Puckett Feb 16 '17 at 20:31
5

The docs tell you the suggested way to do it. The example code is pasted below:

protected function execute(InputInterface $input, OutputInterface $output)
{
    $command = $this->getApplication()->find('demo:greet');

    $arguments = array(
        'command' => 'demo:greet',
        'name'    => 'Fabien',
        '--yell'  => true,
    );

    $input = new ArrayInput($arguments);
    $returnCode = $command->run($input, $output);

    // ...
}
Squazic
  • 3,670
  • 3
  • 26
  • 40
-1

Yes, if your directory structure looks like

/symfony
    /app
    /src

then you would run

phpunit -c app/phpunit.xml.dist

from your unit tests you can run php commands either by using

passthru("php app/console [...]") (http://php.net/manual/en/function.passthru.php)
exec("php app/console [...]") (http://www.php.net/manual/en/function.exec.php)

or by putting the command in back ticks

php app/consode [...]

If you are running the unit tests from a directory other than symofny, you'll have to adjust the relative path to the app directory for it to work.

To run it from the app:

// the document root should be the web folder
$root = $_SERVER['DOCUMENT_ROOT'];

passthru("php $root/../app/console [...]");
ContextSwitch
  • 2,830
  • 6
  • 35
  • 51
-2

The documentation has been updated since my last answer to reflect the proper Symfony 2 way of calling an existing command:

http://symfony.com/doc/current/components/console/introduction.html#calling-an-existing-command

Klaus S.
  • 1,239
  • 10
  • 18
  • 13
    It is not true Symfony way – Vitalii Zurian Aug 01 '12 at 08:28
  • 6
    It's not even a good way as you cannot parse the ouptut correctly. You also might run into problems with the environment (what if php is not in the path of the user running the tests?). – Sgoettschkes Aug 07 '12 at 11:45
  • 1
    Please, don't do it this way! – Sobit Akhmedov Mar 30 '14 at 01:31
  • Note that the original question is not about testing commands, but about executing commands during tests. Like droping / recreating datas, validating users without email validation, etc. Please read carefully before downgrading. – Moonchild Jun 24 '16 at 10:54