Pytest 설정
`project` 디렉토리에`tests` 디렉토리를 생성하고 새롭게 아래 파일을 만들어줍니다.
1. __init__.py
2. conftest.py
3. test_ping.py
기본적으로 pytest는 prefix, suffix로 `test`가 붙어 있을 경우 자동으로 인식합니다.
예) `test_*.py` or `*_test.py`
만약 클래스를 만들어 사용한다면 클래스 이름의 시작은 `Test`로 만들어야 합니다.
# if a class is used, it must begin with Test
class TestFoo:
# test functions must begin with test_
def test_bar(self):
assert "foo" != "bar"
Fixtures
test_app 함수를 conftest 모듈에 정의합니다.
# project/tests/conftest.py
import os
import pytest
from starlette.testclient import TestClient
from app import main
from app.config import get_settings, Settings
def get_settings_override():
return Settings(testing=1, database_url=os.environ.get("DATABASE_TEST_URL"))
@pytest.fixture(scope="module")
def test_app():
# set up
main.app.dependency_overrides[get_settings] = get_settings_override
with TestClient(main.app) as test_client:
# testing
yield test_client
# tear down
여기서는 HTTPX 라이브러리를 사용하여 FastAPI 앱에 대해 요청하는 Starlette의 TestClient을 사용했습니다.
디팬던시 오버라이드를 위해서 get_settings_override 함수를 정의하고 이를 test_app 스코프에서 코드 처리해두었습니다.
참고로 Fixture는 테스트를 위해 재사용 가능한 개체입니다. 여기에는 Fixture가 얼마나 자주 호출되는지 범위가 연결되어 있습니다.
1. function - 테스트 함수당 한 번(기본값)
2. 클래스 - 테스트 클래스 당 한번
3. 모듈 - 테스트 모듈 당 한번
4. 세션 - 테스트 세션 당 한번
requirements.txt 파일에 추가 라이브러리 이름과 버전을 명시합니다.
httpx==0.26.0
pytest==7.4.4
requirements.txt 파일에 추가된 라이브러리는 런타임에 설치되는 것이 아닌 빌드 타임에 설치되므로 다시 도커 이미지를 빌드해주어야 합니다.
$ docker-compose up -d --build
컨테이너가 실행중인 상태에서 테스트를 실행합니다.
$ docker-compose exec web python -m pytest
결과는 아래와 같이 나타납니다.
=============================== test session starts ===============================
platform linux -- Python 3.12.1, pytest-7.4.4, pluggy-1.3.0
rootdir: /usr/src/app
plugins: anyio-4.2.0
collected 0 items
============================== no tests ran in 0.07s ==============================
Tests
test_ping.py 테스트를 해보겠습니다.
# project/tests/test_ping.py
from app import main
def test_ping(test_app):
response = test_app.get("/ping")
assert response.status_code == 200
assert response.json() == {"environment": "dev", "ping": "pong!", "testing": True}
unittest는 클래스를 요구하지만 pytest는 정의된 함수를 실행만 하면 됩니다.
fixture를 사용하기 위해서 argument를 전달하면 됩니다.
$ docker-compose exec web python -m pytest
=============================== test session starts ===============================
platform linux -- Python 3.12.1, pytest-7.4.4, pluggy-1.3.0
rootdir: /usr/src/app
plugins: anyio-4.2.0
collected 1 item
tests/test_ping.py . [100%]
================================ 1 passed in 0.13s ================================
Given-When-Then
테스트 코드를 작성할 때 여러 방법이 있지만, Given-When-Then 을 통해서 더 쉽고 간편하게 코드를 작성합니다.
Given | the state of the application before the test runs | setup code, fixtures, database state |
When | the behavior/logic being tested | code under test |
Then | the expected changes based on the behavior | asserts |
코드 예시는 아래와 같습니다.
def test_ping(test_app):
# Given
# test_app
# When
response = test_app.get("/ping")
# Then
assert response.status_code == 200
assert response.json() == {"environment": "dev", "ping": "pong!", "testing": True}
'프로그래밍 언어 > 파이썬' 카테고리의 다른 글
FastAPI를 이용한 TDD 개발 - 6 (0) | 2024.03.14 |
---|---|
FastAPI를 이용한 TDD 개발 - 5 (0) | 2024.03.14 |
FastAPI를 이용한 TDD 개발 - 3 (0) | 2024.03.12 |
FastAPI를 이용한 TDD 개발 - 2 (0) | 2024.03.11 |
FastAPI를 이용한 TDD 개발 - 1 (0) | 2024.03.10 |