📚 PHP 최상급 - 6주차: 테스트 자동화 (단위/통합/E2E 테스트)- 02 통합 테스트 작성

2025. 10. 20. 13:28프로그램/PHP 최상급

통합 테스트의 이해와 중요성

📚 PHP 최상급 - 6주차: 테스트 자동화 (단위/통합/E2E 테스트)- 02 통합 테스트 작성

 

#소프트웨어 #개발에서 #테스트는 여러 계층으로 나눌 수 있으며, 지난번 #단위 #테스트(#Unit_Test)에 이어 이번에는 **#통합 #테스트(#Integration_Test)**에 대해 다룰 거예요. #통합 #테스트는 여러 #모듈(#Module)이나 #컴포넌트(#Component)가 서로 어떻게 상호작용하는지, 그리고 이들이 함께 올바르게 작동하는지 검증하는 과정이에요.

#단위 #테스트가 개별 코드의 정확성을 보장한다면, #통합 #테스트는 이들이 결합되었을 때 발생할 수 있는 문제, 예를 들어 #인터페이스(#Interface) 불일치, #데이터 #전달 오류 등을 찾아내요. 이는 실제 사용자 시나리오와 더 가까운 환경에서 테스트함으로써 애플리케이션의 견고성을 확보하는 데 매우 중요해요.


통합 테스트 환경 설정

#PHP에서 #통합 #테스트를 작성할 때도 #PHPUnit을 주로 사용하지만, 실제 #데이터베이스나 #외부 #서비스와의 연동이 필요할 수 있으므로 몇 가지 추가적인 설정이 필요할 수 있어요.

1. 테스트 전용 데이터베이스 및 환경

  • 데이터베이스: #통합 #테스트는 실제 #DB에 접근하는 경우가 많으므로, 개발용 #DB와는 별개의 테스트 전용 #데이터베이스를 사용하는 것이 좋아요. 각 테스트 실행 전에 #DB를 초기화(#Migration, #Seeding)하여 일관된 상태를 유지하는 것이 중요해요.
  • 환경 변수: #PHPUnit 설정 파일(phpunit.xml)에서 #테스트 환경에 맞는 #환경 #변수(#Environment_Variable)를 설정하거나, 별도의 설정 파일을 로드하도록 할 수 있어요.

2. 테스트 헬퍼 및 부트스트랩 파일

  • phpunit.xml에 지정된 bootstrap 파일에서 #테스트 #환경을 초기화하는 로직을 구현해요. 예를 들어, #DI #컨테이너(#Dependency_Injection_Container) 설정, #DB #연결, #ORM 초기화 등을 수행해요.
  • tests/bootstrap.php 예시:
  • PHP
     
    <?php
    require dirname(__DIR__) . '/vendor/autoload.php';
    
    // 테스트 환경 로드 (예: .env.testing)
    if (file_exists(dirname(__DIR__) . '/.env.testing')) {
        $dotenv = Dotenv\Dotenv::createImmutable(dirname(__DIR__), '.env.testing');
        $dotenv->load();
    }
    
    // 데이터베이스 연결 설정 (예: PDO)
    // $pdo = new PDO(...) 
    // DB 마이그레이션 및 시딩
    // ...
    

통합 테스트 작성 원칙 및 실제 예시

#단위 #테스트와 마찬가지로 #PHPUnit의 TestCase를 상속받지만, 테스트의 초점이 달라져요.

1. 테스트 대상

  • #컨트롤러(#Controller)와 #서비스(#Service), #서비스와 #리포지토리(#Repository), #리포지토리와 #DB 등 여러 계층이 함께 동작하는 시나리오를 테스트해요.
  • 외부 #API와의 연동, #파일 #시스템(#File_System) 접근 등도 포함될 수 있어요.

2. Fixtures (테스트 고정값)

#통합 #테스트는 종종 특정 #초기 #데이터 #상태를 요구해요. 이를 위해 #Fixtures를 사용하여 테스트 실행 전에 #DB에 필요한 데이터를 미리 넣어두고, 테스트 완료 후 정리하는 과정을 거쳐요.

  • setUp() 메서드에서 #Fixtures를 로드하고, tearDown() 메서드에서 정리해요.
  • 예시: 게시판 #서비스의 글 생성 및 조회 테스트

3. 실제 예시: 게시물 관리 통합 테스트

간단한 게시물 관리 기능을 가정하고, 게시물을 생성하고 조회하는 시나리오에 대한 통합 테스트를 작성해 볼게요.

src/PostRepository.php

PHP
 
<?php
// PostRepository.php (데이터베이스와 연동)
class PostRepository {
    private PDO $pdo;

    public function __construct(PDO $pdo) {
        $this->pdo = $pdo;
    }

    public function create(string $title, string $content): int {
        $stmt = $this->pdo->prepare("INSERT INTO posts (title, content) VALUES (:title, :content)");
        $stmt->execute([':title' => $title, ':content' => $content]);
        return (int)$this->pdo->lastInsertId();
    }

    public function find(int $id): ?array {
        $stmt = $this->pdo->prepare("SELECT * FROM posts WHERE id = :id");
        $stmt->execute([':id' => $id]);
        $post = $stmt->fetch(PDO::FETCH_ASSOC);
        return $post ?: null;
    }
}

tests/Integration/PostManagementTest.php

PHP
 
<?php
use PHPUnit\Framework\TestCase;

// 테스트 전용 PDO 객체 (실제 DB 연결)
class TestDatabase
{
    private static ?PDO $pdo = null;

    public static function getConnection(): PDO
    {
        if (self::$pdo === null) {
            // .env.testing 등에서 DB_DSN, DB_USER, DB_PASS 불러오기
            $dsn = $_ENV['DB_DSN'] ?? 'sqlite::memory:'; 
            $user = $_ENV['DB_USER'] ?? null;
            $pass = $_ENV['DB_PASS'] ?? null;
            self::$pdo = new PDO($dsn, $user, $pass);
            self::$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            self::$pdo->exec("CREATE TABLE IF NOT EXISTS posts (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                title VARCHAR(255) NOT NULL,
                content TEXT NOT NULL
            )");
        }
        return self::$pdo;
    }

    public static function resetDatabase(): void
    {
        $pdo = self::getConnection();
        $pdo->exec("DELETE FROM posts");
        $pdo->exec("DELETE FROM sqlite_sequence WHERE name='posts'"); // SQLite AUTOINCREMENT 재설정
    }
}

class PostManagementTest extends TestCase
{
    private PostRepository $postRepository;

    protected function setUp(): void
    {
        parent::setUp();
        TestDatabase::resetDatabase(); // 각 테스트 전에 DB 초기화
        $this->postRepository = new PostRepository(TestDatabase::getConnection());
    }

    public function testPostCreationAndRetrieval(): void
    {
        // Arrange
        $title = "첫 번째 게시글";
        $content = "내용입니다.";

        // Act - 게시물 생성 및 조회 (PostRepository와 PDO가 함께 작동)
        $newPostId = $this->postRepository->create($title, $content);
        $retrievedPost = $this->postRepository->find($newPostId);

        // Assert
        $this->assertNotNull($retrievedPost);
        $this->assertEquals($title, $retrievedPost['title']);
        $this->assertEquals($content, $retrievedPost['content']);
        $this->assertEquals($newPostId, $retrievedPost['id']);
    }

    public function testNonExistentPostRetrieval(): void
    {
        // Act
        $retrievedPost = $this->postRepository->find(999); // 존재하지 않는 ID

        // Assert
        $this->assertNull($retrievedPost);
    }
}

위 예시는 PostRepository와 실제 #PDO #데이터베이스 #연결이 함께 동작하는지 확인하는 통합 테스트예요. TestDatabase 헬퍼 클래스를 사용하여 #테스트 #전용 #DB를 설정하고 매 테스트마다 초기화하는 것을 볼 수 있어요.


요약

#통합 #테스트는 개별 단위가 결합되어 올바르게 동작하는지 확인하여, 실제 #애플리케이션의 동작과 가장 유사한 환경에서 문제를 찾아내는 데 중요한 역할을 해요. #PHPUnit과 적절한 #환경 #설정, 그리고 #Fixtures 관리를 통해 효과적인 #통합 #테스트를 작성함으로써 #PHP #애플리케이션의 신뢰도를 크게 높일 수 있어요.

 

 

빠른속도, 간편한사용, 장애없는VPN, 사용이력없는 깨끗한 아이피

https://vpn.luzensoft.com

 

VPN 5,500원 / IP교체 1,100원 / 유동프록시 22,000원 | LuzenVPN 루젠VPN

국내최저가 고정IP서비스,유동프록시(IP4000개이상제공),PPTP,L2TP,IPSec,OpenVPNVPN,통신사VPN,VPN프로그램,고정IP,고정아이피,PPTP,저렴한VPN,리니지MVPN,리니지VPN,아이온VPN,던파VPN,유동프록시,유동PROXY,바이

vpn.luzensoft.com