在setUp方法中报告Python unittest中的错误的正确方法是什么?

Jon*_*age 8 python testing unit-testing assert arrange-act-assert

我已经对使用读了一些相互矛盾的意见assertsetUpPython的单元测试的方法.如果测试依赖的前提条件失败,我无法看到测试失败的危害.

例如:

import unittest

class MyProcessor():
    """
    This is the class under test
    """

    def __init__(self):
        pass

    def ProcessData(self, content):
        return ['some','processed','data','from','content'] # Imagine this could actually pass

class Test_test2(unittest.TestCase):

    def LoadContentFromTestFile(self):
        return None # Imagine this is actually doing something that could pass.

    def setUp(self):
        self.content = self.LoadContentFromTestFile()
        self.assertIsNotNone(self.content, "Failed to load test data")
        self.processor = MyProcessor()

    def test_ProcessData(self):
        results = self.processor.ProcessData(self.content)
        self.assertGreater(results, 0, "No results returned")

if __name__ == '__main__':
    unittest.main()
Run Code Online (Sandbox Code Playgroud)

这对我来说似乎是合理的事情,即确保测试能够运行.当由于设置条件而失败时,我们得到:

F
======================================================================
FAIL: test_ProcessData (__main__.Test_test2)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\Projects\Experiments\test2.py", line 21, in setUp
    self.assertIsNotNone(self.content, "Failed to load test data")
AssertionError: unexpectedly None : Failed to load test data

----------------------------------------------------------------------
Ran 1 test in 0.000s

FAILED (failures=1)
Run Code Online (Sandbox Code Playgroud)

Old*_*Fox 10

目的setUp是减少在安排阶段在测试类中的测试之间创建的Boilerplate代码.

在安排阶段,您:设置运行测试代码所需的一切.这包括运行测试所需的依赖项,模拟和数据的任何初始化.

根据以上段落,您不应在setUp方法中断言任何内容.

如前所述; 如果您无法创建测试前提条件,那么您的测试将被破坏.为了避免这样的情况,Roy Osherove写了一本很棒的书:单位测试的艺术(完全披露Lior Friedman(他是Roy的老板)是我的朋友,我和他们密切合作超过2年,所以我我有点偏颇......)

基本上,只有几个理由在安排阶段(或可能导致异常的事情)与外部资源进行交互,其中大多数(如果不是全部)在集成测试中是相关的.

回到你的例子; 有一种模式可以构建您需要加载外部资源的测试(对于所有/大多数).只是旁注; 在您决定应用此模式之前,请确保您不能将此内容作为UT类中的静态资源,如果其他测试类需要使用此资源将此资源提取到模块中.

以下模式减少了失败的可能性,因为您对外部资源的调用较少:

class TestClass(unittest.TestCase):

    def setUpClass(self):
        # since external resources such as other servers can provide a bad content
        # you can verify that the content is valid
        # then prevent from the tests to run  
        # however, in most cases you shouldn't.
        self.externalResourceContent = loadContentFromExternalResource()


    def setUp(self):
        self.content = self.copyContentForTest()
Run Code Online (Sandbox Code Playgroud)

优点:

  1. 失败的可能性较小
  2. 防止不一致行为(1.某事/已经编辑了外部资源.2.您在某些测试中未能加载外部资源)
  3. 更快的执行

缺点:

  1. 代码更复杂


小智 5

setUp不是为了断言先决条件而是创造它们.如果您的测试无法创建必要的夹具,它将被破坏,而不是失败.

  • @JonCage恕我直言,如果你真的需要测试前提条件你应该为它们编写一个测试,而不是使用`setUp()`断言你的前置条件是有效的.所以添加一个像`test_load_fixture(self):self.assertIsNotNone(self.content,"无法加载测试数据")这样的测试,你会对这个测试产生错误,并且每个使用`self.content的测试都会失败`. (3认同)