FastAPI 주니어 테스트 및 코드품질 기술면접
새 면접Q. FastAPI 애플리케이션에서 pytest를 사용해 API 엔드포인트를 테스트할 때, TestClient를 사용하는 이유와 기본적인 사용 방법을 설명해주세요.
실제 서버를 띄우지 않고도 HTTP 요청을 시뮬레이션할 수 있는 방법을 생각해보세요.
TestClient는 FastAPI 애플리케이션을 실제로 서버로 실행하지 않고도 HTTP 요청을 테스트할 수 있게 해주는 도구입니다. starlette의 TestClient를 import하여 FastAPI 앱 인스턴스를 인자로 전달하면 생성됩니다. TestClient 객체를 통해 get, post 등의 메서드를 호출하여 실제 HTTP 요청을 시뮬레이션하고, 응답의 status_code, json() 등을 검증할 수 있습니다. 이를 통해 빠르고 격리된 환경에서 API 동작을 검증할 수 있어 단위 테스트에 적합합니다.
- • TestClient는 서버 실행 없이 HTTP 요청 시뮬레이션
- • starlette 라이브러리에서 제공
- • 응답 검증을 통한 API 동작 확인
- • 빠르고 격리된 테스트 환경 제공
API 엔드포인트 개발 시 코드 변경마다 빠르게 회귀 테스트를 수행하여 기능 정상 동작을 보장합니다.
TestClient를 사용한 테스트와 실제 서버를 띄워서 하는 통합 테스트의 차이점과 각각 언제 사용해야 하는지 설명해주세요.
Q. pytest의 fixture를 사용하는 이유와 FastAPI 테스트에서 데이터베이스 연결이나 테스트 데이터를 fixture로 관리하는 방법을 설명해주세요.
테스트마다 반복되는 설정 코드를 재사용하고 테스트 간 격리를 유지하는 방법을 생각해보세요.
fixture는 테스트 실행 전에 필요한 설정이나 데이터를 준비하고, 테스트 후 정리하는 재사용 가능한 컴포넌트입니다. @pytest.fixture 데코레이터를 사용해 정의하며, 테스트 함수의 파라미터로 전달하여 사용합니다. 데이터베이스 연결의 경우 fixture에서 테스트용 DB를 생성하고 yield로 전달한 후, 테스트 완료 시 롤백하거나 삭제하여 테스트 간 격리를 보장합니다. scope 옵션으로 function, module, session 등 생명주기를 조절할 수 있어 성능과 격리 사이의 균형을 맞출 수 있습니다.
- • fixture는 테스트 설정과 정리를 재사용 가능하게 함
- • yield를 통한 setup/teardown 패턴
- • 테스트 간 격리 보장
- • scope로 생명주기 관리
데이터베이스를 사용하는 API 테스트 시 각 테스트마다 깨끗한 DB 상태를 보장하여 테스트 신뢰성을 확보합니다.
fixture의 scope를 function, module, session으로 설정했을 때 각각의 차이점과 성능상 영향을 설명해주세요.
Q. FastAPI의 Depends를 사용하는 엔드포인트를 테스트할 때, 실제 의존성을 테스트용 의존성으로 오버라이드하는 방법과 그 필요성을 설명해주세요.
app.dependency_overrides를 활용하여 외부 서비스나 데이터베이스 연결을 모킹하는 방법을 생각해보세요.
FastAPI의 app.dependency_overrides 딕셔너리를 사용하여 실제 의존성을 테스트용으로 대체할 수 있습니다. 원래 의존성 함수를 키로, 테스트용 의존성 함수를 값으로 설정하면 테스트 실행 시 대체된 의존성이 주입됩니다. 이는 외부 API 호출, 실제 데이터베이스 연결, 인증 서비스 등을 모킹하여 테스트를 빠르고 안정적으로 만드는 데 필수적입니다. 테스트 완료 후에는 dependency_overrides를 clear하여 다른 테스트에 영향을 주지 않도록 해야 합니다. 이를 통해 외부 의존성 없이 비즈니스 로직만 격리하여 테스트할 수 있습니다.
- • app.dependency_overrides로 의존성 교체
- • 외부 서비스를 모킹하여 테스트 안정성 확보
- • 테스트 후 clear로 격리 유지
- • 비즈니스 로직만 집중 테스트
결제 API나 외부 인증 서비스에 의존하는 엔드포인트를 실제 서비스 호출 없이 안전하게 테스트합니다.
데이터베이스 의존성을 오버라이드할 때 인메모리 DB를 사용하는 것과 실제 DB에 테스트 스키마를 만드는 것의 장단점을 비교해주세요.
Q. 코드 커버리지가 무엇인지 설명하고, pytest-cov를 사용해 FastAPI 프로젝트의 테스트 커버리지를 측정하는 방법과 커버리지 100%를 목표로 해야 하는지에 대한 의견을 말씀해주세요.
커버리지는 테스트가 실행한 코드의 비율이지만, 높은 커버리지가 반드시 좋은 테스트를 의미하는 것은 아닙니다.
코드 커버리지는 전체 코드 중 테스트가 실행한 코드의 비율을 나타내는 지표입니다. pytest-cov 플러그인을 설치하고 pytest --cov=app 명령으로 측정하며, --cov-report html 옵션으로 상세 리포트를 생성할 수 있습니다. 커버리지 100%는 모든 코드가 실행되었다는 의미일 뿐, 모든 엣지 케이스나 비즈니스 로직이 검증되었다는 보장은 없습니다. 따라서 80-90% 정도의 합리적인 목표를 설정하고, 중요한 비즈니스 로직과 복잡한 분기에 집중하는 것이 실용적입니다. 커버리지는 테스트 품질의 하한선을 제시하는 도구로 활용해야 합니다.
- • 커버리지는 테스트 실행 코드 비율
- • pytest-cov로 측정 가능
- • 100% 커버리지가 완벽한 테스트를 보장하지 않음
- • 중요 로직에 집중하는 것이 실용적
CI/CD 파이프라인에서 커버리지 임계값을 설정하여 테스트가 부족한 코드의 배포를 방지합니다.
라인 커버리지와 브랜치 커버리지의 차이점을 설명하고, 어느 것이 더 의미 있는 지표인지 말씀해주세요.
Q. TDD(Test-Driven Development)의 Red-Green-Refactor 사이클을 설명하고, FastAPI로 새로운 API 엔드포인트를 개발할 때 이 방법론을 적용하는 과정을 단계별로 설명해주세요.
실패하는 테스트를 먼저 작성하고, 최소한의 코드로 통과시킨 후, 개선하는 순서를 생각해보세요.
TDD는 테스트를 먼저 작성하고 코드를 구현하는 개발 방법론입니다. Red 단계에서는 아직 구현되지 않은 기능에 대한 테스트를 작성하여 실패하는 것을 확인합니다. Green 단계에서는 테스트를 통과시킬 수 있는 최소한의 코드만 작성합니다. Refactor 단계에서는 테스트가 통과하는 상태를 유지하면서 코드를 개선하고 중복을 제거합니다. FastAPI 엔드포인트 개발 시 먼저 원하는 응답 형식과 상태 코드를 검증하는 테스트를 작성하고, 엔드포인트를 구현한 후, 코드 구조를 개선하는 순서로 진행합니다. 이를 통해 요구사항을 명확히 하고 회귀 버그를 방지할 수 있습니다.
- • Red-Green-Refactor 사이클
- • 테스트 먼저 작성 후 구현
- • 최소 구현 후 점진적 개선
- • 요구사항 명확화와 회귀 방지
복잡한 비즈니스 로직을 가진 결제 처리 API를 개발할 때 요구사항을 테스트로 명확히 정의하고 안전하게 구현합니다.
TDD를 실무에 적용할 때 겪을 수 있는 어려움과 이를 극복하는 방법을 말씀해주세요.
Q. FastAPI 애플리케이션에서 단위 테스트와 통합 테스트의 차이점을 설명하고, 데이터베이스를 포함한 통합 테스트를 작성할 때 고려해야 할 사항들을 말씀해주세요.
단위 테스트는 격리된 컴포넌트를, 통합 테스트는 여러 컴포넌트의 상호작용을 검증합니다.
단위 테스트는 개별 함수나 메서드를 외부 의존성 없이 격리하여 테스트하며, 통합 테스트는 데이터베이스, 외부 API 등 여러 컴포넌트가 함께 동작하는 것을 검증합니다. 통합 테스트 작성 시 테스트용 데이터베이스를 별도로 구성하고, 각 테스트마다 트랜잭션을 롤백하거나 데이터를 초기화하여 테스트 간 격리를 보장해야 합니다. 테스트 실행 순서에 의존하지 않도록 독립적으로 작성하고, 실제 환경과 유사한 설정을 사용해야 합니다. 통합 테스트는 단위 테스트보다 느리므로 중요한 시나리오에 집중하고, 피라미드 구조로 단위 테스트를 더 많이 작성하는 것이 좋습니다.
- • 단위 테스트는 격리, 통합 테스트는 상호작용 검증
- • 테스트용 DB와 데이터 초기화 필요
- • 테스트 간 독립성 보장
- • 테스트 피라미드 구조 유지
사용자 등록 API가 데이터베이스 저장, 이메일 발송, 캐시 업데이트를 모두 정상적으로 수행하는지 검증합니다.
Docker를 활용해 통합 테스트용 데이터베이스 환경을 구성하는 방법과 장점을 설명해주세요.
Q. 코드 리팩토링이 무엇인지 설명하고, FastAPI 엔드포인트 함수가 너무 길어졌을 때 적용할 수 있는 리팩토링 기법들을 구체적으로 말씀해주세요.
외부 동작은 유지하면서 내부 구조를 개선하는 방법들을 생각해보세요.
리팩토링은 코드의 외부 동작을 변경하지 않으면서 내부 구조를 개선하여 가독성과 유지보수성을 높이는 작업입니다. 긴 엔드포인트 함수는 비즈니스 로직을 서비스 레이어로 분리하여 엔드포인트는 요청/응답 처리만 담당하게 할 수 있습니다. 반복되는 검증 로직은 별도 함수나 Pydantic 모델의 validator로 추출하고, 데이터베이스 접근 로직은 리포지토리 패턴으로 분리할 수 있습니다. 복잡한 조건문은 early return이나 guard clause를 사용해 중첩을 줄이고, 매직 넘버나 문자열은 상수로 추출합니다. 리팩토링 후에는 기존 테스트가 여전히 통과하는지 확인하여 동작 변경이 없음을 보장해야 합니다.
- • 외부 동작 유지하며 내부 구조 개선
- • 비즈니스 로직을 서비스 레이어로 분리
- • 리포지토리 패턴으로 DB 로직 분리
- • 테스트로 동작 보장
복잡해진 주문 처리 엔드포인트를 여러 책임으로 분리하여 새로운 요구사항 추가를 쉽게 만듭니다.
리팩토링을 안전하게 수행하기 위해 테스트 코드가 어떤 역할을 하는지 설명해주세요.
Q. FastAPI 프로젝트에서 코드 리뷰를 할 때 주의 깊게 확인해야 할 주요 체크 포인트들을 테스트와 코드 품질 관점에서 설명해주세요.
테스트 존재 여부, 에러 처리, 코드 중복, 네이밍 등 여러 측면을 고려해보세요.
코드 리뷰 시 먼저 새로운 기능이나 수정사항에 대한 테스트가 포함되어 있는지 확인해야 합니다. 예외 상황과 엣지 케이스에 대한 처리가 적절한지, 에러 메시지가 명확한지 검토합니다. 코드 중복이 있다면 함수나 클래스로 추출할 것을 제안하고, 변수명과 함수명이 의도를 명확히 드러내는지 확인합니다. Pydantic 모델의 validation이 적절하게 설정되어 있는지, 데이터베이스 쿼리가 N+1 문제를 일으키지 않는지도 확인합니다. 보안 관련 사항으로는 SQL 인젝션 가능성, 민감 정보 로깅 여부, 인증/인가 처리가 올바른지 점검해야 합니다.
- • 테스트 포함 여부 확인
- • 예외 처리와 에러 메시지 검토
- • 코드 중복 제거와 명확한 네이밍
- • 보안과 성능 이슈 점검
Pull Request 리뷰를 통해 배포 전에 잠재적 버그와 보안 이슈를 사전에 발견하고 팀 전체의 코드 품질을 향상시킵니다.
코드 리뷰 시 건설적인 피드백을 제공하는 방법과 팀 문화 형성에 대해 말씀해주세요.
Q. FastAPI 테스트에서 외부 API 호출이나 시간 관련 함수를 테스트할 때 unittest.mock의 patch를 사용하는 이유와 방법을 설명해주세요.
외부 의존성을 제어 가능한 가짜 객체로 대체하여 테스트를 안정적이고 빠르게 만드는 방법입니다.
mock의 patch는 실제 함수나 객체를 테스트용 가짜 객체로 대체하여 외부 의존성을 제거하고 테스트를 안정적으로 만듭니다. 외부 API 호출의 경우 네트워크 상태나 외부 서비스 장애에 영향받지 않고, 원하는 응답을 미리 정의하여 다양한 시나리오를 테스트할 수 있습니다. @patch 데코레이터로 함수나 메서드를 패칭하고, return_value나 side_effect로 동작을 정의합니다. datetime.now 같은 시간 함수를 패칭하면 시간에 의존하는 로직을 일관되게 테스트할 수 있습니다. 패칭 시에는 임포트 경로를 정확히 지정해야 하며, 테스트가 실제 구현에 지나치게 결합되지 않도록 주의해야 합니다.
- • 외부 의존성을 제어 가능한 mock으로 대체
- • 다양한 시나리오를 안정적으로 테스트
- • return_value와 side_effect로 동작 정의
- • 임포트 경로 정확히 지정
결제 게이트웨이 API를 호출하는 로직을 실제 결제 없이 다양한 성공/실패 케이스로 테스트합니다.
mock 객체의 assert_called_once_with 같은 assertion 메서드들을 사용하는 이유를 설명해주세요.
Q. FastAPI의 async 엔드포인트와 비동기 데이터베이스 작업을 테스트할 때 pytest-asyncio를 사용하는 방법과 주의사항을 설명해주세요.
비동기 함수는 일반 테스트 함수와 다르게 처리되어야 하며, 이벤트 루프 관리가 중요합니다.
pytest-asyncio 플러그인을 설치하고 테스트 함수에 @pytest.mark.asyncio 데코레이터를 적용하면 async 함수를 테스트할 수 있습니다. 비동기 fixture는 async def로 정의하고 await로 값을 반환하며, scope 설정 시 이벤트 루프 생명주기를 고려해야 합니다. TestClient는 기본적으로 동기 방식이므로, 비동기 컨텍스트 내에서 테스트하려면 httpx.AsyncClient를 사용하는 것이 더 적합합니다. 비동기 DB 작업 테스트 시에는 async 세션을 fixture로 관리하고, 각 테스트 후 트랜잭션을 롤백하여 격리를 유지합니다. 이벤트 루프 정책 설정이나 fixture scope 충돌에 주의해야 하며, asyncio.TimeoutError 등 비동기 특유의 예외 처리도 테스트해야 합니다.
- • pytest-asyncio로 async 함수 테스트
- • httpx.AsyncClient 사용 고려
- • 비동기 fixture와 세션 관리
- • 이벤트 루프와 scope 주의
대량의 동시 요청을 처리하는 비동기 API의 동시성 제어와 데이터 일관성을 검증합니다.
비동기 코드에서 발생할 수 있는 race condition을 테스트하는 방법을 설명해주세요.
아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!