테스트 DB 분리와 TransactionTestCase의 사용 시점

Django 테스트의 독립성을 보장하기 위한 테스트 DB 분리 메커니즘과 특정 상황에서 필요한 TransactionTestCase의 정확한 사용법

테스트 DB 분리의 필요성

독립성(Isolation) 보장이 핵심

  • 데이터 오염 방지: 테스트 실행 중 생성/수정/삭제된 데이터가 실제 DB를 오염시키는 상황 방지

  • 의존성 제거: 다른 테스트 결과나 기존 데이터에 의존하지 않는 안정적인 테스트 환경 구성

  • 심각한 사고 예방: 실수로 운영 DB에 위험한 쿼리를 실행하는 상황 차단

Django는 테스트 실행 시 기존 DB와 완전히 독립된 별도의 테스트 DB를 자동 생성하여 사용

Django 테스트 DB 생성 메커니즘

  1. manage.py test 실행

  2. 설정(settings.py)에 명시된 DB 정보 앞에 'test_' 붙여 새 DB 생성

  3. Migration 실행하여 최신 스키마 적용

  4. 개별 테스트 실행

  5. 모든 테스트 종료 후 'test_' DB 삭제

성능 최적화: SQLite In-memory 모드 사용으로 테스트 속도 향상 가능

TestCase vs TransactionTestCase 핵심 차이

구분
TestCase
TransactionTestCase

격리 방식

DB 트랜잭션으로 감싼 후 롤백

테이블을 비움(Truncate)

속도

빠름

느림

DB Commit

실제 COMMIT 발생하지 않음

실제 COMMIT 발생

주 사용처

대부분의 단위/통합 테스트

트랜잭션 동작 테스트

기본 원칙: 항상 TestCase를 기본으로 사용하고, TransactionTestCase는 꼭 필요한 특정 상황에서만 제한적으로 사용

TransactionTestCase 사용 시점

1. transaction.on_commit() 동작 테스트

현재 DB 트랜잭션이 성공적으로 커밋되었을 때만 특정 함수를 실행하는 로직 테스트

  • TestCase: COMMIT이 발생하지 않아 on_commit 콜백이 실행되지 않음

  • TransactionTestCase: 실제 COMMIT 실행으로 on_commit 콜백 정상 실행

2. 여러 스레드/프로세스 간 동작 테스트

별도의 스레드나 프로세스가 DB 데이터를 공유해야 하는 경우

  • 웹소켓 로직이나 병렬 처리 로직 테스트에 필요

3. 데이터베이스 고유의 제약 조건 테스트

COMMIT 시점에만 검사되는 특정 제약 조건(DEFERRABLE 제약 등) 테스트

실무 주의사항

  1. 성능 저하 인지: TransactionTestCase는 TestCase보다 훨씬 느려 전체 테스트 스위트 실행 시간을 크게 증가시킴

  2. 최소한 사용: 꼭 필요한 곳에만 제한적으로 사용

  3. reset_sequences: 기본적으로 각 테스트 후 PK 시퀀스도 리셋되어 매번 id=1부터 시작

Last updated