/
라라벨 8 model factory 로 test data 만들기

라라벨 8 model factory 로 test data 만들기

개요

개발 프로젝트를 진행하다 보면 DB 설계 검증, 화면 기획 및 paging test 등의 용도로 테스트 데이타가 필요합니다.

꽤 중요한 기능이지만 테스트 데이타를 만들기 위해 바쁜 시간을 쪼개서 test data 를 만들기는 쉽지 않습니다.


라라벨 모델 팩토리는 의미 있는 테스트 데이타를 만들어 주는 PHP 라이브러리인 fakerphp 를 프레임워크에 연동하여 손쉽게 DB seeding 및 테스트 데이타를 만들수 있는 기능입니다.


laravel 8 부터는 Model Factory 기능이 대폭 변경되었으며 기본적인  사용 방법은 예제인 database/factories/UserFactory.php 에서 볼 수 있습니다.

 Click here to expand...
namespace Database\Factories;

use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;

class UserFactory extends Factory
{
    /**
     * The name of the factory's corresponding model.
     *
     * @var string
     */
    protected $model = User::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'name' => $this->faker->name(),
            'email' => $this->faker->unique()->safeEmail(),
            'email_verified_at' => now(),
            'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
            'remember_token' => Str::random(10),
        ];
    }
}

$model property 에 Eloquent model 클래스를 정의하며 definition() 메서드에 만들 model factory 를 지정합니다.

Model Factory 사용

팩토리 생성

artisan 명령어로 사용할 모델 팩토리를 만들 수 있습니다.

php artisan make:factory PostFactory --model Post


database/factories/PostFactory.php 의 definition() 메서드에 다음과 같이 생성할 데이타의 타입에 맞는 지정하면 됩니다.

database/factories/ModelFactory.php
class PostFactory extends Factory
{
    /**
     * The name of the factory's corresponding model.
     *
     * @var string
     */
    protected $model = Post::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'author_id' => User::all()->pluck('id')->random(),
            'title' => $this->faker->realText(30),
            'content' => $this->faker->realText(),
            'created_at' => $this->faker->dateTimeBetween('-2 years', 'now'),
        ];
    }
}


factory 사용

factory 메서드를 사용하여 faker 를 호출할 수 있으며 간단하게 tinker 에서 테스트 할 수 있습니다.

데이타 생성

make() 를 사용하면 테스트 데이타를 만들 수 있습니다.

\App\Models\Post::factory()
                ->make();


갯수 지정

count() 메소드를 호출해서 데이타의 갯수를 지정할 수 있습니다.

>>> \App\Models\Post::factory()
  				->count(37)
                ->make(); 

Persistence 데이타 생성

make() 는 임시 데이타만 생성하므로 DB 에 입력하려면 create() 를 사용하면 됩니다.

>>> \App\Models\Post::factory()
  				->count(37)
                ->create();

생성된 데이타는 DBMS 에서 직접 확인할 수 있습니다.

속성 오버라이딩

저자와 책의 정보를 담고 있는 Author와 Book 모델이 있을 경우 Model 의 관계는 다음과 같이 Author 는 여러 개의 Book 을 가질 수 있습니다.


Book 모델 팩토리를 생성할 경우 참조되는 Author 정보가 있어야 합니다. 참조하는 모델 팩토리에서는 다음과 같이 $factory->create() 구문으로 참조되는 모델의 primary key 를 만들 수 있습니다.



또는 아래와 같이 부모 테이블의 id 의 최소/최대 값을 얻어와서 numberBetween($min, $max) 메소드로 구간내의 임의의 값을 설정할 수 있습니다.

$factory->define(App\Book::class, function ($faker) use($factory){
	// 최대값과 최소값 가져오기
	$max = App\Author::max('id');
    $min = App\Author::min('id');
    return [
        'name' => $faker->text,
		// Author id 참조
        'author_id' =>  $faker->numberBetween($min, $max),
        'created_at' => $faker->dateTimeBetween($startDate = '-2 years', $endDate = '-1 years'),
        'updated_at' => $faker->dateTimeBetween($startDate = '-1 years', $endDate = 'now'),
    ];
});

state 사용

state 를 사용하면 Model 의 특별한 상태를 지정해서 생성할 수 있습니다. 만약 Book 모델에 베스트 셀러 여부를 나타내는 is_bestseller 와 주목받는 책임을 나타내는 is_featured 필드가 있다고 가정해 봅시다.


그리고 Model Factory 에 다음과 같이 Model state 를 정의합니다.

$factory->state(App\Book::class, 'bestseller', function() {
    return [
        'is_bestseller' => true,
    ];
});
 
$factory->state(App\Book::class, 'featured', function() {
    return [
        'is_featured' => true,
    ];
});


이제 best seller 인 책을 등록할 경우 아래와 같이 실행하면 is_bestseller 가 true 로 설정됩니다.

factory(\App\Book::class)->states('bestseller')->create();


주목받는 책은 featured state 를 지정해 주면 됩니다.

factory(\App\Book::class)->states('featured')->create();

 동시에 여러 개의 state 를 지정할 경우 파라미터로 구분해서 사용하면 되고 아래는 베스트셀러와 주목받는 책 2가지 state 를 설정합니다.

factory(\App\Book::class)->states('bestseller', 'featured')->create();


factory 에 parameter 전달

TODO

factory 생성시 외부에서 필요한 파라미터를 생성해서 전달할 수 있습니다.  예로 책을 등록할 때 저자 정보를 밖에서 설정해서 입력하고 싶을수 있습니다.

이럴 경우 createmake 메서드에 배열로 전달하려는 파라미터를 key, value 형식으로 입력하면 됩니다.

예로 다음 코드는 author_id => 1 이라는 파라미터를 전달합니다.


사용하는 factory 에서는 다음과 같이 클로저에 array 형식의 parameter 를 기술하고 array 의 값을 확인해서 사용하면 됩니다.

factory parameter
$factory->define(\App\Book::class, function (Faker $faker, array $param) {
   
    return [
		// 저자 정보 외부 입력값 사용
        'author_id' => $param['author_id'] ?? null,
        'title' => $faker->realText(20),
        'comment' => $faker->realText,
    ];
});


Database:Seeding 에서 사용

artisan db:seed 명령어에서도 factory 를 사용할 수 있습니다.

먼저 seed 클래스를 생성합니다.

$ php artisan make:seeder AuthorTableSeeder
Seeder created successfully.


database/seeds/AuthorTableSeeder.php  파일을 수정합니다.

TODO


seed 를 적용합니다.

$ php artisan db:seed


PHPUnit 이나 Controller에서 사용


TODO


Data formatter

TODO


기본 locale 설정하기

Laravel Factory 기본 locale 변경해서 사용하기 참고


같이 보기


Ref


Related content

PHP Faker 프로젝트 중단 및 오픈소스 프로젝트에 대한 단상
PHP Faker 프로젝트 중단 및 오픈소스 프로젝트에 대한 단상
More like this
phpunit 단위 테스트 건너뛰기(skipping tests)
phpunit 단위 테스트 건너뛰기(skipping tests)
More like this
laravel test 하기
laravel test 하기
More like this
PHPUnit test case dependency
PHPUnit test case dependency
More like this
phpunit 설치 및 php 단위 테스트 하기
phpunit 설치 및 php 단위 테스트 하기
More like this
Atlassian 의 새로운 개발 플랫폼 forge #1
Atlassian 의 새로운 개발 플랫폼 forge #1
More like this