목록으로

Python Doctest로 함수의 테스트 코드 작성하기

낱글
2024. 7. 23. PM 12:31:28
#python, #test, #doctest, #테스트, #pytest, #문서화

Docstring

Python에서 Docstring은 함수, 클래스, 모듈 또는 메서드의 첫 번째 문장으로 작성되는 문자열이예요. Docstring이 작성된 해당 코드 블록의 목적이나 동작을 설명하는 데 사용되죠. docstring은 코드의 가독성과 유지 관리를 향상시키는 데 중요한 역할을 하며, 다양한 도구를 통해 자동으로 문서를 생성하는 데 활용돼요.

Docstring은 Python 객체의 __doc__ 속성으로 존재해요.

또는 Python 내장 함수인 help()를 사용해도 Docstring을 볼 수 있어요.

비주얼 스튜디오 코드처럼 Python을 지원하는 코드 에디터는 Docstring도 참고해 함수 등 객체의 설명을 표시하죠.

Docstring은 명백한 문자열 객체로 주석과는 다릅니다. 하지만 Python 인터프리터를 -OO 옵션을 사용하면 무시(무효화)됩니다.

-O 옵션을 사용하면 assert문이 무시되는 것처럼 -OO 사용하면 Docstring이 무시되어 None이 되지요. 만약 Docstring을 비즈니스 로직에 사용한다면 유의해야 해요.

Doctest

개요

Python의 Doctest 기능은 doctest 모듈에서 제공하는데, Docstring에 포함된 예제들이 실제 코드와 일치하는지 검증할 수 있도록 테스팅하는 데 활용해요. Python 대화식 인터프리터(REPL)에서 Python 코드 실행을 전개하듯이 코드로 작성하지요.

Docstring에 Python REPL 프롬프트 기호를 사용하여 add() 함수 동작 예시를 작성하면, 사람이 읽을 때 add() 함수를 어떻게 사용하는지 파악하기 좋습니다. 이렇게 작성한 Doctest는 doctest 모듈의 testmod() 함수를 호출해 작동합니다.

기본 활용

Doctest라는 이름대로 테스팅에서 활용하는데요. 저는 주로 유틸리티 성격이 있는 함수에 Doctest로 테스트를 작성해요.

유틸리티성 함수는 대체로 짧고 간단하지만, 사용하는(의존하는) 곳이 많아서 구현이 변경되면 영향을 크게 미치죠. 유틸리티성 함수를 사용한 사람은 Docstring이나 Doctest를 믿고(신뢰하고) 사용하므로 함수 구현을 수정한다면 가능한 한 Docstring과 Doctest를 유지하면서 테스팅을 통과하도록 하여 문서화된 내용과 실 구현이 일치함을 보장해야하죠. 그래서 Docstring과 Doctest로 문서화와 구현을 최대한 가까이 배치해요.

교육 활용

저는 Python 교육을 하는 데에도 Docstring과 Doctest를 활용해요.

이와 같이 함수의 인터페이스를, 그리고 어떻게 사용하고 동작하는지 예시를 Doctest로 명기하여 제공하고, 학습자분이 이를 참고하여 실제 구현을 하는 거죠. 구현한 코드는 Doctest로 검증하고요. Python 입문자에겐 타입 각주(type annotation)를 사용하는 것보다는 Docstring이 더 쉽고, 테스팅하며 동작 피드백을 빠르게 받을 수 있어 좋아요.

동작 맥락(Context)

Doctest에 작성된 코드는 해당 Doctest가 위치한 모듈의 맥락을 따라요.

이렇게 Doctest를 작성하면 Doctest 대상인 this_year() 함수가 평가(evaluate)되는 모듈의 맥락을 따르므로 datetime.now() 를 사용할 수 있는 거죠.

하지만 저는 구현체가 의존하는 대상을 바로 알아볼 수 있게 Doctest에 import문도 넣는 편이예요.

pytest 지원

pytest는 기본적으로 Doctest를 지원해요. 별다른 옵션없이 실행해도 Doctest를 처리하지만, 만약 pytest가 테스팅 대상으로 수집(collect)할 조건을 사용하고 있다면 --doctest-modules이나 --doctest-glob 옵션을 사용해 수행할 수 있어요. --doctest-modules는 파일 확장자가 .py인 모든 파일에 대해서 Doctest를 실행하고, --doctest-glob=<패턴>은 glob 패턴 매칭으로 Doctest 대상 파일을 지정하죠.

pytest로 Doctest를 할 때 좋은 점 중 또 하나는 doctest.testmod()를 넣지 않아도 된다는 점이예요.

학습이 이뤄지고 있는지 확신이 안 서나요?
사수가 없나요?
효과적이고 효율적으로 학습하며 성장하는
자기만의 학습과 성장 체계를 만들 수 있습니다.
연사자들의 각양각색 학습과 성장 스토리로
여러분의 학습과 성장을 키워보세요.
푸딩캠프 뉴스레터를 구독하면 학습과 성장, 기술에 관해 요약된 컨텐츠를 매주 편하게 받아보실 수 있습니다.