우아한 PHP Test Framework Pest - #2 Test 작성
PHPStorm 이나 VSCode 용 Pest plugin 을 설치하세요.
Pest 는 단위 테스트를 간략하게 작성할 수 있도록 도와주며 laravel 의 test 폴더 구조에 맞게 Unit 과 Feature 에 있는 Test.php 로 끝나는 모든 클래스를 자동으로 실행합니다.
tests
- Unit
- ComponentTest.php -- 유닛 테스트 클래스
- Feature
- HomeTest.php -- 피처 테스트 클래스
Pest.php -- Pest 부트스트랩
phpunit.xml
이제 실제 테스트 케이스 작성을 위해 다음 artisan 명령으로 테스트 클래스를 생성합니다.
Unit Test class 생성
$ php artisan make:test ComponentTest --unit
Feature Test class 생성
$ php artisan make:test HomeTest
Pest 를 사용하면 기존의 TestCase 를 상속받지 않고 다음과 같이 test() 나 it() 메서드로 간략하게 테스트를 작성할 수 있습니다.
HomeTest.php
<?php
test('has home', function () {
$this->assertTrue(true);
});
// 또는
it('has home', function () {
$this->assertTrue(true);
});
테스트 함수 작성 - test() 와 it()
test() 함수의 첫 번째 파라미터는 test 에 대한 설명, 2번째는 클로저입니다.
<?php
function test(string $description = null, Closure $closure = null)
{
it() 도 마찬가지이며 차이점은 $description 앞에 "it" 이라는 단어를 추가해서 실행한다는 점입니다.
<?php
function it(string $description = null, Closure $closure = null)
{
HomeTest.php
<?php
test('has home', function () {
$this->assertTrue(true);
});
// 또는
it('has home', function () {
$this->assertTrue(true);
});
HomeTest.php 에 작성한 테스트를 실행하면 다음과 같은 결과를 표시하며 it() 의 경우 description 에 it 이라는 문자열을 추가한 것을 확인할 수 있습니다.
./vendor/bin/pest
테스트 케이스에 바인딩 - uses()
테스트 케이스에서 특정 클래스나 trait 이 필요할 수 있습니다. 예로 Database 테스트가 끝난 후에 RefreshDatabase trait 을 사용해서 테스트 데이타를 지워야 합니다.
이럴 경우 클래스나 trait 을 현재 테스트 케이스에 바인딩 해주는 uses() 함수를 사용하면 됩니다.
HomeTest.php
<?php
use App\Models\User;
use \Illuminate\Foundation\Testing\WithFaker;
use \Illuminate\Foundation\Testing\RefreshDatabase;
// 테스크 케이스에 trait 바인딩
uses(WithFaker::class);
uses(RefreshDatabase::class);
test('has user', function () {
$faker = $this->faker('ko_KR');
$u = User::create([
'name' => $faker->name,
'email' => $faker->email,
'password' => bcrypt('secret'),
]);
$this->assertDatabaseHas('users', [
'email' => $u->email,
]);
});
이제 pest 를 실행하면 단위 테스트를 실행하고 테스트 데이타를 삭제한 것을 확인할 수 있습니다.
./vendor/bin/pest
PASS Tests\Unit\ComponentTest
✓ example
PASS Tests\Unit\ExampleTest
✓ basic test
PASS Tests\Feature\ExampleTest
✓ basic test
PASS Tests\Feature\HomeTest
✓ has user
Tests: 4 passed
Time: 1.16s
하위 폴더에도 바인딩 - in()
RefreshDatabase 처럼 여러 테스트 케이스에서 사용할 trait 을 매번 지정하는 건 번거로운 일입니다. 이런 불편을 해결하려면 Pest 의 Boot strap 파일인 Pest.php 에 uses() 함수를 옮기면 됩니다.
Pest.php
<?php
uses(Tests\TestCase::class)->in('Feature');
// 테스크 케이스에 trait 바인딩
uses(\Illuminate\Foundation\Testing\WithFaker::class);
uses(\Illuminate\Foundation\Testing\RefreshDatabase::class);
HomeTest.php
<?php
use App\Models\User;
test('has user', function () {
$faker = $this->faker('ko_KR');
$u = User::create([
'name' => $faker->name,
'email' => $faker->email,
'password' => bcrypt('secret'),
]);
$this->assertDatabaseHas('users', [
'email' => $u->email,
]);
});
이제 Pest 를 실행하면 다음과 같이 에러가 발생합니다.
./vendor/bin/pest
이는 Feature 는 하위 폴더이므로 uses() 로 바인딩해도 영향을 주지 않아서이며 in() 함수로 하위 폴더까지 바인딩하도록 선언해야 합니다.
Pest.php 를 아래와 같이 in() 을 호출하도록 수정하고 다시 실행하면 정상 동작하는 것을 확인할 수 있습니다.
Pest.php
<?php
uses(Tests\TestCase::class)->in('Feature');
// 테스크 케이스에 trait 바인딩
uses(\Illuminate\Foundation\Testing\WithFaker::class)->in('Feature');
uses(\Illuminate\Foundation\Testing\RefreshDatabase::class)->in('Feature');
만약 Unit 하위 폴더에도 바인딩할 경우 in() 을 별도로 호출해 주면 됩니다.
Pest.php
<?php
uses(Tests\TestCase::class)->in('Feature');
// 테스크 케이스에 trait 바인딩
uses(\Illuminate\Foundation\Testing\WithFaker::class)->in('Feature');
uses(\Illuminate\Foundation\Testing\WithFaker::class)->in('Unit');
uses(\Illuminate\Foundation\Testing\RefreshDatabase::class)->in('Feature');
uses(\Illuminate\Foundation\Testing\RefreshDatabase::class)->in('Unit');
또는 uses() 의 첫 번째 함수에 바인딩할 trait 이름을 배열로 넘기면 더 깔끔하게 작성할 수 있습니다.
Pest.php
<?php
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
uses(Tests\TestCase::class)->in('Feature');
// 테스크 케이스에 trait 바인딩
uses(WithFaker::class, RefreshDatabase::class)->in('Feature');
uses(WithFaker::class, RefreshDatabase::class)->in('Unit');