pytest
pytest
pytest
는 Python에서 가장 널리 사용되는 테스트 프레임워크 중 하나로, 유닛테스트, 통합테스트 등 다양한 테스트를 쉽고 유연하게 작성하고 실행할 수 있도록 도와줍니다. 이 패키지는 매우 직관적이고 간결한 문법으로 제공하여, 복잡한 테스트 코드를 단순하게 작성할 수 있습니다. pytest
는 기본적으로 python의 내장 unittest
프레임워크보다 더 많은 기능과 유연성을 제공합니다.
주요 특징
- 간결한 테스트 함수:
pytest
는 클래스나 메서드 기반이 아닌, 단순한 함수로 테스트를 작성할 수 있습니다. 별도의 클래스나 setup, teardown 메서드를 작성할 필요 없이 간단한 함수로 테스트가 가능합니다.
def test_addition():
assert 1+1 == 2
================================ test session starts =================================
platform linux -- Python 3.10.12, pytest-8.3.2, pluggy-1.5.0
rootdir: /data/dev/pytest
plugins: anyio-4.4.0
collected 1 item
test_addition.py . [100%]
================================= 1 passed in 0.01s ==================================
-
확장성:
pytest
는 플러그인 시스템을 지원하여, 기본 기능을 확장할 수 있습니다. 예를 들어,pytest-cov
플러그인을 사용하면 코드 커버리지를 측정할 수 있고,pytest-django
와 같은 플러그인은 Django와 함께 테스트를 쉽게 작성할 수 있도록 도와줍니다. -
강력한 assertion 리포트:
pytest
는 테스트 실패 시 매우 읽기 쉬운 리포트를 제공해 디버깅을 쉽게 할 수 있습니다.
def test_failing():
assert 1+1 == 3
================================================================ test session starts ================================================================
platform linux -- Python 3.10.12, pytest-8.3.2, pluggy-1.5.0
rootdir: /data/dev/pytest
plugins: anyio-4.4.0
collected 3 items
test_failing.py F [ 33%]
test_fixture.py . [ 66%]
test_sample.py . [100%]
===================================================================== FAILURES ======================================================================
___________________________________________________________________ test_failing ____________________________________________________________________
def test_failing():
> assert 1+1 == 3
E assert (1 + 1) == 3
test_failing.py:2: AssertionError
============================================================== short test summary info ==============================================================
FAILED test_failing.py::test_failing - assert (1 + 1) == 3
============================================================ 1 failed, 2 passed in 0.08s ============================================================
-
테스트 Fixture:
pytest
는 테스트 실행 전에 설정 작업을 하고, 실행 후 정리 작업을 할 수 있도록 “픽스처”라는 기능을 제공합니다. 이를 통해 중복 코드를 줄이고, 테스트 환경을 설정하는 코드를 재사용할 수 있습니다.- 주요 특징
- 설정 및 초기화: 테스트 함수에서 필요한 데이터나 환경을 미리 설정할 수 있습니다.
- 재사용 가능: 여러 테스트에서 동일한 설정을 재사용할 수 있습니다.
- 자동 주입: 테스트 함수에서 직접 픽스처를 호출하지 않아도, pytest가 자동으로 해당 함수에 전달합니다.
- 스코프 관리: 픽스처의 수명을
function
,class
,module
,session
단위로 설정할 수 있습니다.
import pytest @pytest.fixture def sample_data(): return {"name": "Alice", "age": 25} def test_sample_data(sample_data): assert sample_data['name'] == "Alice" assert sample_data['age'] == 25
위 코드에서
sample_data()
는 픽스처로 정의되었으며,pytest
는test_sample_data
함수가 실행될 때 해당 픽스처를 자동으로 주입합니다. 이 경우, 테스트 함수는 픽스처에서 반환된 데이터를 사용하게 됩니다.- Fixture Scope
- fixture의 기본 스코프는
function
입니다. 즉, 각 테스트 함수마다 새로운 인스턴스가 생성됩니다.pytest
는 다양한 스코프를 지원하며, 이를 통해 픽스처가 테스트 함수, 클래스, 모듈 또는 세션단위로 재사용되도록 설정할 수 있습니다.
- fixture의 기본 스코프는
import pytest @pytest.fixture(scope = "module") def sample_data(): print("픽스터 설정") return {"name": "Alice", "age": 25} def test_sample_data_1(sample_data): assert sample_data['name'] == "Alice" def test_sample_data_2(sample_data): assert sample_data['age'] == 25
위 코드에서
scope="module"
로 설정된 픽스처는 모듈 내에서 한 번만 생성됩니다. 따라서 두 개의 테스트 함수(test_sample_data_1
,test_sample_data_2
)에서 같은 픽스처 인스턴스를 공유하게 됩니다.print
문을 통해 픽스처가 몇 번 호출되는지 확인할 수 있습니다.- 여러 픽스처 사용하기
하나의 테스트 함수에서 여러 픽스처를 사용할 수도 있습니다.
pytest
는 자동으로 필요한 픽스처들을 각 테스트 함수에 전달합니다.
import pytest @pytest.fixture def user_data(): return {"name": "Alice"} @pytest.fixture def age_data(): return {"age": 25} def test_multiple_fixtures(user_data, age_data): assert user_data['name'] == "Alice" assert age_data['age'] == 25
- 주요 특징
-
매개변수화된(Parameterized) 테스트: 동일한 테스트 함수를 다양한 입력값으로 여러 번 실행할 수 있도록 매개벼수화 기능을 제공합니다. 이를 통해 중복된 테스트 코드를 줄일 수 있습니다.
@pytest.mark.parametrize("input, expected", [
(1+1, 2),
(1+2, 3),
(1+3, 4)
])
def test_addition(input, expected):
assert input == expected
- 마커 (Markers):
pytest
는 테스트를 그룹화하거나 특정 조건에 따라 테스트를 실행할 수 있는 마커 기능을 제공합니다. 예를들어, 특정 테스트를 건너뛰거나, 속도에 따라 그룹화하여 실행할 수 있습니다.
@pytest.mark.skip(reason = "테스트를 건너뜁니다.")
def test_skip():
assert 1 == 1
@pytest.mark.slow
def test_slow_function():
# 느리게 실행되는 테스트
assert slow_function() == True