수색…


py.test 설정하기

py.test 는 Python에서 사용할 수있는 여러 타사 테스트 라이브러리 중 하나입니다. pip 와 함께 설치할 수 있습니다.

pip install pytest

테스트 코드

projectroot/module/code.py 에서 추가 함수를 테스트한다고 가정 projectroot/module/code.py .

# projectroot/module/code.py
def add(a, b):
    return a + b

테스트 코드

projectroot/tests/test_code.py 에 테스트 파일을 projectroot/tests/test_code.py . 파일 test_시작해야 테스트 파일로 인식됩니다.

# projectroot/tests/test_code.py
from module import code


def test_add():
    assert code.add(1, 2) == 3

테스트 실행하기

projectroot 에서 py.test 를 실행하면됩니다.

# ensure we have the modules
$ touch tests/__init__.py
$ touch module/__init__.py
$ py.test
================================================== test session starts ===================================================
platform darwin -- Python 2.7.10, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
rootdir: /projectroot, inifile:
collected 1 items

tests/test_code.py .

================================================ 1 passed in 0.01 seconds ================================================

실패한 테스트

실패한 테스트는 무엇이 잘못되었는지에 대한 유용한 결과를 제공합니다.

# projectroot/tests/test_code.py
from module import code


def test_add__failing():
    assert code.add(10, 11) == 33

결과 :

$ py.test
================================================== test session starts ===================================================
platform darwin -- Python 2.7.10, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
rootdir: /projectroot, inifile:
collected 1 items

tests/test_code.py F

======================================================== FAILURES ========================================================
___________________________________________________ test_add__failing ____________________________________________________

    def test_add__failing():
>       assert code.add(10, 11) == 33
E       assert 21 == 33
E        +  where 21 = <function add at 0x105d4d6e0>(10, 11)
E        +    where <function add at 0x105d4d6e0> = code.add

tests/test_code.py:5: AssertionError
================================================ 1 failed in 0.01 seconds ================================================

테스트 설비 소개

더 복잡한 테스트는 테스트 할 코드를 실행하기 전에 설정해야 할 경우가 있습니다. 테스트 기능 자체에서이 작업을 수행 할 수는 있지만 대규모 테스트 기능으로 인해 결국 설정이 중지되고 테스트가 시작되는 위치를 알기가 어렵습니다. 다양한 테스트 기능간에 중복 된 설정 코드를 많이 얻을 수도 있습니다.

우리의 코드 파일 :

# projectroot/module/stuff.py
class Stuff(object):
    def prep(self):
        self.foo = 1
        self.bar = 2

테스트 파일 :

# projectroot/tests/test_stuff.py
import pytest
from module import stuff


def test_foo_updates():
    my_stuff = stuff.Stuff()
    my_stuff.prep()
    assert 1 == my_stuff.foo
    my_stuff.foo = 30000
    assert my_stuff.foo == 30000


def test_bar_updates():
    my_stuff = stuff.Stuff()
    my_stuff.prep()
    assert 2 == my_stuff.bar
    my_stuff.bar = 42
    assert 42 == my_stuff.bar

이것들은 꽤 간단한 예제이지만, Stuff 객체가 더 많은 셋업을 필요로한다면, 다루기 힘들어 질 것입니다. 우리는 테스트 케이스 사이에 중복 된 코드가 있다는 것을 알았으므로 먼저이를 별도의 함수로 리팩토링하자.

# projectroot/tests/test_stuff.py
import pytest
from module import stuff


def get_prepped_stuff():
    my_stuff = stuff.Stuff()
    my_stuff.prep()
    return my_stuff


def test_foo_updates():
    my_stuff = get_prepped_stuff()
    assert 1 == my_stuff.foo
    my_stuff.foo = 30000
    assert my_stuff.foo == 30000


def test_bar_updates():
    my_stuff = get_prepped_stuff()
    assert 2 == my_stuff.bar
    my_stuff.bar = 42
    assert 42 == my_stuff.bar

이것은 더 나아 보이지만 우리는 여전히 my_stuff = get_prepped_stuff() 호출이 우리의 테스트 함수를 혼란 my_stuff = get_prepped_stuff() 합니다.

py.test 구출 구조!

Fixture는 테스트 설정 기능의 훨씬 강력하고 유연한 버전입니다. 우리가 여기서 활용하는 것보다 훨씬 많은 일을 할 수 있지만, 한 번에 한 걸음 씩 나아갈 것입니다.

먼저 get_prepped_stuffprepped_stuff 라는 조명기로 변경합니다. 나중에 테스트 함수에서 조명기가 사용되는 방법 때문에 동사가 아닌 명사로 조명기의 이름을 지정하려고합니다. @pytest.fixture 는이 특정 함수가 정규 함수가 아닌 고정 장치로 처리되어야 함을 나타냅니다.

@pytest.fixture
def prepped_stuff():
    my_stuff = stuff.Stuff()
    my_stuff.prep()
    return my_stuff

이제 우리는 fixture를 사용하도록 테스트 함수를 업데이트해야합니다. 이는 조명기 이름과 정확하게 일치하는 매개 변수를 정의에 추가하여 수행됩니다. py.test가 실행되면 테스트를 실행하기 전에 조명기를 실행 한 다음 해당 매개 변수를 통해 조명기의 반환 값을 테스트 함수로 전달합니다. (조명기는 값을 리턴 할 필요 가 없으며, 외부 자원 호출, 파일 시스템 정렬, 데이터베이스에 값 입력, 설정 테스트에 필요한 모든 것)와 같은 다른 설정 작업을 수행 할 수 있습니다.

def test_foo_updates(prepped_stuff):
    my_stuff = prepped_stuff
    assert 1 == my_stuff.foo
    my_stuff.foo = 30000
    assert my_stuff.foo == 30000


def test_bar_updates(prepped_stuff):
    my_stuff = prepped_stuff
    assert 2 == my_stuff.bar
    my_stuff.bar = 42
    assert 42 == my_stuff.bar

이제 우리는 명사로 이름을 지은 이유를 알 수 있습니다. 하지만 my_stuff = prepped_stuff 라인은 꽤 쓸모가 없으므로 대신 prepped_stuff 직접 사용하도록합시다.

def test_foo_updates(prepped_stuff):
    assert 1 == prepped_stuff.foo
    prepped_stuff.foo = 30000
    assert prepped_stuff.foo == 30000


def test_bar_updates(prepped_stuff):
    assert 2 == prepped_stuff.bar
    prepped_stuff.bar = 42
    assert 42 == prepped_stuff.bar

이제 우리는 비품을 사용하고 있습니다! 우리는 조명기의 범위를 변경함으로써 더 나아갈 수 있습니다 (그래서 그것은 테스트 기능마다 한 번만 실행되는 것이 아니라 테스트 모듈 또는 테스트 스위트 실행 세션마다 한 번만 실행됩니다), 다른 조명기를 사용하는 조명기를 구축하고 조명기를 매개 변수화함으로써 (조명기 및 모든 해당 조명기를 사용하는 테스트는 조명기에 지정된 각 매개 변수에 대해 한 번 여러 번 실행됩니다.) 앞에서 언급했듯이 조명기 모듈에서 값을 읽는 조명기는 조명기가 일반 설치 기능보다 훨씬 강력하고 유연성이 뛰어납니다.

검사가 끝나면 청소.

우리 코드가 커졌고 Stuff 객체가 특별한 정리가 필요하다고 가정 해 봅시다.

# projectroot/module/stuff.py
class Stuff(object):
def prep(self):
    self.foo = 1
    self.bar = 2

def finish(self):
    self.foo = 0
    self.bar = 0

모든 테스트 함수의 맨 아래에 정리를 호출 할 수있는 코드를 추가 할 수 있지만 픽스쳐는이를 수행하는 더 좋은 방법을 제공합니다. 조명기에 함수를 추가하고이를 파이널 라이저 로 등록하면, 파이널 라이저를 사용하는 테스트가 완료된 후에 파이널 라이저 함수의 코드가 호출됩니다. 조명기의 범위가 하나의 함수 (모듈이나 세션과 같은)보다 큰 경우 범위의 모든 테스트가 완료된 후에 파이널 라이저가 실행되므로 모듈이 실행 완료되거나 전체 실행 세션이 끝난 후에 실행됩니다 .

@pytest.fixture
def prepped_stuff(request):  # we need to pass in the request to use finalizers
    my_stuff = stuff.Stuff()
    my_stuff.prep()
    def fin():  # finalizer function
        # do all the cleanup here
        my_stuff.finish()
    request.addfinalizer(fin)  # register fin() as a finalizer
    # you can do more setup here if you really want to
    return my_stuff

함수 내에서 파이널 라이저 함수를 사용하는 것은 언뜻보기에 이해하기 어렵습니다. 특히 복잡한 픽스처가있는 경우 더욱 그렇습니다. 대신에 yield fixture 를 사용하여 사람이 읽을 수있는 실행 흐름으로 동일한 작업을 수행 할 수 있습니다. 유일한 차이점은 대신 사용하는 것입니다 return 우리가 사용 yield 설치 완료 및 제어 테스트 기능으로 이동해야하는 고정 부분에서, 다음 이후에 모든 정리 코드를 추가 yield . 우리는 또한 그것을 yield_fixture py.test가 그것을 처리하는 방법을 안다.

@pytest.yield_fixture
def prepped_stuff():  # it doesn't need request now!
    # do setup
    my_stuff = stuff.Stuff()
    my_stuff.prep()
    # setup is done, pass control to the test functions
    yield my_stuff
    # do cleanup 
    my_stuff.finish()

그리고 이것으로 인스 트루먼 트 테스트 픽스쳐가 마무리되었습니다!

더 자세한 정보는 공식 py.test fixture 문서공식 yield fixture documentation을보십시오.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow