CodeIgniterのコントローラテスト手法を徹底解説!初心者向け自動テスト完全ガイド
生徒
「CodeIgniterでWebアプリケーションを作っているのですが、コントローラが正しく動いているか自動で確認するテストの方法がわかりません。」
先生
「PHPのフレームワークであるCodeIgniterには、コントローラの動作を自動でテストするための便利な機能が最初から用意されていますよ。」
生徒
「パソコンの操作やプログラミング自体がまだ初心者なのですが、そんな私でも自動テストのプログラムを書くことはできますか?」
先生
「大丈夫です。画面を実際にクリックしなくても、プログラムが代わりに動いてチェックしてくれる仕組みを、基礎から順番に学んでいきましょう!」
1. コントローラのテストとは何か
CodeIgniterにおけるコントローラとは、ユーザーからのリクエストを受け取り、データベースを操作したり、画面を表示したりする、いわば案内人のような重要な役割を持つプログラムです。この案内人が正しく道案内をしているかどうかを、人間の代わりにコンピューターに自動で検証させる作業をコントローラテスト、または自動テストと呼びます。
通常、プログラムが正しく動くか確認するには、パソコンのブラウザを起動して、文字を入力し、ボタンをクリックするという手作業が必要です。しかし、機能が増えるたびにこの手作業を繰り返すのは非常に大変で、見落としの原因になります。自動テストを導入することで、コマンドをひとつ実行するだけで、何十箇所もの動きを一瞬で正確にチェックできるようになります。
2. 自動テストを行うための準備と設定
CodeIgniterでテストを実行するためには、PHPUnitという世界的に広く使われているテスト用のツールを利用します。難しそうな名前に聞こえますが、CodeIgniterには最初からこのPHPUnitと連携するための仕組みが組み込まれているため、初心者でも少しの設定を行うだけで準備が完了します。
テストを実行する場所は、パソコンの画面ではなく、文字だけで操作を行うコマンドプロンプトやターミナルと呼ばれる黒い画面を使用します。テスト専用の設定ファイルが最初から用意されているため、基本的にはその設定の指示に従ってテスト用のフォルダの中にプログラムを追加していくことになります。これにより、本番の開発環境を汚すことなく、安全に検証を行う環境が整います。
3. 最初に作成する最もシンプルなコントローラの例
まずはテストの対象となる、もっとも簡単なコントローラのプログラムを作成してみましょう。ここでは、アクセスすると画面にシンプルな挨拶の文字を表示するだけのコントローラを用意します。プログラムの書き方や構造に慣れることから始めていきましょう。
このコントローラは、特定のURLにアクセスがあった際に呼び出され、画面に指定した文字列を出力するだけの単純な動きをします。まずはこの動きを基準にして、自動テストがどのように機能するのかを体験していきます。
<?php
namespace App\Controllers;
class WelcomeController extends BaseController
{
public function index()
{
return 'こんにちは、テストの世界へようこそ!';
}
}
4. 最初のコントローラテストコードの書き方
先ほど作成した挨拶を表示するコントローラが、本当に正しく「こんにちは、テストの世界へようこそ!」という文字を返してくるかを検証するテストプログラムを書きます。CodeIgniterでは、コントローラをテストするために専用の機能が提供されています。
テスト用のプログラムでは、特定のURLを擬似的に呼び出し、その結果として返ってきた画面の内容や文字が、自分が予想していた通りのものと一致しているかどうかを比較する命令を記述します。この比較する命令のことを専門用語でアサーションと呼びます。
<?php
namespace App;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\FeatureTestTrait;
class WelcomeControllerTest extends CIUnitTestCase
{
use FeatureTestTrait;
public function testIndexReturnsCorrectGreeting()
{
$result = $this->call('get', 'welcomecontroller/index');
$result->assertSee('こんにちは、テストの世界へようこそ!');
}
}
5. テストを実行して結果を確認する方法
テストのプログラムが書けたら、パソコンのコマンド入力画面を使ってテストを実行します。実行すると、内部でプログラムが高速で動き出し、一瞬で結果を画面に教えてくれます。成功したときと失敗したときの画面の表示の味方を覚えておきましょう。
テストがすべて成功すると、画面には緑色の背景で合格を意味するメッセージが表示されます。もしプログラムの書き間違いや、予想と異なる結果が出た場合は、赤色の背景で不合格のメッセージと、どこの行で何が違っていたのかという原因が詳しく表示されます。これにより、どこを修正すればよいのかがすぐに分かります。
PHPUnit 9.5.0 by Sebastian Bergmann and contributors.
. 1 / 1 (100%)
Time: 00:00.123, Memory: 10.00 MB
OK (1 test, 1 assertion)
6. 条件によって表示が変わるコントローラのテスト
次はもう少し実践的な例として、アクセスする時間帯や入力された値などの条件によって、画面の表示内容が変化するコントローラのテストに挑戦してみましょう。今回は、ユーザーの名前を受け取って、その名前を含んだお祝いのメッセージを画面に表示するコントローラを作ります。
このように外部からデータを受け取る仕組みがある場合、何もデータを受け取れなかったときの動きや、おかしなデータが送られてきたときの動きなども想定して、複数のパターンのテストを用意することが、信頼性の高いアプリケーション作りに繋がります。
<?php
namespace App\Controllers;
class ProfileController extends BaseController
{
public function greet($name = 'ゲスト')
{
return 'ようこそ、' . $name . '様!ご訪問ありがとうございます。';
}
}
7. データを送信する複雑なテストケースの書き方
先ほどの名前を受け取るコントローラに対して、実際にデータを送信しながらテストを行うプログラムを記述します。テストコードの中で擬似的にデータを組み立ててコントローラに渡す方法を学びましょう。
今回は、名前として「鈴木」という文字を送信した場合に、画面に「ようこそ、鈴木様!」という正しい文章が含まれているかどうかを検証します。データを変えて何度もテストを行うことで、プログラムがどんな入力に対しても頑丈に作られているかを確認できます。
<?php
namespace App;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\FeatureTestTrait;
class ProfileControllerTest extends CIUnitTestCase
{
use FeatureTestTrait;
public function testGreetWithCustomName()
{
$result = $this->call('get', 'profilecontroller/greet/鈴木');
$result->assertSee('ようこそ、鈴木様!ご訪問ありがとうございます。');
}
public function testGreetWithDefaultName()
{
$result = $this->call('get', 'profilecontroller/greet');
$result->assertSee('ようこそ、ゲスト様!ご訪問ありがとうございます。');
}
}
8. エラー画面やステータスコードを検証する手法
自動テストでは、画面に表示される文字だけでなく、Webサーバーが返すステータスコードと呼ばれる隠れた数字のチェックも行います。ステータスコードとは、通信が成功したか失敗したかを表す3桁の数字のことです。
例えば、ページが無事に見つかって通信が成功したときは「200」、ページが存在しないエラーのときは「404」という数字が返されます。この数字をテストすることで、おかしなURLにアクセスされたときに、コントローラが正しくエラー画面を表示して処理を拒否できているかどうかを、確実に確認することができます。
<?php
namespace App;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\FeatureTestTrait;
class StatusCheckTest extends CIUnitTestCase
{
use FeatureTestTrait;
public function testNormalPageResponse()
{
$result = $this->call('get', 'welcomecontroller/index');
$result->assertStatus(200);
}
public function testMissingPageResponse()
{
$result = $this->call('get', 'nonexistentcontroller/index');
$result->assertStatus(404);
}
}