2012-01-22 14 views
4

Symfony2の学習の一環として、私は単純にphpcs(PHP Code Sniffer)を実行する非常に単純なコンソールコマンドを書こうとしています。Symfony2コンソールコマンドをテストできません

ここ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 

を実行して、コンソールコマンドを実行することが可能ですし、それが完璧に動作します。出力ファイルは期待どおりに生成されます。

Iは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:私が観察したことの1つは、「exec」と呼ばれるコマンドの行をコメントアウトすると、テストが実行されます(渡されず、phpcsが存在しないということに気づかない)ので、問題です間違いなくexecコマンドを使用しています。

PHPUnitテストは、phpcsが利用できない別のユーザーとして実行されますか?

+0

PHPUnitをどのように実行していますか?コンソールから、Jenkinsや他のCIツールの中から、IDEからどのように実行していますか? Jenkinsは私のUbuntuシステムで 'jenkins'ユーザとして動作しますが、私のIDEはコンソールと同じように動作します。 –

+0

私は通常それらをIntelliJから実行していますが、コマンドラインからも実行しようとしました。 –

+0

あなたの '$ PATH'に' phpcs'がインストールされていることを確認してください。これは典型的なケースですので少し奇妙です。 Mockingは問題を解決しますが、問題を下流に遅らせるだけの場合もあります。 –

答えて

5

単体テストの場合、呼び出しをexec()に合わせることを検討する必要があります。これはあなたのテストをスピードアップし、このような環境問題を避けるでしょう。この場合は、exec()を呼び出すメソッドをクラスに追加して、テスト用にモックすることができます。コマンドは、レポートを表示するようにユーザーを促すためないように言われ

  1. 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'); 
        } 
    } 
    

    モッキングは、それが簡単に三つの可能なパスを検証することができます。

  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 ... 
} 
+0

あなたの答えをありがとう、これは間違いなくそれにアプローチする最善の方法です。なぜ私はexecにコールを嘲笑することを考えなかったのか分かりません。優れたアドバイス! –

関連する問題