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