質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Symfony2

Symphony2は、簡単で速く堅牢なプログラムの開発サイクルに焦点を当てた、オープンソースのPHPウェブアプリケーション開発フレームワークです。PHP version 5.3.3以上を対象としています。

PHPUnit

PHPUnitは、PHP向けのユニット・テスト向けフレームワークで、手動では手間のかかるテスト作業を自動化し、繰り返し実行することが可能です。

Laravel 5

Laravel 5は、PHPフレームワークLaravelの最新バージョンで、2014年11月に発表予定です。ディレクトリ構造がが現行版より大幅に変更されるほか、メソッドインジェクションやFormRequestの利用が可能になります。

Q&A

解決済

1回答

4884閲覧

デフォルトで使える -v のテスト方法

hotta

総合スコア1613

Symfony2

Symphony2は、簡単で速く堅牢なプログラムの開発サイクルに焦点を当てた、オープンソースのPHPウェブアプリケーション開発フレームワークです。PHP version 5.3.3以上を対象としています。

PHPUnit

PHPUnitは、PHP向けのユニット・テスト向けフレームワークで、手動では手間のかかるテスト作業を自動化し、繰り返し実行することが可能です。

Laravel 5

Laravel 5は、PHPフレームワークLaravelの最新バージョンで、2014年11月に発表予定です。ディレクトリ構造がが現行版より大幅に変更されるほか、メソッドインジェクションやFormRequestの利用が可能になります。

0グッド

1クリップ

投稿2016/10/13 06:04

Laravel 5.2 で以下のようなコンソールアプリを作りました。動作としては問題ないように見えます。

bash

1$ ./artisan goodexample:start 2 3 [RuntimeException] 4 Either id or tag needed. 5 6$ ./artisan goodexample:start --id=1 7GoodExampleCommand called with id=1 8 9$ ./artisan goodexample:start --id=1 -v 10GoodExampleCommand called with id=1(verbose) 11 12$ ./artisan goodexample:start --undefined=1 13 14 [Symfony\Component\Console\Exception\RuntimeException] 15 The "--undefined" option does not exist.

ソースは以下の通りです。当初はコマンド定義として $signature を使っていましたが、今は $name と getOptions() に変えています。

php

1<?php 2 3namespace App\Console\Commands; 4 5use Illuminate\Console\Command; 6use Symfony\Component\Console\Input\InputOption; 7use RuntimeException; 8 9class GoodExampleCommand extends Command 10{ 11//protected $signature = 'example:start {--id=} {--tag=}'; 12 protected $name = 'goodexample:start'; 13 protected $description = 'Run GoodExample'; 14 public function __construct() 15 { 16 parent::__construct(); 17 } 18 public function handle() 19 { 20 $id = $this->option('id'); 21 $tag = $this->option('tag'); 22 if (!$id && !$tag) { 23 throw new RuntimeException('Either id or tag needed.'); 24 } 25 $this->info(sprintf("GoodExampleCommand called with %s=%s%s", 26 $id ? 'id':'tag', $id ? $id : $tag, 27 $this->getOutput()->isVerbose() ? '(verbose)' : '')); 28 } 29 protected function getOptions() 30 { 31 return [ 32 [ 'id', 'i', InputOption::VALUE_REQUIRED, 'desc of id', null ], 33 [ 'tag', 't', InputOption::VALUE_REQUIRED, 'desc of tag', null ], 34 ]; 35 } 36}

ところがテストでは、デフォルトで使える -v が未定義オプション扱いになってしまいます。

bash

1$ phpunit tests/GoodExampleCommandTest.php 2PHPUnit 5.6.0 by Sebastian Bergmann and contributors. 3 4...E 4 / 4 (100%) 5 6Time: 130 ms, Memory: 10.00MB 7 8There was 1 error: 9 101) GoodExampleCommandTest::testGoodExampleCommandWithIdVerboseWillSuccess 11Symfony\Component\Console\Exception\InvalidOptionException: The "-v" option does not exist. 12 13/var/www/laravel/vendor/symfony/console/Input/ArrayInput.php:154 14/var/www/laravel/vendor/symfony/console/Input/ArrayInput.php:136 15/var/www/laravel/vendor/symfony/console/Input/Input.php:62 16/var/www/laravel/vendor/symfony/console/Command/Command.php:221 17/var/www/laravel/vendor/laravel/framework/src/Illuminate/Console/Command.php:155 18/var/www/laravel/tests/GoodExampleCommandTest.php:53 19/var/www/laravel/tests/GoodExampleCommandTest.php:45 20 21ERRORS! 22Tests: 4, Assertions: 4, Errors: 1.

テスト側のソースは以下の通りです:

php:GoodExampleCommandTest.php

1<?php 2 3use Illuminate\Foundation\Testing\WithoutMiddleware; 4use App\Console\Commands\GoodExampleCommand; 5use Symfony\Component\Console\Output\BufferedOutput; 6use Symfony\Component\Console\Input\ArrayInput; 7 8class GoodExampleCommandTest extends TestCase 9{ 10 public function setUp() 11 { 12 parent::setUp(); 13 $this->command = new \App\Console\Commands\GoodExampleCommand; 14 $this->command->setLaravel($this->app); 15 } 16 17 /** example:start - no options 18 * @expectedException RuntimeException 19 * @expectedExceptionMessage Either id or tag needed. 20 */ 21 public function testGoodExampleCommandWithoutMandatoryOptionsWillFail() 22 { 23 $output = $this->execute(); 24 } 25 26 /** example:start - id specified */ 27 public function testGoodExampleCommandWithIdWillSuccess() 28 { 29 $output = $this->execute(['--id' => 'id1']); 30 $this->assertEquals('GoodExampleCommand called with id=id1', 31 trim($output->fetch())); 32 } 33 34 /** example:star - tag specified */ 35 public function testGoodExampleCommandWithTagWillSuccess() 36 { 37 $output = $this->execute(['--tag' => 'tag1']); 38 $this->assertEquals('GoodExampleCommand called with tag=tag1', 39 trim($output->fetch())); 40 } 41 42 /** example:start - id specified (verbose) */ 43 public function testGoodExampleCommandWithIdVerboseWillSuccess() 44 { 45 $output = $this->execute(['--id' => 'id1', '-v' => null ]); // ここが通らない 46 $this->assertEquals('GoodExampleCommand called with id=id1(verbose)', 47 trim($output->fetch())); 48 } 49 50 protected function execute(array $params = []) 51 { 52 $output = new BufferedOutput(); 53 $this->command->run( new ArrayInput($params), $output); 54 return $output; 55 } 56 57}

CLI に関するテストの書き方は書籍(LaravelリファレンスVer.5.1 LTS対応)を参考にしていますが、Symfony のコンポーネントを使って実行する部分については、正直あまり理解できておりません。何かアドバイスがありましたらお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

Laravelのことはあまり分かりませんが、Symfony\Consoleサイドから回答させていただきます。原因は、-vや-hなどの共通オプションを管理しているのがSymfony\Component\Console\Command\Command(Illuminate\Console\Commandの親クラス)ではなく、Symfony\Component\Console\Applicationなことだと思います。

Symfony\Consoleで作成したコンソールアプリケーションでは、新しいCommandApplicationに追加してから呼び出す形になっていて、この場合に-vオプションなどが有効になるようです。多分、Laravelでも内部で利用しているのではないでしょうか。

この仕組みをテストで簡単に扱えるよう用意されているのがCommandTesterというクラスになります。一度以下の内容で試してみてください。

php

1// 追加 2use Symfony\Component\Console\Application; 3use Symfony\Component\Console\Tester\CommandTester;

php

1// 変更 2public function setUp() 3{ 4 parent::setUp(); 5 $goodExampleCommand = new \App\Console\Commands\GoodExampleCommand; 6 $goodExampleCommand->setLaravel($this->app); 7 8 // ApplicationにCommandを登録 9 $app = new Application(); 10 $app->add($goodExampleCommand); 11 12 // CommandTesterを被せる 13 $command = $app->find('goodexample:start'); 14 $this->command = new CommandTester($command); 15} 16 17// 変更 18protected function execute(array $params = []) 19{ 20 $this->command->execute($params); 21 return $this->command->getDisplay(); 22}

参考

Console コンポーネント | Symfony2日本語ドキュメント
http://docs.symfony.gr.jp/symfony2/components/console/introduction.html

console/Application.php at master · symfony/console
https://github.com/symfony/console/blob/master/Application.php#L892

投稿2016/10/13 14:17

編集2016/10/13 21:17
nnssn

総合スコア1221

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hotta

2016/10/14 01:30

変更後ソース(テスト側): ```GoodExampleCommand.php <?php use Illuminate\Foundation\Testing\WithoutMiddleware; use App\Console\Commands\GoodExampleCommand; use Symfony\Component\Console\Output\BufferedOutput; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Application; use Symfony\Component\Console\Tester\CommandTester; class GoodExampleCommandTest extends TestCase { public function setUp() { parent::setUp(); $goodExampleCommand = new \App\Console\Commands\GoodExampleCommand; $goodExampleCommand->setLaravel($this->app); // ApplicationにCommandを登録 $app = new Application(); $app->add($goodExampleCommand); // CommandTesterを被せる $command = $app->find('goodexample:start'); $this->command = new CommandTester($command); } /** example:start - no options * @expectedException RuntimeException * @expectedExceptionMessage Either id or tag needed. */ public function testGoodExampleCommandWithoutMandatoryOptionsWillFail() { $output = $this->execute(); } /** example:start - id specified */ public function testGoodExampleCommandWithIdWillSuccess() { $output = $this->execute(['--id' => 'id1']); $this->assertEquals('GoodExampleCommand called with id=id1', trim($output)); } /** example:star - tag specified */ public function testGoodExampleCommandWithTagWillSuccess() { $output = $this->execute(['--tag' => 'tag1']); $this->assertEquals('GoodExampleCommand called with tag=tag1', trim($output)); } /** example:start - id specified (verbose) */ public function testGoodExampleCommandWithIdVerboseWillSuccess() { $output = $this->execute(['--id' => 'id1', '-v' => null ]); $this->assertEquals('GoodExampleCommand called with id=id1(verbose)', trim($output)); } protected function execute(array $params = []) { $this->command->execute($params); return $this->command->getDisplay(); } } ``` これで再度テストを行ってみましたが、 ```bash $ phpunit tests/GoodExampleCommandTest.php PHPUnit 5.6.0 by Sebastian Bergmann and contributors. ...F 4 / 4 (100%) Time: 139 ms, Memory: 10.00MB There was 1 failure: 1) GoodExampleCommandTest::testGoodExampleCommandWithIdVerboseWillSuccess Failed asserting that two strings are equal. --- Expected +++ Actual @@ @@ -'GoodExampleCommand called with id=id1(verbose)' +'GoodExampleCommand called with id=id1' /var/www/laravel/tests/GoodExampleCommandTest.php:57 FAILURES! Tests: 4, Assertions: 5, Failures: 1. ``` 今度はアプリケーションが -v を認識してくれなくなりました。 その後、以下のように変更することで、テストが通るようになりました! ```bash s$ diff -Nur GoodExampleCommandTest.php.orig GoodExampleCommandTest.php --- GoodExampleCommandTest.php.orig 2016-10-14 10:25:00.037816409 +0900 +++ GoodExampleCommandTest.php 2016-10-14 10:23:48.688917317 +0900 @@ -6,6 +6,7 @@ use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Application; +use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Tester\CommandTester; class GoodExampleCommandTest extends TestCase @@ -53,14 +54,15 @@ /** example:start - id specified (verbose) */ public function testGoodExampleCommandWithIdVerboseWillSuccess() { - $output = $this->execute(['--id' => 'id1', '-v' => null ]); + $output = $this->execute(['--id' => 'id1', '-v' => null ], + [ 'verbosity' => OutputInterface::VERBOSITY_VERBOSE ]); $this->assertEquals('GoodExampleCommand called with id=id1(verbose)', trim($output)); } - protected function execute(array $params = []) + protected function execute(array $input = [], $options = []) { - $this->command->execute($params); + $this->command->execute($input, $options); return $this->command->getDisplay(); } ``` 以上、ご指導いただきまして、ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問