목차
- 최고급 통합actices
- pip를 통한 패키지 설치
- Python 테스트 발견 규칙
- 테스트 레이아웃 구조 및 임포트 규칙
- 애플리케이션 코드 외부에서 테스트
- 애플리케이션 코드 내에서의 테스트
- tox
pip를 통한 패키지 설치
개발을 위해, 우리는 [venv]를 통해 애플리케이션 및 의존성뿐만 아니라 pytest 패키지를 설치할 것을 권장합니다. 이는 시스템 Python 설치와의 격리된 환경을 보장합니다.
다음은 패키지 루트 디렉토리에 위치시킨 setup.py 파일의 최소 내용입니다:
from setuptools import setup, find_packages
setup(name="mypackage", packages=find_packages())
mypackage는 패키지의 이름입니다. 그런 다음, 같은 디렉토리에서 실행하여 패키지를 개발 모드로 설치할 수 있습니다:
pip install -e .
이 방법은 소스 코드(테스트 및 애플리케이션)를 변경하고 마음대로 테스트를 다시 실행할 수 있도록 합니다. 이는 python setup.py develop나 conda develop와 유사합니다.
Python 테스트 발견 규칙
Pytest는 다음과 같은 표준 테스트 발견 규칙을 구현합니다:
- 매개변수가 지정되지 않으면
testpaths가 구성되었을 경우 해당 디렉토리나 현재 디렉토리에서 수집을 시작합니다.또는, 명령줄 매개변수를 통해 디렉토리, 파일명 또는 노드 ID의 임의 조합을 사용할 수 있습니다. norecursedirs와 일치하지 않는 디렉토리까지 재귀 검색합니다.- 이러한 디렉토리에서
test_*.py또는*_test.py파일을 검색하고, 그들로부터 테스트 항목을 수집합니다: - 클래스 외부의
test_접두사를 가진 테스트 함수 또는 메서드 Test클래스 내에서test_접두사를 가진 테스트 함수 또는 메서드(초기화 메서드 없음)
표준 [Python 테스트 발견]을 customeize하는 방법示例에 대해 자세히 알아보세요.
Python 모듈 내에서, pytest는 또한 [unittest.TestCase] 상속을 통해 테스트를 발견합니다.
테스트 레이아웃 구조 및 임포트 규칙
pytest는 두 가지 주요한 테스트 레이아웃을 지원합니다:
애플리케이션 코드 외부에서 테스트
여러분이 많은 함수 테스트를 갖고 있거나, 애플리케이션 코드와 테스트를 분리하는 이유가 있다면, 애플리케이션 코드 외부에 추가 디렉토리를 만들고 테스트를 배치하는 것이 매우 유용할 수 있습니다:
setup.py
mypkg/
__init__.py
app.py
view.py
tests/
test_app.py
test_view.py
...
이 방법에는 다음과 같은 이점이 있습니다:
- 설치 후, 테스트는 설치된 버전을 대상으로 실행됩니다.
pip install - 설치 후, 로컬 소스 코드에 변경사항을 적용하고 테스트를 실행할 수 있습니다.
pip install --editable setup.py파일이 없고 Python이 현재 디렉토리를sys.path에 추가하여 패키지를 임포트할 때, 로컬 소스를 대상으로 테스트를 실행할 수 있습니다.python -m pytest``pip없이
주의: [pytest 임포트 메커니즘 및 sys.path / PYTHONPATH]에서
pytest와python -m pytest사이의 차이에 대해 더詳しく 알아보세요.
이 방법을 사용할 때, 테스트 파일은 반드시 고유한 이름을 가져야 합니다. pytest는 이 파일들을 최상위 모듈로 임포트하기 때문입니다. 즉, 테스트 파일들은 tests/ 디렉토리를 sys.path에 추가함으로써 test_app 및 test_view와 같이 최상위 모듈로 임포트됩니다.
동일한 이름의 테스트 모듈이 필요할 경우, tests 디렉토리와 하위 디렉토리에 __init__.py 파일을 추가하고 그 파일을 패키지로 만들 수 있습니다:
setup.py
mypkg/
...
tests/
__init__.py
foo/
__init__.py
test_view.py
bar/
__init__.py
test_view.py
이제 pytest는 tests.foo.test_view 및 tests.bar.test_view를 로드하여 동일한 이름의 모듈을 사용할 수 있습니다.그러나 이는 mypkg 패키지를 임포트할 때, 가상 환경 외부에서 테스트를 실행하는 도구(예: tox)와의 상호작용에 문제가 발생할 수 있습니다.
이와 같은 상황에서, [src] 애플리케이션 루트 패키지가 루트 디렉토리의 하위 디렉토리에 위치하도록 하는 레이아웃을 강하게 추천합니다:
setup.py
src/
mypkg/
__init__.py
app.py
view.py
tests/
__init__.py
foo/
__init__.py
test_view.py
bar/
__init__.py
test_view.py
이 레이아웃은 많은 함정을 피하고 많은 이점을 제공합니다. [Ionel Cristian Mărieş]의 설명이 상세합니다.
애플리케이션 코드 내에서의 테스트
테스트와 애플리케이션 모듈간에 직접적인 관계가 있고, 이를 애플리케이션과 함께 배포하고자 할 때, 애플리케이션 패키지 내부에 테스트 디렉토리를 배치하는 것이 유용합니다:
setup.py
mypkg/
__init__.py
app.py
view.py
test/
__init__.py
test_app.py
test_view.py
...
이 방법에서, 다음 옵션을 사용하여 쉽게 테스트를 실행할 수 있습니다:
pytest --pyargs mypkg
pytest는 설치된 위치에서 애플리케이션 패키지를 발견하고 테스트를 수집합니다.
이 방법은 [src] 섹션에서 설명한 레이아웃과도 함께 사용할 수 있습니다.
주의: Python 3 네임스페이스 패키지([PEP 420])를 사용할 수 있지만,
pytest는 디렉토리 구조에__init__.py파일이 있는지에 따라 테스트 패키지 이름을 발견합니다.추천 레이아웃 중 하나를 사용하고__init__.py파일을 삭제하면 Python 3.3 이상 버전에서 작동합니다. 그러나, [내부 테스트]에서 절대 임포트를 사용해야 합니다.
주의:
pytest가 파일 시스템을 탐색하며a/b/test_module.py와 같은 테스트 파일을 발견하면, 다음과 같이 임포트명을 결정합니다:
basedir: 첫 번째 "위로" 디렉토리가 되며, 이 디렉토리부터__init__.py가 없습니다.a와b중 하나가__init__.py를 갖고 있다면, 부모 디렉토리a가basedir이 됩니다.sys.path에basedir을 추가하여 테스트 모듈을 완전한 임포트명으로 임포트합니다.이는 디렉토리 및 파일명을 임포트명으로 직접 매핑해야 한다는 점을 주의해야 합니다.
이와 같은 진화적인 임포트 기술은 대형 프로젝트에서 여러 테스트 모듈이 상호 임포트될 때 발생할 수 있는 문제를 방지하는 데 도움이 됩니다.
tox
테스트가 실제 패키지에 통합되었는지 확인하고 싶을 때, [tox]와 같은 virtualenv 테스트 자동화 도구를 사용해 보세요. tox는 미리 정의된 의존성 세트를 사용하여 virtualenv 환경을 만들고, 미리 구성된 테스트 명령을 실행합니다.이는 설치된 패키지를 대상으로 테스트를 실행함으로써 패키징 오류를 감지하는 데 도움이 됩니다.
[setuptools 통합]
pytest-runner 플러그인을 사용하여 setuptools 기반 프로젝트에 테스트 실행을 통합할 수 있습니다.
setup.py 파일에 다음을 추가하세요:
from setuptools import setup
setup(
# ...,
setup_requires=["pytest-runner", ...],
tests_require=["pytest", ...],
# ...,
)
그리고 setup.cfg 파일에 아래와 같이 암호를 추가하세요:
[aliases]
test=pytest
만약에, 다음 명령을 실행하면:
python setup.py test
이것은 pytest-runner를 통해 테스트를 실행합니다. 이 방법은 pytest를 미리 설치하지 않아도 됩니다. test 명령을 실행할 때 항상 pytest가 설치될 것입니다.
setup.cfg 파일에 [tool:pytest] 섹션에 추가 pytest 인자도 지정할 수 있습니다:
[tool:pytest]
addopts = --verbose
python_files = testing/*/*.py
수동 통합
pytest-runner를 사용하지 않으려는 경우, 자체 setuptools 테스트 커맨드를 작성하여 pytest를 호출할 수 있습니다.
import sys
from setuptools.command.test import test as TestCommand
class PyTest(TestCommand):
user_options = [("pytest-args=", "a", "Arguments to pass to pytest")]
def initialize_options(self):
TestCommand.initialize_options(self)
self.pytest_args = ""
def run_tests(self):
import shlex
import pytest
errno = pytest.main(shlex.split(self.pytest_args))
sys.exit(errno)
setup(
# ...,
tests_require=["pytest"],
cmdclass={"pytest": PyTest},
)
이제, 다음 명령을 실행하면:
python setup.py test
이것은 필요에 따라 pytest를 설치하고 예상대로 테스트를 실행합니다. --pytest-args나 -a 명령줄 옵션을 통해 pytest에 대한 추가 매개변수도 전달할 수 있습니다. 예를 들어:
python setup.py test -a "--durations=5"
이는 pytest --durations=5와 동일합니다.