如何在Unittest方法中使用pytest fixture

时间:2018-06-05 22:55:47

标签: pytest

class MyTestCase(unittest.Testcase):
    def setUp(self):
        self.something = True

    @pytest.fixture(autouse=True)
    def MyTestMethod(self, frozentime):
        fn(self.something)  # self.something is NOT defined

如果我使用@pytest.fixture(autouse=True),我最终会遇到PyTest的一些奇怪行为。 PyTest不会在测试方法之前调用我的setUp方法,而是跳过setUp并调用MyTestMethod,就像它是PyTest MyTestFunction一样,当然效果不好。

如何在不忽略应首先调用的MyTestMethod方法的情况下让frozentime使用setUp装置。

class MyTestCase(unittest.Testcase):
    def setUp(self):
        self.something = True

    #@pytest.fixture(autouse=True)
    def MyTestMethod(self, frozentime): # Fails on call, because it needs too many arguments.
        fn(self.something)  

2 个答案:

答案 0 :(得分:2)

那是因为autouse灯具是在setUp / tearDown方法之前执行的:

  

注意

     

由于两个框架之间存在体系结构差异,基于unittest的测试的设置和拆除是在call测试阶段而不是pytest的标准{{1}中执行的}和setup个阶段。在某些情况下,这一点非常重要,特别是在推理错误时。例如,如果基于teardown的套件在设置过程中出现错误,unittest将在pytest阶段报告错误,而是在setup期间引发错误。

Source

你无能为力解决这种问题。您可以使用call / setUp方法移除与灯具相关的代码,例如:如果在类别范围的灯具中使用tearDown,则可以替换

self.flag

class Tests(unittest.TestCase):

    def setUp(self):
        self.flag = True

    def tearDown(self):
        self.flag = False

    @pytest.fixture(autouse=True)
    def myfixture(self):
        print(self.flag)

或者您可以从灯具中移动所有class Tests(unittest.TestCase): @pytest.fixture(autouse=True) def prepare_flag(self): self.flag = True yield self.flag = False @pytest.fixture(autouse=True) def myfixture(self, prepare_flag): print(self.flag) 相关代码:

setUp

变为

class Tests(unittest.TestCase):

    def setUp(self):
        self.flag = True

    @pytest.fixture(autouse=True)
    def myfixture(self, somearg):
        fn(self.flag, somearg)

答案 1 :(得分:0)

正如@hoefling 所提到的,这两个生命周期是不兼容的……但如果您的目标不是直接兼容,这可能会被破解。

import pytest
from pytestqt.plugin import QtBot
from unittest import TestCase
from myproject import custom_widget

@pytest.fixture(scope="class")
def qtbot_adapter(qapp, request):
    """Adapt qtbot fixture for usefixtures and unittest.TestCase"""
    request.cls.qtbot = QtBot(request)

def with_updown(function):
    """Wrapper to bodge setUp/tearDown into fixtures+TestCase"""
    def test_wrapper(self, *args, **kwargs):
        __tracebackhide__ = True
        if callable(getattr(self, 'up', None)):
            self.up()
        try:
            function(self, *args, **kwargs)
        finally:
            if callable(getattr(self, 'down', None)):
                self.down()
    test_wrapper.__doc__ = function.__doc__

    return test_wrapper

@pytest.mark.usefixtures("qtbot_adapter")
class MyTestCase(TestCase):
    def up(self):
        self.widget = custom_widget.CustomWidget()
        self.widget.show()

    @with_updown
    def test_some_property(self):
        with self.qtbot.waitSignal(self.widget.my_signal,
                                   timeout=300):
            self.widget.do_thing()
        self.assertEqual(self.widget.get_thing(), 'foo')