さて、本題に入ります。
今回はLaravelとPHPUnitでControllerのテストケースを紹介したいと思います。
皆さんはアプリケーション開発時、どのような手法でテストを実施しているでしょうか?
Selenium等で自動テストを実施などがあると思いますが、手作業で実施しているケースもあったりするのではないでしょうか。
そのような環境にも導入しやすいテストケースから考えていきたいと思います。
環境
・PHP 8.1.9
・Laravel Framework 9.25.1
・PHPUnit 9.5.21
テストケース(成功例)
Controller概要
例として、次のようなControllerを作成しました。
・DBからInformationのレコードを取得する。
・ViewにInformationの数をセットする。
・画面タイトルとInformationの数を出力したViewを返す。
ソースコードは下記です。
// app\Http\Controllers\InformationController.php
namespace App\Http\Controllers;use App\Models\Information;
use Illuminate\View\View;
class InformationController extends Controller
{
public function getIndex(): View
{
$information = Information::orderBy('created_at')->limit(10)->get();
return view('information.index', ['information_count' => $information->count()]);
}
}
// resources\views\information\index.blade.php
Information Count
count: {{ $count }}
上記を実行すると画面には下記のように表示されます。
Information Count
count: 9
// tests\Feature\InformationControllerTest.php
namespace Tests\Feature;
use Tests\TestCase;
class InformationControllerTest extends TestCase
{
/**
* @test
*/
public function getIndex()
{
$response = $this->get(route('information.index'));
$response->assertOk();
$response->assertViewIs('information.index');
$response->assertViewHas(['count' => 10]);
$response->assertSeeText('Information');
$response->assertSeeText('count: 10');
}
}
実行と結果
上記のテストケースを実行します。
# vendor/bin/phpunit
下記のように表示されれば、テスト成功です。
テストケース説明
// まず、テスト対象ページを取得します。
$response = $this->get(route('information.index'));
// ページに正常にアクセス出来ることをテストします。
// HTTPステータスコード200が返ってきていることを確認します。
$response->assertOk();
// 指定のViewを読み込んでいることをテストします。
$response->assertViewIs('information.index');
// View変数をセットしているかテストします。
$response->assertViewHas(['count' => 10]);
// ページの中に指定の文字列が存在するかテストします。
$response->assertSeeText('Information');
$response->assertSeeText('count: 10');
ここまでで、Controllerとそれに対するテストケースの実装が出来ました。
次に、このテストケースを使って不具合を発見する例を書きたいと思います。
作り終わってから修正が全く入らないプログラムは少なく、殆どの場合、後から何らかの追加修正や不具合修正が入ると思います。
既に作成済みのプログラムが正常に動くことを注意しつつ、修正を行うことは多いのではないでしょうか。
このような場合、上記で作成したテストケースが役に立ちます。
テストケース(失敗例)
次に不具合を検知する例を書きたいと思います。
先ほどのControllerを一部変更しました。
limit(10)がlimit(9)になっています。
// app\Http\Controllers\InformationController.php
class InformationController extends Controller
{
public function getIndex(): View
{
// limit(9)に修正しました。
$information = Information::orderBy('created_at')->limit(9)->get();
return view('information.index', ['information_count' => $information->count()]);
}
}
実行と結果
このような状態でテストケースを実行すると、下記の結果になります。
行番号が表示されているので、下記のテストケースが失敗したことがわかります。
$response->assertViewHas(['count' => 10]);
最後に
今回はLaravelのControllerに対して、基本的なテストを書いてみました。
PHPUnitはLaravelに限らずPHPで製造したアプリケーションであれば、ほぼ導入可能かと思います。
テストケースを書くことで不具合修正やリファクタリング時に発生した不具合を検知しやすくなります。
実際のアプリケーションはController以外の要素も登場しますが、それらに対するテスト方法も存在します。(Model、Routing、認証など)
次回からは、Controller以外のテストや、テスト観点(テストケースの考え方)などを紹介していきたいと思います。
ロジカルスタジオではエンジニアを募集しています。
今回使ったLaravelやPHPUnitなど、バックエンド技術を使って開発がしてみたいという方は、是非以下よりご応募ください!