2013-08-05 46 views
10

我使用py.test 2.2.4和我的測試用例的結構如下:如何在基類中使用@ 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如下:

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) 

當我執行此設置輸出顯示標記似乎疊起來:

$ 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 =================================== 

所以我想知道它是如何可能這些標記在子類之間泄漏,以及如何修復/解決這些標記(測試用例將存在於基類中,但子類將設置必要的平臺抽象)。

回答

4

除了ecatmur的很好的答案:你可能想定義pytest.mark.skipif表達這樣的:

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

,然後只是裝點僅Win32測試它::

@win32only 
def test_something(...): 

另一個問題是,如果你可以,也許只是把「BaseTests」變成了正常的測試類::

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

即避免任何繼承?如果您在測試中需要固定裝置,您可以在測試模塊中定義它們,並在測試功能(跨平臺或特定於平臺的測試功能)中接受它們,請參閱pytest fixture docs。不過,一定要使用pytest-2.3.5,因爲在pytest-2.3系列中有很多改進,尤其是對於燈具的改進(更多的是與2.4一起提供)。

9

pytest比其他Python測試框架(例如unittest)需要更多的面向功能的測試方法來測試,因此類主要被視爲組織測試的一種方式。

特別是,應用於類(或模塊)的標記被轉移到測試函數本身,並且由於未覆蓋的派生類方法與基類方法是相同的對象,這意味着標記被應用於基類方法。

(技術細節:目前這種情況發生在_pytest.python.transfer_markers(),但不依賴於)

代替類繼承的,可以考慮使用fixtures封裝特定於平臺的測試設置。


一個更簡單的解決方案可能是比較反對的類名,因爲py.test增加了即時含有類產品關鍵字:

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