Contents
Laravel DB Test
Factory と Seeder を使って、テストデータの登録を行います。
Factory
Factory はテストデータを簡単に作成できる機能です。
Facker などを使ってデータをセットすることができます。
artisan コマンドで factory を生成します。
1 |
php artisan make:factory SurveyFactory |
model
オプションでモデル名を一緒に設定できます。
1 |
php artisan make:factory SurveyFactory --model=Survey |
Faker
Faker はテストの為のランダムデータを生成できます。
Faker を使用してテストデータをセットします。
1 2 3 4 5 6 7 8 9 10 11 12 |
use Faker\Generator as Faker; use Illuminate\Support\Str; $factory->define(App\User::class, function (Faker $faker) { return [ 'name' => $faker->name, 'email' => $faker->unique()->safeEmail, 'email_verified_at' => now(), 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password 'remember_token' => Str::random(10), ]; }); |
日本語のデータを登録するには locale を変更します。
locale を変更するにはconfig\app.php
を編集します。
1 |
'faker_locale' => 'ja_JP' |
Seeder
Seeder はテストデータをいくつも登録する際に簡単に実行することができます。
Factory でセットしたデータを登録していきます。
作成
artisan コマンドで Seeder クラスを作成します。
1 |
php artisan make:seeder UsersTableSeeder |
10ユーザーを登録するようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
use Illuminate\Database\Seeder; use App\User; class UsersTableSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { factory(App\User::class, 10)->create(); } } |
呼び出し
作成したUsersTableSeeder
を呼び出すようにします。
DatabaseSeeder
クラスのrun
メソッドに追記します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
use Illuminate\Database\Seeder; class DatabaseSeeder extends Seeder { /** * Seed the application's database. * * @return void */ public function run() { $this->call(UsersTableSeeder::class); } } |
リレーションしたデータ登録
ユーザーが投稿した記事へのコメントまでのデータを登録します。
3階層分をデータを登録するようにします。
ユーザー5、1ユーザーの投稿2、1投稿のコメント3を登録します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
use App\Models\Comment; use App\Models\Post; use Illuminate\Database\Seeder; class UsersTableSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { factory(App\User::class, 5)->create()->each(function ($user) { factory(Post::class, 2)->create(['user_id' => $user->id])->each(function ($post) { factory(Comment::class, 3)->create(['post_id' => $post->id]); }); }); } } |
実行
- 事前準備
Seeder クラスを作成したら事前に Composer のオートローダーを再生成します。
dump-autoload
コマンドで実行します。
1 |
composer dump-autoload |
- 一括で実行
DatabaseSeeder
クラスに設定した Seeder を実行します。
1 |
php artisan db:seed |
- 個別に実行
個別に Seeder を実行したい場合はclass
オプションで指定します。
1 |
php artisan db:seed --class=UsersTableSeeder |
- 削除して実行
テーブルを全て消してマイグレーションから実行したい場合はmigrate:fresh
コマンドにseed
オプションをつけて実行します。
1 |
php artisan migrate:fresh --seed |
- 強制実行
production 環境でデプロイ時の自動実行などを行いたい場合などのときにforce
オプションをつけて実行します。
1 |
php artisan db:seed --force |
テスト
ユニットテストやフィーチャーテストが分けられてあります。
原則、ユニットテストでは依存しないテストを行う為PHPUnit\Framework\TestCase
クラス、
フィーチャーテストではフレームワークの機能を使えるように継承したTests\TestCase
クラスを使っていきますが、DBテストを行う為、ユニットテストTests\TestCase
クラスを使っていきます。
ユニットテスト
artisan コマンドでユニットテストのファイルを生成します。
1 |
php artisan make:test --unit UserTest |
フィーチャーテスト
artisan コマンドでフィーチャーテストのファイルを生成します。
1 |
php artisan make:test UserTest |
事前準備
config/database.php ファイルにテスト用DBの設定を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
'connections' => [ 'mysql' => [ 'driver' => 'mysql', 'url' => env('DATABASE_URL'), 'host' => env('DB_HOST', '127.0.0.1'), 'port' => env('DB_PORT', '3306'), 'database' => env('DB_DATABASE', 'forge'), 'username' => env('DB_USERNAME', 'forge'), 'password' => env('DB_PASSWORD', ''), 'unix_socket' => env('DB_SOCKET', ''), 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', 'prefix' => '', 'prefix_indexes' => true, 'strict' => true, 'engine' => null, 'options' => extension_loaded('pdo_mysql') ? array_filter([ PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), ]) : [], ], 'mysql_test' => [ 'driver' => 'mysql', 'url' => env('DATABASE_URL'), 'host' => env('DB_HOST', '127.0.0.1'), 'port' => env('DB_PORT', '3306'), 'database' => env('DB_DATABASE', 'forge'), 'username' => env('DB_USERNAME', 'forge'), 'password' => env('DB_PASSWORD', ''), 'unix_socket' => env('DB_SOCKET', ''), 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', 'prefix' => '', 'prefix_indexes' => true, 'strict' => true, 'engine' => null, 'options' => extension_loaded('pdo_mysql') ? array_filter([ PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), ]) : [], ], ], |
テスト環境として .env.testing ファイルを用意します。
DBをテスト用に修正します。
1 |
DB_DATABASE=test_db |
テストDBのマイグレーションを実行します。
1 |
php artisan migrate --env=testing |
テストDBへ seeder も一緒に実行します。
1 |
php artisan migrate --seed --env=testing |
テストDBのデータ削除を実行します。
1 |
php artisan migrate:refresh --env=testing |
アサーション
いくつかアサートメソッドを見てみます。
- assertDatabaseHas
データが、テーブルに存在することを検証します。
1 2 3 4 |
$user = factory(User::class)->create(); $this->assertDatabaseHas('users', [ 'id' => $user->id ]); |
- assertDatabaseMissing
データが、テーブルに含まれないことを検証します。
1 2 3 4 5 6 7 8 |
$user = factory(User::class)->create(); $this->assertDatabaseHas('users', [ 'id' => $user->id ]); $this->assertDatabaseMissing('users', [ 'id' => ($user->id + 1) ]); |
- assertDeleted
レコードが削除されていることを検証します。
1 2 3 4 5 6 7 8 |
$user = factory(User::class)->create(); $this->assertDatabaseHas('users', [ 'id' => $user->id ]); $user->delete(); $this->assertDeleted($user); |
- assertSoftDeleted
レコードがソフトデリートされていることを検証します。
論理削除の設定を行っておきます。
1 2 3 4 5 6 7 8 |
$user = factory(User::class)->create(); $this->assertDatabaseHas('users', [ 'id' => $user->id ]); $user->delete(); $this->assertSoftDeleted($user); |
- assertTrue / assertFalse
結果がオブジェクトか検証します。
1 2 3 4 5 6 7 8 9 10 |
$user = factory(User::class)->create(); $this->assertDatabaseHas('users', [ 'id' => $user->id ]); Auth::login($user); $this->assertTrue(Auth::check()); Auth::logout($user); $this->assertFalse(Auth::check()); |
- assertSame
hidden されたフィールドが一致するかを検証します。
1 2 3 4 5 6 |
$user = $this->user->find(1); $expected = [ 'id', 'name', 'email', 'email_verified_at', 'created_at', 'updated_at' ]; $this->assertSame($expected, array_keys($user->toArray())); |
データリセット
RefreshDatabase
トレイトを使うことで、テスト後のデータベースをリセットできます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
namespace Tests\Feature; use Illuminate\Foundation\Testing\RefreshDatabase; use Tests\TestCase; class ExampleTest extends TestCase { use RefreshDatabase; public function testDatabase() { // ... } } |
Seeder とデータリセットを使ったテスト
Seeder とデータリセットを使ったテストを行います。
setUp
メソッドで seeder を実行してデータを登録しておきます。
tearDown
メソッドを使ってデータベースをリセットするようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
namespace Tests\Feature; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Support\Facades\Auth; use Tests\TestCase; use App\User; use UsersTableSeeder; class ExampleTest extends TestCase { use RefreshDatabase; public function setUp() { parent::setUp(); $this->seed(UsersTableSeeder::class); $this->user = new User(); } public function tearDown() { Artisan::call('migrate:refresh'); parent::tearDown(); } public function testUserField() { $user = $newUser->find(1); $expected = [ 'id', 'name', 'email', 'email_verified_at', 'created_at', 'updated_at' ]; $this->assertSame($expected, array_keys($user->toArray())); } public function testDeleted() { $user = factory(User::class)->create(); $this->assertDatabaseHas('users', [ 'id' => $user->id ]); $user->delete(); $this->assertDeleted($user); } ... ... } |
実行
全体で実行
1 |
phpunit |
ファイルを指定して実行
1 |
phpunit tests/Unit/UserTest.php |
グループを指定して実行
1 |
phpunit tests/Unit/UserTest.php --group xxxgroup |
参考リンク
Database Testing
Laravel 6.x データベースのテスト
Eloquent: Relationships
Laravel 6.x Eloquent:リレーション
Database: Seeding
Laravel 6.x データベース:シーディング