Laravel学習記録 #024 自動テスト(DBを使ったケース)について学ぶ
Laravelの自動テストについて学習したものをメモ程度にまとめてます。
今回はDBのデータを使って試す編です。
前提として、
以前の記事でやったように、マイグレーションを行わずDBを複製している程でいきます。
DBを使ったテストケース例
メソッドにテストデータ挿入から確認までをまとめる例を考えます。
「インフォメーションテーブルにお知らせが登録されていれば表示する。」
という仕様を例にして作っていきます。
実際のコード
まずは、実際のコードを簡単に作成していきましょう。
□モデル、マイグレーションファイル作成
※テストではマイグレーションファイルなしでやりますが、テーブル作成のためです。
php artisan make:model Info -m
titleとcontentカラムを作ります。
database/migrations/2024_xx_xx_xxxx_create_infos_table.php
public function up()
{
Schema::create('infos', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('content');
$table->timestamps();
});
}
作成したらテストDBをマイグレーションします。
php artisan migrate --env=testing
app/Models/Info.php
class Info extends Model
{
use HasFactory;
protected $fillable = [
'title',
'content'
];
}
□コントローラー作成
Infoコントローラーを作成します。
php artisan make:controller InfoController
登録があればビューに表示するように取得します。
app/Http/Controllers/InfoController.php
class InfoController extends Controller
{
public function index() {
$infos = Info::all();
return view('info', ['infos' => $infos]);
}
}
□ビューを作成
resources/views/info.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Laravel学習記録</title>
</head>
<body>
<p>お知らせ</p>
@foreach ($infos as $info)
<p>{{ $info->title }} | {{ $info->content }}</p>
@endforeach
</body>
</html>
□ルート作成
Route::get('info', [InfoController::class, 'index']);
ここまでで /infoにアクセスするとお知らせがあれば表示される画面ができました。
テストコード作成
本題のテストコードです。
ファイルを作成します。
php artisan make:test InfoControllerTes
tests/Feature/InfoControllerTest.php
登録データがないケース
登録データなしのケースは以下のようにgetメソッドで/infoへアクセスして実行。実行後のステータスコードとinfoビューが返されることを確認しておきます。
public function testIndexWithNoData()
{
// テストデータ用意なし
// リクエスト
$response = $this->get('/info');
// ステータス確認
$response->assertStatus(200);
// infoビューが返されること
$response->assertViewHas('infos');
}esponse->assertViewHas('infos', collect());
}
登録データがあるケース
登録データがあるケースを作成するため、ファクトリーを用意します。
php artisan make:factory InfoFactory
database/factories/InfoFactory.php
タイトルとコンテンツにそれぞれテキストでランダム生成した値をセットします。
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use App\Models\Info;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Info>
*/
class InfoFactory extends Factory
{
protected $model = Info::class;
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition()
{
return [
'title' => $this->faker->realText(10),
'content' => $this->faker->realText(100),
];
}
}
作成したファクトリーを使ってテストケースを用意します。
・1件登録
・複数件登録
どちらも登録したデータがassertViewHasメソッドで値として持っているかを確認しておきます。
public function testIndexWithOneData()
{
// 1件登録
$info = Info::factory(1)->create();
// リクエスト
$response = $this->get('/info');
// ステータス確認
$response->assertStatus(200);
// infoビューが返され,登録したデータが表示されること
$response->assertViewHas('infos', $info);
}
public function testIndexWithMultipleData()
{
// 3件登録
$infos = Info::factory(3)->create();
// リクエスト
$response = $this->get('/info');
// ステータス確認
$response->assertStatus(200);
// infoビューが返されること,登録したデータが表示されること
$response->assertViewHas('infos', $infos);
}
データベースを汚さないように
ここまででテストケースを作成しましたが、実行前にはデータベースを汚さないように設定しておきます。
と言っても、use DatabaseTransactionsを使うだけです。
use Illuminate\Foundation\Testing\DatabaseTransactions;
class InfoControllerTest extends TestCase
{
use DatabaseTransactions;
DatabaseTransactionsを使うことで、テストメソッド内でデータベーストランザクションが開始され、メソッド終了時にロールバックされます。
今回はマイグレーションファイルなしの方針なのでこれを使います。
(マイグレーションファイルあればRefreshDatabaseが使えます。)
ここまでできたらテストを実行
php artisan test
こんな感じでできますね。
この記事が気に入ったらサポートをしてみませんか?