pytest 사용기 - fixture, scope
파이썬에서 제공하는 테스팅 모듈로는 unittest, pytest가 유명한데, 둘 중 어느걸 사용해 볼까 하다가 pytest가 간단해 보여서 pytest로 작업을 진행했습니다. 빠른 진행을 위해서는 테스팅 모듈이 간편한게 좋을 것 같다는 생각이 들었기 때문입니다. pytest 어떻게 사용했는지 살펴보겠습니다.
설치
pytest는 pip 로 설치하며 기초 설명은 공식 홈페이지에서 확인 가능합니다.
1 | pip install pytest |
프로젝트 구조
테스트 코드를 작성한 프로젝트의 구조는 다음과 같습니다.
1 | . |
pytest를 위해 작성한 파일은 pytest.ini와 test폴더 하위의 파일들입니다. 먼저, pytest.ini에는 테스트에 사용할 파일과 테스트 옵션을 추가합니다. 일반적으로 test_*.py 또는 *_test.py를 테스트 파일로 인식하지만 직접 지정해줄 수도 있습니다. 파일이 여러 개인 경우 스페이스로 구분합니다.
1 | [pytest] |
테스트는 pytest 명령어를 사용해 실행합니다. 실행하는 경로에 상관없이 pytest용 파일을 찾아 실행합니다. q옵션을 사용하면 로그를 간략하게 볼 수 있습니다.
1 | (venv) yejinui-MacBook-Pro:logparser yejin$ pytest -q |
테스트 코드 작성
테스트 함수에는 아래와 같이 함수명에 접두사로 test_ 를 붙여야 합니다. 접두사가 없으면 그 함수는 실행하지 않고 넘어갑니다. count 함수와 sequence 함수를 테스트 하기 위해 각각 test_count, test_sequnce함수를 만들었습니다. test_count는 로그 수가 맞는지를 확인하고 test_sequence는 ‘type’ 별 집계가 일치하는지 확인합니다.
1 | #test_parser.py |
두 함수에서는 공통적으로 log_parser()함수를 사용해 로그를 읽어옵니다. 예시 이외에도 로그를 읽어 오는 테스트가 더 있어 클래스를 정의하는 방식으로 변경하였습니다. self.logs를 사용하는 방식으로 코드를 수정했습니다.
1 | class TestParserClass: |
그런데 에러가 발생했습니다. 클래스에 __init__를 정의한 것이 문제가 되었습니다. 공식 홈페이지를 확인해보니 __init__를 정의하는 경우 클래스가 인스턴스화 되지 않는다고 하네요.
1 | (venv) yejinui-MacBook-Pro:logparser yejin$ pytest -q |
그래서 fixture를 사용했습니다. fixture란, 테스트 시 사용하는 함수들을 미리 정의하는 기능입니다.
fixture함수는 test/conftest.py에 작성합니다.
1 | #test/conftest.py |
test_ 함수에서 사용할 때에는 따로 conftest를 임포트할 필요없이 매개변수로 지정하기만 하면됩니다.
1 | #test_parser.py |
굳이 fixture를 사용하지 않고 test_log_parse 함수를 만들어도 되는게 아닌가 생각할 수도 있습니다. 그렇게도 가능합니다. 그러나 깨끗한 테스트 코드를 위해 변하지 않는 기능은 한 곳에 넣어두고 자주 변경되며 확장할 기능을 만들도록 하는 것이 관리에 좋아 보입니다. 클래스 상속 개념처럼요🙂 그리고 무엇보다도 fixture를 사용하면 fixture가 제공하는 부가 옵션들을 사용할 수 있습니다. 여기서는 scope를 사용했습니다.
scope를 사용해 fixture를 모듈, 클래스, 세션 단위로 공유합니다. 다시 말해, test_ 함수를 실행할 때마다 fixture함수를 재호출하지 않고 사용할 수 있다는 것입니다. scope를 module 단위로 지정했더니, test_log_parse 한 번 호출 후 계속 재사용하기 때문에 아래와 같이 실행 시간이 단축됩니다.
1 | //scope 사용 |