This documentation is currently being translated. Some pages may appear in Korean.
Skip to main content
Version: 13.x

데이터베이스 테스트 (Database Testing)

소개 (Introduction)

Laravel은 데이터베이스 기반 애플리케이션을 더 쉽게 테스트할 수 있도록 다양한 유용한 도구와 어서션을 제공합니다. 또한 Laravel 모델 팩토리와 시더를 사용하면 애플리케이션의 Eloquent 모델과 연관관계를 이용해 테스트용 데이터베이스 레코드를 손쉽게 만들 수 있습니다. 이어지는 문서에서는 이러한 강력한 기능들을 모두 살펴보겠습니다.

각 테스트 후 데이터베이스 재설정

더 진행하기 전에, 이전 테스트의 데이터가 이후 테스트에 영향을 주지 않도록 각 테스트 후 데이터베이스를 재설정하는 방법을 살펴보겠습니다. Laravel에 포함된 Illuminate\Foundation\Testing\RefreshDatabase trait가 이 작업을 처리해 줍니다. 테스트 클래스에서 이 trait를 사용하기만 하면 됩니다.

<?php

use Illuminate\Foundation\Testing\RefreshDatabase;

pest()->use(RefreshDatabase::class);

test('basic example', function () {
$response = $this->get('/');

// ...
});
<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class ExampleTest extends TestCase
{
use RefreshDatabase;

/**
* A basic functional test example.
*/
public function test_basic_example(): void
{
$response = $this->get('/');

// ...
}
}

Illuminate\Foundation\Testing\RefreshDatabase trait는 스키마가 최신 상태라면 데이터베이스 마이그레이션을 실행하지 않습니다. 대신 테스트를 데이터베이스 트랜잭션 안에서만 실행합니다. 따라서 이 trait를 사용하지 않는 테스트 케이스가 데이터베이스에 추가한 레코드는 여전히 데이터베이스에 남아 있을 수 있습니다.

데이터베이스를 완전히 재설정하고 싶다면 대신 Illuminate\Foundation\Testing\DatabaseMigrations 또는 Illuminate\Foundation\Testing\DatabaseTruncation trait를 사용할 수 있습니다. 하지만 두 옵션 모두 RefreshDatabase trait보다 훨씬 느립니다.

모델 팩토리 (Model Factories)

테스트를 실행하기 전에 데이터베이스에 몇 개의 레코드를 삽입해야 할 수 있습니다. 이러한 테스트 데이터를 만들 때 각 컬럼의 값을 직접 지정하는 대신, Laravel에서는 모델 팩토리를 사용하여 각 Eloquent 모델에 대한 기본 속성 집합을 정의할 수 있습니다.

모델 팩토리를 만들고 이를 활용해 모델을 생성하는 방법을 더 자세히 알아보려면 전체 모델 팩토리 문서를 참고하시기 바랍니다. 모델 팩토리를 정의한 뒤에는 테스트 안에서 팩토리를 사용해 모델을 생성할 수 있습니다.

use App\Models\User;

test('models can be instantiated', function () {
$user = User::factory()->create();

// ...
});
use App\Models\User;

public function test_models_can_be_instantiated(): void
{
$user = User::factory()->create();

// ...
}

시더 실행 (Running Seeders)

기능 테스트 중에 데이터베이스 시더를 사용해 데이터베이스를 채우고 싶다면 seed 메서드를 호출할 수 있습니다. 기본적으로 seed 메서드는 DatabaseSeeder를 실행하며, 이 시더는 다른 모든 시더를 실행해야 합니다. 또는 특정 시더 클래스명을 seed 메서드에 전달할 수 있습니다.

<?php

use Database\Seeders\OrderStatusSeeder;
use Database\Seeders\TransactionStatusSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;

pest()->use(RefreshDatabase::class);

test('orders can be created', function () {
// Run the DatabaseSeeder...
$this->seed();

// Run a specific seeder...
$this->seed(OrderStatusSeeder::class);

// ...

// Run an array of specific seeders...
$this->seed([
OrderStatusSeeder::class,
TransactionStatusSeeder::class,
// ...
]);
});
<?php

namespace Tests\Feature;

use Database\Seeders\OrderStatusSeeder;
use Database\Seeders\TransactionStatusSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class ExampleTest extends TestCase
{
use RefreshDatabase;

/**
* Test creating a new order.
*/
public function test_orders_can_be_created(): void
{
// Run the DatabaseSeeder...
$this->seed();

// Run a specific seeder...
$this->seed(OrderStatusSeeder::class);

// ...

// Run an array of specific seeders...
$this->seed([
OrderStatusSeeder::class,
TransactionStatusSeeder::class,
// ...
]);
}
}

또는 RefreshDatabase trait를 사용하는 각 테스트 전에 Laravel이 데이터베이스를 자동으로 시딩하도록 지시할 수 있습니다. 기본 테스트 클래스에 Seed 속성을 추가하면 됩니다.

<?php

namespace Tests;

use Illuminate\Foundation\Testing\Attributes\Seed;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;

#[Seed]
abstract class TestCase extends BaseTestCase
{
}

Seed 속성이 있으면 테스트는 RefreshDatabase trait를 사용하는 각 테스트 전에 Database\Seeders\DatabaseSeeder 클래스를 실행합니다. 하지만 테스트 클래스에 Seeder 속성을 사용하여 실행할 특정 시더를 지정할 수도 있습니다.

<?php

namespace Tests\Feature;

use Database\Seeders\OrderStatusSeeder;
use Illuminate\Foundation\Testing\Attributes\Seeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

#[Seeder(OrderStatusSeeder::class)]
class OrderTest extends TestCase
{
use RefreshDatabase;

// ...
}

사용 가능한 어서션 (Available Assertions)

Laravel은 Pest 또는 PHPUnit 기능 테스트를 위한 여러 데이터베이스 어서션을 제공합니다. 아래에서 각 어서션을 살펴보겠습니다.

assertDatabaseCount

데이터베이스의 테이블에 지정한 수의 레코드가 포함되어 있는지 검증합니다.

$this->assertDatabaseCount('users', 5);

assertDatabaseEmpty

데이터베이스의 테이블에 레코드가 없는지 검증합니다.

$this->assertDatabaseEmpty('users');

assertDatabaseHas

데이터베이스의 테이블에 주어진 키 / 값 쿼리 제약 조건과 일치하는 레코드가 포함되어 있는지 검증합니다.

$this->assertDatabaseHas('users', [
'email' => '[email protected]',
]);

assertDatabaseMissing

데이터베이스의 테이블에 주어진 키 / 값 쿼리 제약 조건과 일치하는 레코드가 포함되어 있지 않은지 검증합니다.

$this->assertDatabaseMissing('users', [
'email' => '[email protected]',
]);

assertSoftDeleted

assertSoftDeleted 메서드는 주어진 Eloquent 모델이 "소프트 삭제"되었는지 검증하는 데 사용할 수 있습니다.

$this->assertSoftDeleted($user);

assertNotSoftDeleted

assertNotSoftDeleted 메서드는 주어진 Eloquent 모델이 "소프트 삭제"되지 않았는지 검증하는 데 사용할 수 있습니다.

$this->assertNotSoftDeleted($user);

assertModelExists

주어진 모델 또는 모델 컬렉션이 데이터베이스에 존재하는지 검증합니다.

use App\Models\User;

$user = User::factory()->create();

$this->assertModelExists($user);

assertModelMissing

주어진 모델 또는 모델 컬렉션이 데이터베이스에 존재하지 않는지 검증합니다.

use App\Models\User;

$user = User::factory()->create();

$user->delete();

$this->assertModelMissing($user);

expectsDatabaseQueryCount

expectsDatabaseQueryCount 메서드는 테스트 시작 부분에서 호출하여 테스트 중 실행될 것으로 예상하는 데이터베이스 쿼리의 총 개수를 지정할 수 있습니다. 실제 실행된 쿼리 수가 이 예상과 정확히 일치하지 않으면 테스트는 실패합니다.

$this->expectsDatabaseQueryCount(5);

// Test...