py.test를 사용하여 python3 코드에 대한 테스트를하고 있습니다. 이 코드는 aiopg (Postgres에 대한 Asyncio 기반 인터페이스)를 사용하여 PostgreSQL 데이터베이스에 액세스합니다.py.test 픽스쳐와 asyncio coroutine을 섞기
내 주요 기대 :
모든 테스트 케이스는 새로운 asyncio 이벤트 루프에 액세스 할 수 있어야합니다.
너무 오래 실행되는 테스트는 시간 초과 예외로 중지됩니다.
모든 테스트 케이스는 데이터베이스 연결에 대한 액세스 권한을 가져야합니다.
테스트 사례 작성시 자신을 반복하고 싶지 않습니다.
py.test fixtures를 사용하면 원하는 결과에 가깝지만 모든 비동기 테스트 케이스에서 약간의 반복을해야합니다. 내가 지금까지 가지고있는 솔루션을 살 수 있지만 내부 코 루틴을 정의하는 성가신 얻을 수있는 모든 비동기 테스트의 run_timeout 라인을 추가
@pytest.fixture(scope='function')
def tloop(request):
# This fixture is responsible for getting a new event loop
# for every test, and close it when the test ends.
...
def run_timeout(cor,loop,timeout=ASYNC_TEST_TIMEOUT):
"""
Run a given coroutine with timeout.
"""
task_with_timeout = asyncio.wait_for(cor,timeout)
try:
loop.run_until_complete(task_with_timeout)
except futures.TimeoutError:
# Timeout:
raise ExceptAsyncTestTimeout()
@pytest.fixture(scope='module')
def clean_test_db(request):
# Empty the test database.
...
@pytest.fixture(scope='function')
def udb(request,clean_test_db,tloop):
# Obtain a connection to the database using aiopg
# (That's why we need tloop here).
...
# An example for a test:
def test_insert_user(tloop,udb):
@asyncio.coroutine
def insert_user():
# Do user insertion here ...
yield from udb.insert_new_user(...
...
run_timeout(insert_user(),tloop)
:
이처럼 내 코드는 모습입니다 내가 쓰는 것. 나는 섬세한 방법으로 이러한 장식을 만들기 위해 시도했지만 실패
@some_magic_decorator
def test_insert_user(udb):
# Do user insertion here ...
yield from udb.insert_new_user(...
...
:
나는 나의 테스트는 다음과 같이 다소보고 싶어요. 내 테스트가 보이는 경우보다 일반적으로, 같은 :
는@some_magic_decorator
def my_test(arg1,arg2,...,arg_n):
...
그런 다음 생성 기능 (데코레이터가 적용된 후)해야한다 :
def my_test_wrapper(tloop,arg1,arg2,...,arg_n):
run_timeout(my_test(),tloop)
주 내 시험의 일부가 UDB 외에 (다른기구를 사용하는 것이 예제), 그 조명기는 생성 된 함수의 인자로 나타나야한다. 그렇지 않으면 py.test가 그것들을 호출하지 않을 것이다.
wrapt과 decorator 파이썬 모듈을 사용하여 이러한 마법 장식자를 만들려고했지만 두 모듈 모두 my_test와 동일한 서명을 가진 함수를 만드는 데 도움이되는 것처럼 보입니다.이 경우에는 좋은 해결책이 아닙니다.
이것은 아마도 eval 또는 유사한 해킹을 사용하여 해결할 수 있지만 여기에 누락 된 우아한 것이 있는지 궁금합니다.
pytest_pycollect_makeitem 및 pytest_pyfunc_call에 대해 알지 못했습니다. 정말 멋진! 그런 것들은 어디에서 가져 왔습니까? 이 방법을 사용하려면 모든 테스트마다 다른 루프가 있는지 확인하고 코드에 run_timeout 함수를 추가하여 테스트가 중단되지 않도록하십시오. – real
pytest docs (http://pytest.org/latest/plugins.html#pytest-hook-reference)에서 코드를 파고 추측하는 것에서. IMHO 정말 잘 문서화되어 있지 않습니다. 어쩌면 공식 pytest-plugin으로 공개하겠습니다. –