AI Store에서 AI코딩으로 만들어진 앱을 만나보세요!
지금 바로 방문하기

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. 코드 리팩토링 제안

  • ReaderReaderContext 클래스를 통해 Path.open()과 로직 분리
  • read_file 함수에 context 매개변수를 추가하여 추상화 적용
  • 장점: 테스트와 로직 분리, 재사용성 향상

결론

  • monkey patching은 파일 시스템과의 상호작용을 모킹하여 테스트를 간소화할 수 있는 강력한 기법
  • 핵심 팁: monkeypatch.setattr()을 사용할 때, 실제 import 경로(mp_test.utils, pathlib)를 정확히 대체해야 함
  • 추천 구현: MockPathMockReader 클래스를 사용하여 컨텍스트 매니저 기능을 구현하고, 테스트 시 경로 검증을 위해 MockPath.paths 리스트 사용
  • 추가 권장: 로직과 파일 I/O를 분리하기 위해 Reader/ReaderContext 추상화 적용하여 테스트 유연성 확보