Pytest의 아주 강력한 기능은 바로 fixture 기능이다. 간략하게 정리해 보자면 fixture는 테스트에 필요한 공통 자원들 또는 조건들을 미리 정의해둔 코드들이다. 이렇게 구현된 fixture는 필요에 따라 테스트 케이스마다 쉽게 가져와 사용할 수 있다. 일종의 디펜던시 인젝션 형태라고 이해하면 좋을듯하다.
fixture는 @pytest.fixture
데코레이터를 통해 정의할 수 있다. 또한 fixture는 conftest.py
에 정의해두면 모든 테스트 스위트에서 공통적으로 가져와 사용할 수 있다. 아래 코드는 fixture를 정의하는 예제 코드이다.
# conftest.py
@pytest.fixture
def set_userinfo():
""" username과 password를 리턴해주는 fixture """
username = "taekyeong@abcdefg.com"
password = "abcdefg1234"
return username, password
아래 코드는 사전에 정의된 set_userinfo
fixture를 사용하는 예제 코드이다. 테스트할 메서드의 인자로 fixture를 넘겨주면 된다.
import pytest
class TestSignIn:
def test_pytest(self, set_userinfo):
print(set_userinfo)
# 결과 : ("taekyeong@abcdefg.com", ("abcdefg1234"))
fixture는 실행되는 범위에 대해 정의할 수 있다. fixture는 설정한 scope 단위로 실행되며 총 5단계의 scope가 존재한다.
function(default) < class < module < package < session
@pytest.fixture(scope="function") : 함수 단위로 1회 실행 (이 값은 디폴트 값이며 @pytest.fixture 와 동일함)
@pytest.fixture(scope="class") : 클래스 단위로 1회 실행
@pytest.fixture(scope="module") : 파일(py) 단위로 1회 실행
@pytest.fixture(scope="package") : 패키지 단위로 1회 실행
@pytest.fixture(scope="session") : test session동안 1회 실행
fixture param을 통해 같은 테스트를 여러 차례 실행할 수 있다. 아래 예제를 보면 테스트 코드는 test_pytest
하나이지만 fixture param이 두 개 존재하여 총 2회의 테스트가 실행된 것을 알 수 있다.
@pytest.fixture(params=["abcd", "efgh"])
def first_fixture(request):
param = request.param
print(param)
def test_pytest(self, first_fixture):
print("test_pytest 실행 완료")
""" 결과 : abcd
test_pytest 실행 완료
efgh
test_pytest 실행 완료 """
fixture도 오버라이딩이 가능하다. 아래 예제 코드를 살펴보자. conftest.py
에 set_username
fixture가 존재하는 상태에서 TestSamlpe.py
모듈 안에 set_username
을 오버라이딩 하였다. 이처럼 같은 모듈 내에 존재하는 fixture가 있다면 conftest.py
에 존재하는 fixture보다 높은 우선순위를 가진다.
# conftest.py
@pytest.fixture
def set_username():
username = "taekyeong@abcdefg.com"
password = "abcdefg1234"
return username, password
# TestSamlpe.py
class TestSignIn:
@pytest.fixture
def set_username(self, set_username):
username = "taekyeong@123123.com" # 오버라이딩하여 username 재정의
password = set_username[1] # 부모 픽스쳐의 변수 그대로 사용
return username, password
def test_pytest(self, set_username):
print(set_username)
# 결과 : ('taekyeong@123123.com', 'abcdefg1234')