pytest
https://docs.pytest.org/en/stable/
1 2 3 4 5 6 def inc (x ): return x + 1 def test_answer (): assert inc(3 ) == 5
함수, 파일명에 _test, test_ 클래스명에 Test... 문자열이 들어가 있으면 pytest 가 자동으로 테스트 함수임을 감지한다.
1 2 3 4 5 6 7 8 9 10 11 pytest --version pytest my_python.py
@pytest.mark.parametrize 여러개의 입력 파라미터로 지정할 수 있다.
1 2 3 4 5 6 7 @pytest.mark.parametrize("input, expected" , [ (1 , 2 ), (2 , 3 ), (3 , 4 ), ] )def test_increment (input , expected ): assert input + 1 == expected
@pytest.mark.skip 테스트 진행하지 않고 skip
1 2 3 @pytest.mark.skip(reason="not implemented yet" ) def test_not_implemented (): assert False
@pytest.mark.skipif 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 skip_flag = True @pytest.mark.skipif(skip_flag, reason="feature flag is disabled" ) def test_skip_flag (): assert True @pytest.mark.skipif(sys.version_info < (3 , 7 ), reason="requires Python 3.7 or higher" ) def test_python_version (): assert True @pytest.mark.skipif(os.getenv('SKIP_TEST' ) == 'true' , reason="SKIP_TEST environment variable is set" ) def test_skip_based_on_env_var (): assert True
외부 의존성에 맞춰 테스트
1 2 3 4 5 6 7 8 9 10 def is_service_available (): try : response = requests.get("https://example.com" ) return response.status_code == 200 except requests.RequestException: return False @pytest.mark.skipif(not is_service_available( ), reason="external service is not available" ) def test_external_service (): assert True
@pytest.fixture 모든 테스트에 필요한 공통 설정을 입력 파라미터로 지정할 수 있다.@pytest.fixture scope 별로 공통설정에서 반환한 값이 공유될 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 @pytest.fixture def sample_data (): return {"key" : "value" } def test_sample_data (sample_data ): assert sample_data["key" ] == "value" @pytest.fixture def user (): return {"username" : "test_user" } @pytest.fixture def password (): return "secure_password" def test_user_login (user, password ): assert user["username" ] == "test_user" assert password == "secure_password" @pytest.fixture(autouse=True ) def auto_setup (): print ("Automatically setting up" ) def test_auto_setup_1 (): assert True def test_auto_setup_2 (): assert True
1 2 3 4 5 6 7 8 9 10 11 @pytest.fixture def username (): return "test_user" @pytest.fixture def user (username ): return {"username" : username} def test_user (user ): assert user["username" ] == "test_user"
fixture 와 yield 테스트 수행시 공통적인 setup & teardown(설정 & 해제) 작업을 @pytest.fixture 를 통해 정의할 수 있다.
file 열기, file 반남 형태의 테스트를 수행할 때 자주 사용함.
1 2 3 4 5 6 7 8 9 10 @pytest.fixture def setup_and_teardown (): data = {"key" : "value" } yield data print ("Teardown" ) def test_setup_and_teardown (setup_and_teardown ): assert setup_and_teardown["key" ] == "value"
setup code 에서 데이터를 가져오고, 테스트가 수행 완료된 후 teardown code 를 수행하여 후처리를 진행한다.
fixture scope @pytest.fixture scope 옵션은 네 가지 범위를 지원한다.
function (기본값): 함수 내에서만 사용 가능
class: 클래스 내부 정의된 테스트 함수간 공유
module: 파일내부 정의된 테스트 함수간 공유
package: 패키지(폴더)내부 정의된 테스트 함수간 공유
session: 테스트 진행동안 공유
1 2 3 4 5 6 7 8 9 10 11 12 @pytest.fixture(scope="function" ) def resource (): return [] def test_function_scope_1 (resource ): resource.append(1 ) assert resource == [1 ] def test_function_scope_2 (resource ): resource.append(2 ) assert resource == [2 ]
1 2 3 4 5 6 7 8 9 10 11 12 13 @pytest.fixture(scope="class" ) def resource (): return [] class TestClassScope : def test_class_scope_1 (self, resource ): resource.append(1 ) assert resource == [1 ] def test_class_scope_2 (self, resource ): resource.append(2 ) assert resource == [1 , 2 ]
1 2 3 4 5 6 7 8 9 10 11 12 @pytest.fixture(scope="module" ) def resource (): return [] def test_module_scope_1 (resource ): resource.append(1 ) assert resource == [1 ] def test_module_scope_2 (resource ): resource.append(2 ) assert resource == [1 , 2 ]
@pytest.mark.usefixtures 테스트 함수 매개변수로 @pytest.fixture 로 정의한 공용설정 메서드를 삽입해야 했지만@pytest.mark.usefixtures 를 사용하면 테스트 함수 위에 decorator 만 추가해주면 된다.
대신 공통 설정에 대한 값은 가져올 수 없다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 @pytest.fixture def setup_data (): print ("Setting up data" ) @pytest.mark.usefixtures("setup_data" ) def test_example (): assert True @pytest.fixture def setup_data (): print ("Setting up data" ) @pytest.fixture def setup_database (): print ("Setting up database" ) @pytest.mark.usefixtures("setup_data" , "setup_database" ) class TestMultipleFixtures : def test_method_1 (self ): assert True def test_method_2 (self ): assert True
pytest-timeout 1 pip install pytest-timeout
pytest.ini 파일 설정 하여 모든 테스트에 timeout 관련 설정을 할 수 있다.
1 2 3 4 [pytest] markers = slow: 느린 테스트 timeout = 5 # 기본 타임아웃 설정 (필요 시)
@pytest.mark.timeout 해당 시간안에 테스트가 종료되지 않을 경우 오류로 판단.
1 2 3 4 5 6 7 8 9 10 @pytest.mark.timeout(2 ) def test_with_timeout (): time.sleep(1 ) assert True @pytest.mark.timeout(2 ) def test_with_timeout_failure (): time.sleep(3 ) assert True
@pytest.mark.xfail 실패해도 결과가 실패로 간주되지 않는다
실패했을 때 failed 로 처리되지 않고 ignored 로 처리됨
1 2 3 @pytest.mark.xfail def test_not_yet_implemented (): assert False