monkey patching을 활용한 pytest 테스트 소개
카테고리
프로그래밍/소프트웨어 개발
서브카테고리
개발 툴
대상자
- 대상자: pytest를 사용하는 소프트웨어 개발자 및 테스터
- 난이도: 중급 (monkey patching과 mocking 개념 이해 필요)
핵심 요약
- monkey patching은
Path
객체를 임시로 대체하여 파일 시스템과의 상호작용을 모킹함으로써 테스트를 간소화하는 기법 - 핵심 구현은
monkeypatch.setattr()
을 사용하여Path
객체를MockPath
클래스로 대체하고,open()
메서드를 모킹 - 문제 해결을 위해
MockReader
클래스를 추가하여__enter__
/__exit__
메서드를 구현하여 컨텍스트 매니저를 지원
섹션별 세부 요약
1. 문제 정의 및 테스트 대상 함수
read_file
함수는Path.open()
을 사용하여 파일을 직접 읽고, 이로 인해 테스트 시 파일 시스템과의 상호작용 발생- 테스트 시
FileNotFoundError
발생: 파일이 존재하지 않을 경우 예외 처리 필요 - 파일 생성/삭제 관리 문제로 인해 테스트가 불가능
2. monkey patching 적용 시도
monkeypatch.setattr(pathlib, "Path", lambda x: print(x))
사용:Path
객체를lambda
로 대체- 문제:
Path
객체가utils.py
에서 직접 import 되어 있어pathlib
대신mp_test.utils
를 대체해야 함
3. `MockPath` 클래스 구현
MockPath
클래스를 정의하여open()
메서드를 오버라이드MockPath.open()
은MockReader
인스턴스를 반환- 문제:
MockReader
가 컨텍스트 매니저(__enter__
,__exit__
)를 지원하지 않아TypeError
발생
4. `MockReader` 클래스 추가
MockReader
클래스에__enter__
,__exit__
,read()
메서드 추가MockPath.open()
은MockReader
인스턴스를 반환하여with
문 지원- 테스트 시
assert value == 13
을 통해 테스트 성공
5. 테스트 검증 및 개선
MockPath.paths
리스트를 통해Path
객체가 올바른 경로로 생성되었는지 검증assert 'test_file_foo' == MockPath.paths[0]
으로 경로 검증- 문제:
read_file
함수 내부에서Path
객체가 생성되는 방식이 테스트 시 확인되지 않음
6. 코드 리팩토링 제안
Reader
및ReaderContext
클래스를 통해Path.open()
과 로직 분리read_file
함수에context
매개변수를 추가하여 추상화 적용- 장점: 테스트와 로직 분리, 재사용성 향상
결론
- monkey patching은 파일 시스템과의 상호작용을 모킹하여 테스트를 간소화할 수 있는 강력한 기법
- 핵심 팁:
monkeypatch.setattr()
을 사용할 때, 실제 import 경로(mp_test.utils
,pathlib
)를 정확히 대체해야 함 - 추천 구현:
MockPath
및MockReader
클래스를 사용하여 컨텍스트 매니저 기능을 구현하고, 테스트 시 경로 검증을 위해MockPath.paths
리스트 사용 - 추가 권장: 로직과 파일 I/O를 분리하기 위해
Reader
/ReaderContext
추상화 적용하여 테스트 유연성 확보