pdm - 의존성 관리도구, 가상환경에서 pytest 실행하기
pdm은 이전글에서도 설명한대로 의존성 관리도구이며 pyenv처럼 가상환경 기능을 제공한다.
여러가지 모듈을 pdm 가상환경에 설치하여 다양한 기능을 테스트해 볼 수 있다. 당연히 의존성 관리 도구이기 때문에 설치한 모듈을 관리할 수 있다. 관리할 수 있다는건 생성, 삭제, 수정이 용이하다는 것이다.
pdm 가상환경을 구축하는 건 매우 간단하다. pdm을 실행하고자 하는 경로로 이동하여 아래 코드를 차례대로 입력하면 된다.
pdm init #pdm 실행
source .venv/bin/activate #pdm 가상환경 실행
만약 가상환경이 실행이 되지 않는다면 venv가 없기때문이다. 아래 코드로 따라서 별도로 설치하고 다시 실행하면 된다.
pdm venv create #venv 생성
여기 드는 의문! 그냥 가상환경말고 내 컴퓨터에서 테스트할 수 있지않나?
라고 의문이 들 수 있지만,
내 컴퓨터에서는 정상적으로 실행이 되는 코드이지만 다른 컴퓨터에서는 에러가 날 수 있다. 게다가 내 컴퓨터 환경에 이미 많은 모듈들이 설치되어 있다면 구현한 기능과 관련된 모듈들과 섞이면서 의존성 관리하기 어려울 것이다.
따라서, pdm을 이용해 가상환경을 구축하고 그 안에서 파이썬에서 제공하는 테스트할 수 있는 기능인 pytest를 설치해 테스트하는 것이 좋다.
개발과정에서 테스트는 매우 중요하다. 바로 안정성때문이다.
테스트를 진행하지 않았을 때 버그가 있을 확률이 매우 높은데 모든 버그들을 수정하고 테스트를 반복하는 비용은 어마어마하게 늘어날 것이다.
비용이 왜 늘어날까? 에 대한 답은.. 캐시, 데이터베이스 등 외부 컴포넌트들과 연결하는 데 시간이 필요하기 때문이다. (시간이 금이다!!)
따라서, 우리는 개발 및 테스팅을 위한 비용을 최소화하기위해 유닛코드(Unit Code) 테스트를 진행해야 한다. 즉 코드를 단위별로 나눠 테스트를 진행해야 한다는 뜻이다.
유닛코드를 테스트하는데 아주 좋은 기능이 파이썬에 있다. 바로 pytest이다.
pytest?
pytest가 생소할 수 있다. pytest는 tests 폴더 안에 파이썬파일을 만들고 내가 테스트하고자 하는 코드를 불러와 저장하기만 하면 바로 테스트해 볼 수 있다. 게다가 내 원본코드에는 영향이 가지않아 테스트코드에서 이것저것 수정하여 버그들을 고쳐나가면 된다.
이는 협업할 때 굉장히 유용하다. 만약 회사동료가 버그를 고치기 위해 내 원본파일을 이리저리 수정하면, 나중에 내가 그 원본파일로 다른 작업을 하려할 때 매우 난감할 수 있다... 그러나 테스트파일이 있다면 테스트파일로 수정을 하고 아니다싶으면 지우고 다시 원본파일 코드를 가져와 테스트할 수 있다.
pdm 가상환경에서 pytest를 설치하는 방법은 아래와 같다.
pdm install
위 코드를 입력하고 설치했다면 pyproject.toml 안에 dependencies에 추가하자.
pdm add -dG test pytest #pytest을 dependencies에 추가
pdm add -dG test pytest pytest-cov #pytest와 pytest-cov을 dependencies에 추가
pdm list를 통해 내가 설치한 기능을 확인할 수 있다.
혹은 pyproject.toml 파일에 들어가 확인해보면 된다. 아래 코드가 있다면 정상적으로 dependencies에 들어간 것이다.
[tool.pdm.dev-dependencies]
test = [
"pytest>=8.3.1",
"pytest-cov>=5.0.0",
]
pytest를 실행하는 방법은 매우 간단하다. 테스트파일에 테스트할 유닛코드를 작성하고 저장하고 나와 pytest 라고 쳐보면 된다.
pytest는 내가 테스트할 것을 추가할 때마다 몇개의 item 즉 유닛코드가 통과하였는지 보여준다. 또한 어떤 유닛코드가 어디서 Failed 했는지도 알려줘서 유용하다.
여기서 주의해야할 점은,
test할 코드는 반드시 tests 폴더 안에 _test.py 혹은 test_*.py 만들어 작성해야 한다. 그래야 '얘는 test코드야~'하고 읽어 실행시켜준다. 파이썬 파일명이 _test.py 혹은 test_*.py 아닐 경우 못읽어서 에러가 난다.
에러메세지: ModuleNotFoundError: No module named ~~
간혹 test코드에 원본코드를 import하여 사용할 경우 pytest를 진행하였는데 위 에러메세지가 나올 수 있다. 이는 pytest가 src 경로를 읽지못해 발생하는 에러로... 해결방법은 pyproject.toml 에 아래 코드를 추가해주는 것이다. 이래야 잘 읽어온다.
[tool.pytest.ini_options]
pythonpath = [".", "src"]
pytest는 code coverage 라는 기능도 제공하는데 코드 커버리지 보고서를 생성하기 위해 사용된다. 코드 커버리지란 테스트가 소스 코드의 몇 퍼센트나 실행되는지를 측정하는 것을 의미한다. 에러날 경우 에러난 코드 line도 알려주니 그 부분만 다시 test 기능에 추가하여 테스트를 계속 진행할 수 있다.
pytest --cov
Failed한 코드가 없어 100%로 나타난다.
pytest 3가지 명령어
pytest | 테스트 실행 |
pytest --cov | 코드 커버리지 생성 |
pytest -s | 코드에서 print문 혹은 로그출력 |
테스트는 다 마쳤고 깃헙에도 올렸다~
근데 나만 테스트하면 안되지. 회사동료도 해봐야지. 근데 pdm publish는 회사 보안상 안되는데 어떻게 하지?
그냥 깃헙에 있는걸로 설치받아 테스트하믄돼!
회사동료에게 알려주자 아래 코드를 입력해~~ (회사동료도 pytest가 있다는 전제하에)
# main에 있는 코드라면,
$ pip install git+{깃허브 HTTPS url}
# branch에 있는 코드라면,
$ pip install git+{깃허브 HTTPS url}@{BRANCH_NAME}
*부록
pdm은 여러가지 옵션을 지정할 수 있다. pytest 명령어를 커스텀할 수 있는데 아래 코드를 pyproject.toml에 추가하면 된다.
[tool.pdm.scripts]
{명령어 입력} = "pytest"
{명령어 입력} = "pytest --cov"
{명령어 입력} = "pytest -s"
#예시
test = "pytest"
ctest = "pytest --cov"
stest = "pytest -s"
이렇게하면 pytest --cov로 테스트해보고 싶을 때 ctest만 입력하면 정상적으로 실행이 된다.
결론, pytest를 사용하면 테스트를 실행하고 디버그할 수 있다.