コンソールテスト
イントロダクション
HTTPテストの簡素化に加え、LaravelはアプリケーションのカスタムコンソールコマンドをテストするためのシンプルなAPIを提供しています。
成功/失敗の表明
まず、Artisanコマンドの終了コードに関するアサーションを行う方法を探ってみましょう。これを実現するために、artisanメソッドを使用してテストからArtisanコマンドを呼び出します。次に、assertExitCodeメソッドを使用して、コマンドが指定の終了コードで完了したことをアサートします。
1test('console command', function () {2 $this->artisan('inspire')->assertExitCode(0);3});
1/**2 * Test a console command.3 */4public function test_console_command(): void5{6 $this->artisan('inspire')->assertExitCode(0);7}
コマンドが指定の終了コードで終了しなかったことを表明するには、assertNotExitCodeメソッドを使用します。
1$this->artisan('inspire')->assertNotExitCode(1);
もちろん、すべてのターミナルコマンドは、成功した場合は通常0のステータスコードで終了し、成功しなかった場合はゼロ以外の終了コードで終了します。したがって、利便性のために、assertSuccessfulとassertFailedアサーションを利用して、指定したコマンドが成功の終了コードで終了したか、そうでないかをアサートできます。
1$this->artisan('inspire')->assertSuccessful();2 3$this->artisan('inspire')->assertFailed();
入力/出力の表明
Laravelでは、expectsQuestionメソッドを使用して、コンソールコマンドへのユーザー入力を簡単に「モック」できます。さらに、assertExitCodeとexpectsOutputメソッドを使用して、コンソールコマンドによって出力されると予想される終了コードとテキストを指定できます。たとえば、以下のコンソールコマンドについて考えてみます。
1Artisan::command('question', function () { 2 $name = $this->ask('What is your name?'); 3 4 $language = $this->choice('Which language do you prefer?', [ 5 'PHP', 6 'Ruby', 7 'Python', 8 ]); 9 10 $this->line('Your name is '.$name.' and you prefer '.$language.'.');11});
このコマンドは、次のテストでテストできます。
1test('console command', function () {2 $this->artisan('question')3 ->expectsQuestion('What is your name?', 'Taylor Otwell')4 ->expectsQuestion('Which language do you prefer?', 'PHP')5 ->expectsOutput('Your name is Taylor Otwell and you prefer PHP.')6 ->doesntExpectOutput('Your name is Taylor Otwell and you prefer Ruby.')7 ->assertExitCode(0);8});
1/** 2 * Test a console command. 3 */ 4public function test_console_command(): void 5{ 6 $this->artisan('question') 7 ->expectsQuestion('What is your name?', 'Taylor Otwell') 8 ->expectsQuestion('Which language do you prefer?', 'PHP') 9 ->expectsOutput('Your name is Taylor Otwell and you prefer PHP.')10 ->doesntExpectOutput('Your name is Taylor Otwell and you prefer Ruby.')11 ->assertExitCode(0);12}
Laravel Promptsが提供するsearchまたはmultisearch関数を利用している場合は、expectsSearchアサーションを使用して、ユーザーの入力、検索結果、選択をモックできます。
1test('console command', function () {2 $this->artisan('example')3 ->expectsSearch('What is your name?', search: 'Tay', answers: [4 'Taylor Otwell',5 'Taylor Swift',6 'Darian Taylor'7 ], answer: 'Taylor Otwell')8 ->assertExitCode(0);9});
1/** 2 * Test a console command. 3 */ 4public function test_console_command(): void 5{ 6 $this->artisan('example') 7 ->expectsSearch('What is your name?', search: 'Tay', answers: [ 8 'Taylor Otwell', 9 'Taylor Swift',10 'Darian Taylor'11 ], answer: 'Taylor Otwell')12 ->assertExitCode(0);13}
コンソールコマンドが何も出力しないことをdoesntExpectOutputメソッドを使用してアサートすることもできます。
1test('console command', function () {2 $this->artisan('example')3 ->doesntExpectOutput()4 ->assertExitCode(0);5});
1/**2 * Test a console command.3 */4public function test_console_command(): void5{6 $this->artisan('example')7 ->doesntExpectOutput()8 ->assertExitCode(0);9}
expectsOutputToContainとdoesntExpectOutputToContainメソッドは、出力の一部に対してアサーションを行うために使用します。
1test('console command', function () {2 $this->artisan('example')3 ->expectsOutputToContain('Taylor')4 ->assertExitCode(0);5});
1/**2 * Test a console command.3 */4public function test_console_command(): void5{6 $this->artisan('example')7 ->expectsOutputToContain('Taylor')8 ->assertExitCode(0);9}
確認の表明
「yes」か「no」の形式で確認を期待するコマンドを作成する場合、expectsConfirmationメソッドを利用できます。
1$this->artisan('module:import')2 ->expectsConfirmation('Do you really wish to run this command?', 'no')3 ->assertExitCode(1);
テーブルの表明
コマンドがArtisanのtableメソッドを使用して情報のテーブルを表示する場合、テーブル全体に対する出力の表明を記述するのは面倒な場合があります。代わりに、expectsTableメソッドを使用できます。このメソッドは、テーブルのヘッダを最初の引数として、テーブルのデータを2番目の引数として受け入れます。
1$this->artisan('users:all')2 ->expectsTable([3 'ID',4 'Email',5 ], [8 ]);
コンソールイベント
デフォルトでは、アプリケーションのテスト実行中にIlluminate\Console\Events\CommandStartingおよびIlluminate\Console\Events\CommandFinishedイベントはディスパッチされません。ただし、Illuminate\Foundation\Testing\WithConsoleEventsトレイトをクラスに追加することで、特定のテストクラスでこれらのイベントを有効にできます。
1<?php2 3use Illuminate\Foundation\Testing\WithConsoleEvents;4 5uses(WithConsoleEvents::class);6 7// ...
1<?php 2 3namespace Tests\Feature; 4 5use Illuminate\Foundation\Testing\WithConsoleEvents; 6use Tests\TestCase; 7 8class ConsoleEventTest extends TestCase 9{10 use WithConsoleEvents;11 12 // ...13}