【问题标题】:How to use pytest fixtures with Unittest methods如何使用带有 Unittest 方法的 pytest 固定装置
【发布时间】:2018-06-05 22:55:46
【问题描述】:
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)  

【问题讨论】:

    标签: python pytest


    【解决方案1】:

    这是因为 autouse 固定装置在 setUp/tearDown 方法之前执行:

    注意

    由于两个框架之间的架构差异,基于unittest 的测试的设置和拆卸是在call 测试阶段执行的,而不是在pytest 的标准setupteardown 阶段执行。在某些情况下,理解这一点很重要,尤其是在推理错误时。例如,如果基于unittest 的套件在设置期间出现错误,pytest 将在其setup 阶段不报告错误,而是在call 期间引发错误。

    Source

    您无法解决此问题。您可以将与夹具相关的代码移出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)
    

    或者你可以从fixtures中移动所有setUp相关代码:

    class Tests(unittest.TestCase):
    
        def setUp(self):
            self.flag = True
    
        @pytest.fixture(autouse=True)
        def myfixture(self, somearg):
            fn(self.flag, somearg)
    

    变成

    class Tests(unittest.TestCase):
    
        def setUp(self):
            self.flag = True
            fn(self.flag, self._somearg)
    
        @pytest.fixture(autouse=True)
        def assign_stuff(self, somearg):
            self._somearg = somearg
    

    【讨论】:

      【解决方案2】:

      正如@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')
      

      【讨论】:

        猜你喜欢
        • 2020-02-29
        • 1970-01-01
        • 2020-10-04
        • 2018-02-10
        • 1970-01-01
        • 1970-01-01
        • 2021-02-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多