2013-08-05 8 views
10

나는 py.test 2.2.4을 사용하고 다음과 같이 내을 testcases가 구성되어 있습니다 :이 설정에@ pytest.mark를 기본 클래스와 함께 사용하는 방법은 무엇입니까?

import pytest 

class BaseTests(): 
    def test_base_test(self): 
     pass 

@pytest.mark.linuxonly 
class TestLinuxOnlyLocal(BaseTests): 
    pass 

@pytest.mark.windowsonly 
class TestWindowsOnly(BaseTests): 
    pass 

class TestEverywhere(BaseTests): 
    pass 

문제는 첫 번째 클래스의 장식이 두 번째 클래스로 유출된다는 점이다. 나는 conftest.py를 만들 때 다음과 같이

$ py.test --capture=no 
========================================== test session starts =========================================== 
platform linux2 -- Python 2.7.3 -- pytest-2.2.4 
collected 3 items 

test_cases.py 
TestLinuxOnlyLocal.test_base_test keywords: {'linuxonly': <MarkInfo 'linuxonly' args=() kwargs={}>, 'test_base_test': True} 
. 
TestWindowsOnly.test_base_test keywords: {'linuxonly': <MarkInfo 'linuxonly' args=() kwargs={}>, 'test_base_test': True, 'windowsonly': <MarkInfo 'windowsonly' args=() kwargs={}>} 
Skipped: Windows only test 
s 
TestEverywhere.test_base_test keywords: {'linuxonly': <MarkInfo 'linuxonly' args=() kwargs={}>, 'test_base_test': True, 'windowsonly': <MarkInfo 'windowsonly' args=() kwargs={}>} 
Skipped: Windows only test 
s 

================================== 1 passed, 2 skipped in 0.01 seconds =================================== 

그래서 내가 이해하고자하는 것이 가능 방법 :

import pytest 
import sys 

def pytest_runtest_setup(item): 
    print "\n %s keywords: %s" % (item.getmodpath(), item.keywords) 
    skip_message = None 
    if 'windowsonly' in item.keywords and not sys.platform.startswith('win'): 
     skip_message = "Skipped: Windows only test" 

    if 'linuxonly' in item.keywords and not sys.platform.startswith('linux'): 
     skip_message = "Skipped: Linux only test" 

    if skip_message is not None: 
     print skip_message 
     pytest.skip(skip_message) 

하는 난이 출력이 표시 쌓아 것으로 보인다 보여줍니다 설정 실행하면 이 마킹들이 서브 클래스들 사이에서 유출되고 이것이 어떻게 해결 될 수 있는지 (테스트 케이스들은 기본 클래스에 살지만 서브 클래스들은 필요한 플랫폼 추상화를 설정할 것임).

답변

4

: 당신은에 할 수 있습니다 py.test는 항목 키워드에 즉시 포함하는 클래스를 추가하기 때문에


간단한 해결책은 클래스 이름에 대해 비교 될 수 이

win32only = pytest.mark.skipif("sys.platform != 'win32'") 

을 :: 다음 그냥으로는 Win32 전용 테스트를 장식 같은 pytest.mark.skipif 표현을 정의 ::

을 당신은 어쩌면 그냥 :: 정상적인 테스트 클래스에 "BaseTests"를 돌 수 있었다

class TestCrossPlatform: 
    def test_base_tests(...): 
     ... 

즉 어떤 상속을 피하기 경우 0

@win32only 
def test_something(...): 

또 다른 질문은? 그런 다음 테스트에서 픽스쳐가 필요하면 테스트 모듈에서 테스트 픽스쳐를 정의하고 테스트 기능 (플랫폼 간 또는 플랫폼 별)에서이를 수락 할 수 있습니다 (pytest fixture docs 참조). 하지만 pytest-2.3 시리즈 (특히 2.4)에있는 조명기와 관련하여 많은 개선이 있었기 때문에 pytest-2.3.5을 사용해야합니다.

9

pytest는 다른 Python 테스트 프레임 워크 (예 : unittest)보다 테스트에 더 많은 기능 지향 접근 방식을 사용하므로 클래스는 주로 테스트 구성 방법으로 간주됩니다.

특히 클래스 (또는 모듈)에 적용된 마커는 테스트 함수 자체에 전송되며 오버라이드되지 않은 파생 클래스 메서드는 기본 클래스 메서드와 동일한 개체이므로 마커가 기본 클래스 메소드

(기술 세부 사항 :. 현재이 _pytest.python.transfer_markers()에서 발생하지만에 의존하지 않는) 대신 클래스 상속의

, 플랫폼 별 테스트 설정을 캡슐화 fixtures을 사용하는 것이 좋습니다.

는 ecatmur의 좋은 답변에 추가
if 'TestWindowsOnly' in item.keywords and not sys.platform.startswith('win'): 
    skip_message = "Skipped: Windows only test" 

if 'TestLinuxOnly' in item.keywords and not sys.platform.startswith('linux'): 
    skip_message = "Skipped: Linux only test" 
+0

이 문제의 해결 방법이 있습니까? 나는 기존의 거대한 테스트 스위트를 가지고있다. 나는 py.test – dbn

+0

@dbw를 사용하여 마이그레이션하고 싶다. – ecatmur

+0

우리의 경우에는 작동하지 않을 것입니다 - 우리는 100 가지가 넘는 다른 테스트가 다른 패널에 대한 공통 테스트를 제공하기 위해 상속받은 기본 테스트를 가지고 있습니다. 이것을하기위한 py.test-ish 방법에 대한 새로운 질문을 할 것입니다. – dbn

관련 문제