Невозможно проверить консольную команду Symfony2 - PullRequest
4 голосов
/ 22 января 2012

В рамках изучения Symfony2 я пытаюсь написать очень простую консольную команду, которая просто запускает phpcs (PHP Code Sniffer).

Вот функция execute, которая находится в классе, расширяющем ContainerAwareCommand:

protected function execute(InputInterface $input, OutputInterface $output)
{
    $output->writeln('<info>Generating PHP Code Sniffer report...</info>');
    exec('phpcs ./src > ./app/logs/phpcs.log');

    if ($input->getOption('noprompt') == null) {
        $dialog = $this->getHelperSet()->get('dialog');
        if ($dialog->askConfirmation($output, '<question>Open report in TextMate? (y/n)?</question>', false)) {
            exec('mate ./app/logs/phpcs.log');
        }
    }

    $output->writeln('<info>...done</info>');
}

Я могу выполнить консольную команду, запустив

app/console mynamespace:ci:phpcs

, и она отлично работает.Выходной файл генерируется, как и ожидалось.

Я пытаюсь проверить команду mynamespace: ci: phpcs, используя следующую функцию (которая является частью PHPUnit_Framework_TestCase):

public function testExecute()
{
    $kernel = new \AppKernel("test", true);
    $kernel->boot();

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

    $command = $application->find('mynamespace:ci:phpcs');
    $commandTester = new CommandTester($command);
    $commandTester->execute(array('command' => $command->getName()));

    // ... Test if output file was created here ... ommitted for brevity ... //
}

Однакопри попытке выполнить его с помощью модульного теста происходит сбой со следующим выводом:

sh: phpcs: command not found

У кого-нибудь есть идея, почему это происходит?

PS: Я наблюдал одну вещьБыло то, что, когда я закомментировал строки в команде, которые вызывают 'exec', тест проходит (не проходя, но не жалуясь, что phpcs не существует), поэтому проблема определенно связана с командами exec.

Тесты PHPUnit запускаются от имени другого пользователя, где phpcs недоступен?

1 Ответ

5 голосов
/ 23 января 2012

Для модульных тестов вы должны подумать о том, чтобы посмеяться над вызовами на exec().Это ускорит ваши тесты и позволит избежать экологических проблем, таких как эта.В этом случае вы можете просто добавить методы, которые вызывают exec(), к вашему классу, который вы можете смоделировать для тестов.

class PhpCodeSnifferCommand extends ...
{
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        // ...
        runReport();
        // ...
                viewReport();
        // ...
    }

    protected function runReport() {
        exec('phpcs ./src > ./app/logs/phpcs.log');
    }

    protected function viewReport() {
        exec('mate ./app/logs/phpcs.log');
    }
}

Пересмешивание облегчает проверку трех возможных путей:

  1. Команде предписано не предлагать пользователю просмотреть отчет.
  2. Команде выдается запрос;пользователь говорит нет.
  3. Команде дают подсказку;пользователь говорит да.

Поместите каждый путь в его собственный тест.Вы можете поместить общий код в метод вспомогательного тестирования, чтобы сделать его намного короче.

public function testRunsReportWithoutAskingToView()
{
    // ...

    $application = new Application($kernel);
    $phpcs = $this->getMock('PhpCodeSnifferCommand', array('runReport', 'viewReport'));
    $phpcs->expects($this->once())->method('runReport');
    $phpcs->expects($this->never())->method('viewReport');
    $application->add($phpcs);

    // Tell the command not to prompt to view the report ...
}

public function testRunsAndViewsReport()
{
    // ...

    $application = new Application($kernel);
    $phpcs = $this->getMock('PhpCodeSnifferCommand', array('runReport', 'viewReport'));
    $phpcs->expects($this->once())->method('runReport');
    $phpcs->expects($this->once())->method('viewReport');
    $application->add($phpcs);

    // Tell the command to prompt to view and the dialog to hit "Y" for you ...
}

public function testRunsReportButDoesntViewIt()
{
    // ...

    $application = new Application($kernel);
    $phpcs = $this->getMock('PhpCodeSnifferCommand', array('runReport', 'viewReport'));
    $phpcs->expects($this->once())->method('runReport');
    $phpcs->expects($this->never())->method('viewReport');
    $application->add($phpcs);

    // Tell the command to prompt to view and the dialog to hit "N" for you ...
}
...