もがき系プログラマの日常

もがき系エンジニアの勉強したこと、日常のこと、気になっている技術、備忘録などを紹介するブログです。

laravel8のFactoryを使用したテストデータ作成

はじめに

こんばんは。

夜中子供が寝ているときに粛々と仕事と勉強をしております。

表題通りlaravel8でテストデータを作ったのですが、昔やってたlaravelのバージョンとは作り方違ってたので、備忘録として残しておきます。

本番

1. コンフィグの修正

config/app.php を修正して fakerで日本語を使用できるようにします。

'faker_locale' => 'ja_JP',

1. Factory作成

makeコマンド実行

$ php artisan make:factory UserProfileFactory
Factory created successfully.

できたFactoryクラスを以下みたいに修正

<?php

namespace Database\Factories;

use App\Model\UserProfile;
use Illuminate\Database\Eloquent\Factories\Factory;

class UserProfileFactory extends Factory
{
    protected $model = UserProfile::class; // 対象となるModelクラスを指定

    public function definition()
    {
        // return値の値を作成(fakerを使ってダミーデータを作成)
        return [
            'name'        => $this->faker->name,
            'postal_code' => $this->faker->postcode(),
            'prefecture'  => $this->faker->prefecture(),
            'address'     => $this->faker->city() . $this->faker->streetName() . $this->faker-> streetAddress() 
        ];
    }
}

2. Modelに必要なtraitをuseする

makeコマンド実行

php artisan make:model UserProfile
Model created successfully.

作成されたmodelには HasFactory traitがuseされていると思いますが、makeコマンド介さずにmodelクラスを作った場合は以下のように HasFactory traitをuseします。

<?php

namespace App\Model;

use Database\Factories\UserProfileFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory;

class UserProfile extends Model
{
    use HasFactory; // ← 対象のtrait

    protected static function newFactory()
    {
        return UserProfileFactory::new(); // ← 対象のFactoryを指定する
    }
}

3. SeederでFactoryを指定してテストデータを作成する

makeコマンド実行

$ php artisan make:seeder UserProfileSeeder
Seeder created successfully.

できたSeederファイルでFactoryを使用してデータを作成

<?php

namespace Database\Seeders;

use App\Model\UserProfile;
use Illuminate\Database\Seeder;

class UserProfileSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        UserProfile::factory(100)->create(); // これで100件のテストデータが作成できる

        // テストデータの一部 or 全てを上書きしたい場合
        UserProfile::factory()->create([
            'name' => 'あいうえお' // nameだけテストデータではなく 「あいうえお」 にする
        ]);
    }
}

番外編 factoryで使用するfakerに新たなメソッドを生やす

作成したfactoryクラスの親クラスである Illuminate\Database\Eloquent\Factories\Factory に存在している withFaker() をオーバライドして以下のように新たにproviderを作ります。

    protected function withFaker()
    {
        $faker = parent::withFaker();
        $faker->addProvider(new class($faker) extends \Faker\Provider\Base {
            public function ngWord(): string
            {
                return $this->generator->randomElement([
                    'バカ',
                    'アホ',
                    'マヌケ'
                ]);
            }
        });

        return $faker;
    }

これで $this->faker->ngWord() が使えるようになります。

baseクラスを新たに作って生やしてもいいし、 HasFactory trait側のメソッドをオーバライドして対応とか、色々やり方はありそうです。

終わりに

久々にlaravel使っているんですが、テストデータとか作りやすいですね。

現場からは以上です。