제2.8장: API 테스트
학습 시간: 1시간
1. 왜 테스트가 필요한가요?
우주선을 만들었다고 상상해 보세요. 화성으로 보내기 전에 지구에서 수천 번의 검사를 수행합니다. 프로그래밍에서의 테스트도 마찬가지입니다. 테스트는:
- 자신감을 줍니다: 코드를 변경할 수 있으며, 테스트가 통과하면 아무것도 손상시키지 않았다는 의미입니다.
- 시간을 절약합니다: 변경할 때마다 Postman에서 모든 것을 수동으로 "클릭"하는 대신, 단일 명령을 실행하면 몇 초 만에 모든 것을 검사합니다.
- 문서 역할을 합니다: 좋은 테스트는 API가 어떻게 작동해야 하는지 보여줍니다.
2. 테스트 "실험실" 설정
Laravel은 테스트 설정을 놀라울 정도로 간단하게 만듭니다. 기본적으로 주 데이터베이스에 영향을 주지 않도록 별도의 구성을 사용합니다.
테스트용 데이터베이스:
기본적으로 Laravel은 메모리 내 데이터베이스(:memory:
)를 사용합니다. 디스크에 아무것도 쓸 필요가 없기 때문에 가장 빠른 방법입니다. 데이터베이스는 테스트 전에 생성되고 테스트 후에 파괴됩니다. 이를 위해 아무것도 설정할 필요조차 없습니다!
테스트 파일 생성: 행성과 관련된 테스트를 위한 특별한 파일을 만들어 봅시다.
이 명령은 tests/Feature/PlanetApiTest.php
파일을 생성합니다. Feature
라는 단어는 우리가 전체 기능(예: "사용자가 행성을 생성할 수 있는가?")을 테스트하고, 개별적인 작은 클래스를 테스트하는 것이 아님을 의미합니다.
3. 테스트의 해부학: 준비, 실행, 검증
tests/Feature/PlanetApiTest.php
를 엽니다. 그 안에 첫 번째 테스트를 작성할 것입니다. 좋은 테스트는 항상 세 부분(Arrange, Act, Assert)으로 구성됩니다.
<?php
namespace Tests\Feature;
use App\Models\Planet; // 모델을 임포트하는 것을 잊지 마세요
use Illuminate\Foundation\Testing\RefreshDatabase; // 가장 중요한 도구!
use Tests\TestCase;
class PlanetApiTest extends TestCase
{
// 이 트레이트는 "마법처럼"
// 각 테스트 전에 테스트 데이터베이스를 정리하고 다시 생성합니다.
// 이는 테스트들이 서로 영향을 주지 않도록 보장합니다.
use RefreshDatabase;
/**
* 테스트: 행성 목록을 가져오는 엔드포인트가 올바르게 작동합니다.
* 테스트 이름은 의미가 있어야 합니다!
*/
public function test_can_get_all_planets(): void
{
// 1. 준비 (Arrange)
// 테스트 데이터베이스에 가짜 행성 3개를 생성합니다
// 이전에 생성한 팩토리를 사용하여.
Planet::factory()->count(3)->create();
// 2. 실행 (Act)
// API에 실제 GET 요청을 시뮬레이션합니다.
$response = $this->getJson('/api/planets');
// 3. 검증 (Assert)
// 모든 것이 제대로 되었는지 확인합니다.
$response->assertStatus(200); // 서버가 "200 OK"로 응답했는지 확인합니다
$response->assertJsonCount(3); // 응답에 정확히 3개의 행성이 있는지 확인합니다
}
}
use RefreshDatabase
: 이 트레이트는 당신의 가장 친한 친구입니다. 각 테스트가 "깨끗한 상태" 즉, 비어있는 데이터베이스로 시작하도록 보장합니다.Planet::factory()
: 팩토리는 테스트 데이터를 생성하는 데 이상적입니다.$this->getJson()
: 이것은 테스트 내에서 API 요청을 보내기 위한 Laravel의 특별한 메서드입니다.assert...()
: 이것은 "어설션" 또는 "검증"입니다. 이들 중 하나라도 실패하면 테스트는 통과하지 못합니다.
4. 주요 작업 (CRUD) 테스트
행성을 생성, 업데이트 및 삭제하는 테스트를 작성해 봅시다.
A. 행성 생성 테스트 (POST)
<?php
public function test_can_create_a_planet(): void
{
// 1. 준비: 새 행성 데이터를 준비합니다
$planetData = [
'name' => 'Kepler-186f',
'description' => 'Первая экзопланета размером с Землю в обитаемой зоне.',
'size_km' => 14000,
'solar_system' => 'Kepler-186'
];
// 2. 실행: 데이터와 함께 POST 요청을 보냅니다
$response = $this->postJson('/api/planets', $planetData);
// 3. 검증
$response->assertStatus(201); // "201 Created" 상태를 예상합니다
$response->assertJsonFragment(['name' => 'Kepler-186f']); // 응답에 생성된 이름이 있는지 확인합니다
// 가장 중요한 검증: 데이터가 실제로 데이터베이스에 들어갔는가?
$this->assertDatabaseHas('planets', [
'name' => 'Kepler-186f'
]);
}
B. 행성 삭제 테스트 (DELETE)
<?php
public function test_can_delete_a_planet(): void
{
// 1. 준비: 삭제할 행성을 생성합니다
$planet = Planet::factory()->create();
// 2. 실행: DELETE 요청을 보냅니다
$response = $this->deleteJson("/api/planets/{$planet->id}");
// 3. 검증
$response->assertStatus(204); // "204 No Content"를 예상합니다 - 성공적인 삭제
// 레코드가 데이터베이스에서 실제로 사라졌는지 확인합니다
$this->assertDatabaseMissing('planets', [
'id' => $planet->id
]);
}
5. "잘못된" 시나리오 테스트
성공적인 경우를 테스트하는 것은 좋습니다. 하지만 오류를 테스트하는 것이 훨씬 더 중요합니다!
A. 유효성 검사 오류 테스트
<?php
public function test_creation_fails_with_invalid_data(): void
{
// 2. 실행: 의도적으로 잘못된 데이터를 보냅니다
$response = $this->postJson('/api/planets', ['name' => '']); // 빈 이름
// 3. 검증
$response->assertStatus(422); // "422 Unprocessable Entity"를 예상합니다
$response->assertJsonValidationErrors('name'); // 'name' 필드에 오류가 있을 것으로 예상합니다
}
B. "찾을 수 없음" (404) 테스트
<?php
public function test_returns_404_for_non_existent_planet(): void
{
// 2. 실행: 존재하지 않는 ID로 행성을 요청합니다
$response = $this->getJson('/api/planets/99999');
// 3. 검증
$response->assertStatus(404); // "404 Not Found"를 예상합니다
}
6. 테스트 실행
이제 테스트가 작성되었으니, 실행하는 것은 매우 간단합니다. 터미널에서 다음을 실행하세요:
Laravel은 모든 테스트를 찾아 하나씩 실행합니다. 모든 것이 성공적으로 통과하면 녹색 출력을 볼 수 있습니다. 어떤 테스트라도 실패하면 오류에 대한 자세한 설명과 함께 빨간색 출력이 표시되어 신속하게 수정할 수 있습니다.
특정 파일 하나만 실행하려면:
8. 코드 커버리지 (Code Coverage)
단계 1: Xdebug 설치
코드 커버리지 정보를 수집하려면 PHP 확장인 Xdebug가 필요합니다.
wizard에
php -i
결과를 보내고 지침을 따르세요.
단계 2: phpunit.xml
설정
<phpunit ... >
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">./app</directory>
</include>
</coverage>
</phpunit>
단계 3: 보고서와 함께 실행
보고서: 브라우저에서coverage/index.html
을 엽니다
9. Postman과의 통합
Newman을 통한 자동화:
- Postman 컬렉션을
tests/Postman/SpaceApi.postman_collection.json
으로 내보냅니다 - Newman 설치:
composer.json
에 스크립트 추가:- 실행:
개념 확립을 위한 퀴즈
🚀 장 요약:
사전 비행 테스트의 전체 주기를 완료했습니다! 이제 귀하의 API는 다음을 수행합니다:
- ✅ 손쉽게 테스트 환경 설정
- 🛡️ "준비-실행-검증" 원칙에 따라 테스트 작성.
- 📊 성공적인 시나리오(CRUD)와 오류(유효성 검사, 404)를 모두 테스트.
- 🔁 단일 명령어로 테스트를 실행하고 코드에 대한 확신을 가짐.
우주선 발사 준비 완료! Laravel에서 API를 생성하는 섹션을 완료했습니다.
📌 최종 확인:
php artisan test
를 실행하세요.- 모든 테스트가 통과하는지 확인하세요 (초록불!).
- 코드 커버리지 보고서를 확인하세요.
⚠️ 테스트가 실패할 경우:
- Postman을 통해 API 작동을 확인하세요.
- 테스트 DB가 설정되어 있는지 확인하세요.
dd($response->content())
를 사용하여 디버깅하세요.
2장 완료를 축하합니다! API를 생성했을 뿐만 아니라, 향후 미션을 위한 신뢰할 수 있고 검증된 "우주선"을 만들었습니다.
🌌 다음 단계:
- 인증 설정 (Sanctum)
- Swagger를 사용한 API 문서화
- 서버 배포 (Forge, VPS)
- Vue/React로 프런트엔드 작성
우주 미션의 성공적인 발사를 기원합니다! 다음 장에서는 API를 처음부터 작성하는 방법을 살펴보겠습니다 🚀