pytest 사용법

보람찬하루·2024년 10월 8일
1

pytest로 테스트 코드를 작성해보자

1. pytest

  • pytest는 Python의 테스팅 프레임워크 중 하나로, 단위 테스트(unit tests)부터 기능 테스트(functional tests)까지 다양한 종류의 테스트를 쉽게 작성할 수 있습니다.
  • 간결하고 강력한 테스트 코드를 작성할 수 있도록 다양한 기능을 제공하며, 플러그인 시스템을 통해 확장이 가능합니다.
  • 테스트는 독립적이어야 하고 각 테스트는 다른 테스트의 결과에 영향을 받지 않아야 합니다.
  • 테스트 함수 이름은 명확하고, 어떤 동작을 테스트하는지 알 수 있게 작성합니다.
  • Fixtures를 활용하여 설정 코드를 재사용하고 가독성을 높입니다.
  • pytesttest_로 시작하거나 _test로 끝나는 함수들을 자동으로 발견하고 실행합니다.

2. 설치 방법

pip install pytest

3. 테스트

3.1 작성

  • 테스트 함수는 test_로 시작해야 합니다.
  • assert 구문을 사용하여 테스트가 통과되었는지 여부를 확인합니다.

예제 코드:

# test_sample.py

def test_addition():
    assert 1 + 1 == 2

def test_subtraction():
    assert 2 - 1 == 1
  • 모듈, 클래스, 함수 단위로 테스트를 구성하여 테스트 코드를 체계화합니다. 이렇게 하면 특정 모듈이나 기능을 선택적으로 테스트할 수 있습니다. 예제: 모듈 내부의 클래스별로 테스트를 그룹화
    python
    코드 복사
    # test_calculator.py
    class TestAddition:
        def test_add_positive(self):
            assert add(1, 2) == 3
    
        def test_add_negative(self):
            assert add(-1, -1) == -2
    
    class TestSubtraction:
        def test_subtract(self):
            assert subtract(5, 3) == 2
    

3.2 실행

  • 테스트를 실행하려면 터미널에서 pytest 명령을 사용합니다.
  • 특정 파일만 테스트하려면:
pytest test_sample.py
  • 테스트 실행 옵션
    • v: 자세한 테스트 진행 상황 출력

    • q: 간략한 테스트 결과만 출력

    • pytest -k "expression": 지정한 키워드와 일치하는 테스트만 실행. 예: k "addition".

    • -maxfail=N: N개의 테스트가 실패하면 실행 중단.

    • -tb=short: 에러 발생 시 간략한 traceback 표시.

      • pytest --pdb: 테스트 실패 시 디버깅 모드로 진입.
      • pytest --fixtures: 사용할 수 있는 fixture 목록 표시.
      • pytest --durations=N: 실행 시간이 오래 걸리는 상위 N개의 테스트를 표시.
    • -junitxml 옵션을 사용하면 테스트 결과를 XML 형식으로 저장.

      예제:

      pytest -v --maxfail=2 --tb=short
      pytest --junitxml=report.xml

3.3 해석

  • .: 테스트가 성공한 경우
  • F: 테스트가 실패한 경우
  • 테스트 결과 출력에서 실패한 테스트의 상세 내용과 어디에서 오류가 발생했는지 볼 수 있습니다.

4. 기능

4.1 @pytest.mark.parametrize

  • 동일한 테스트 함수에 여러 입력 값을 테스트하려면 @pytest.mark.parametrize를 사용합니다.

예제:

import pytest

@pytest.mark.parametrize("a, b, expected", [(1, 2, 3), (2, 3, 5), (3, 5, 8)])
def test_addition(a, b, expected):
    assrt a + b == expected

4.2 pytest.raises

  • 예외가 발생하는지 테스트하려면 pytest.raises 컨텍스트 관리자를 사용합니다.

예제:

import pytest

def test_divide_by_zero():
    with pytest.raises(ZeroDivisionError):
        1 / 0

4.3@pytest.fixture

  • Fixtures는 반복적으로 사용하는 준비 코드를 재사용할 수 있게 해줍니다.
  • @pytest.fixture 데코레이터를 사용하며, 테스트 함수에 인자로 넘겨주어 사용할 수 있습니다.

예제:

import pytest

@pytest.fixture
def sample_list():
    return [1, 2, 3, 4, 5]

def test_list_sum(sample_list):
    assert sum(sample_list) == 15
  • Fixture의 스코프 조절
    • scope 매개변수를 사용하여 fixture의 생명주기를 조절할 수 있습니다 (function, module, class, session).

    • 데이터베이스 연결 같은 자원을 효율적으로 사용하려면 적절한 스코프를 선택합니다.

      @pytest.fixture(scope="module")
      def db_connection():
          conn = create_db_connection()
          yield conn
          conn.close()
  • Fixture를 다른 Fixture에서 사용하기
    • 복잡한 테스트 환경에서는 여러 fixture를 조합하여 사용할 수 있습니다.

      @pytest.fixture
      def user_data():
          return {"name": "John", "age": 30}
      
      @pytest.fixture
      def user(user_data):
          return User(**user_data)
      
      def test_user_age(user):
          assert user.age == 30
    • 서로 연관된 fixture를 분리하여 모듈화하면 테스트를 더욱 유연하고 가독성 있게 만들 수 있습니다.

4.4 @pytest.mark

  • @pytest.mark.<name>를 사용해 테스트를 그룹화하고 특정 그룹만 실행할 수 있습니다. 예를 들어, 느린 테스트나 특정 조건이 필요한 테스트를 분리할 수 있습니다.

예제:

import pytest

@pytest.mark.slow
def test_large_computation():
    assert large_computation() == expected_value

실행 시 특정 마커의 테스트만 실행:

pytest -m slow
  • Custom Marker
    • 프로젝트 수준에서 마커를 정의하여 특정 유형의 테스트를 구분하고 관리할 수 있습니다. pytest.ini 또는 pyproject.toml 파일에서 마커를 정의합니다.

      pytest.ini 파일 예제:

      markers =
          slow: 느린 테스트
          db: 데이터베이스 관련 테스트

5. 플러그인

  • pytest는 플러그인 시스템을 통해 확장 가능합니다. 일부 유용한 플러그인은 다음과 같습니다:
    • pytest-cov: 테스트 코드의 커버리지를 확인할 수 있습니다.
      pip install pytest-cov
      pytest --cov=my_module
    • pytest-xdist: 멀티코어를 활용하여 테스트 병렬 실행을 지원합니다.
      pip install pytest-xdist
      pytest -n auto
profile
를 만들어 가자

0개의 댓글