是否有充分的理由在单元测试事务中捕获异常?

时间:2019-04-23 19:41:53

标签: python django unit-testing

unittest模块非常适合检测代码中的问题。 我了解使用断言隔离和测试部分代码的想法:

self.assertEqual(web_page_view.func, web_page_url)

但是,除了这些断言之外,在相同的测试方法中,您可能还需要了解一些逻辑。

我想知道在TestCase子类的方法内部是否应该考虑手动处理异常。

因为如果我将块包装在try-catch中,则如果失败,则测试将返回OK并且不会失败:

    def test_simulate_requests(self):
        """
        Simulate requests to a url
        """
        try:
           response = self.client.get('/adress/of/page/')
           self.assertEqual(response.status_code, 200)
        except Exception as e:
            print("error: ", e)

在这样的测试中应该始终避免异常处理吗?

2 个答案:

答案 0 :(得分:1)

测试有两种“不良”状态:失败(当一个断言失败时)和错误(当测试本身失败时-您的情况)。

首先,不用说,最好以使其达到断言的方式构建测试。

如果需要断言某些经过测试的代码会引发异常,则应使用with self.assertRaises(ExpectedError)

如果测试中的某些代码引发异常-最好从“错误”结果中了解它,而不是看到“确定所有测试均已通过”。

如果您的测试逻辑确实认为测试本身可能会失败并且属于正常行为,则可能是测试错误。也许您应该使用模拟(https://docs.python.org/3/library/unittest.mock.html)来模仿api调用或其他方法。

在您的情况下,即使测试失败,您也要勉强抓住它,然后说“确定,继续”。反正实现是错误的。

最后:不,除了您的测试用例之外,应该没有其他

P.S。最好用test_what_you_want_to_test_name调用测试函数,在这种情况下,test_successful_request可能没问题。

答案 1 :(得分:0)

答案的第一部分:

正如您正确地说的那样,在实际测试之前需要有一些逻辑。属于单元测试的代码可以分为四个部分(以下我将使用Meszaros的术语):设置,练习,验证,拆卸。通常,测试用例的代码的结构应使四个部分的代码清晰地分开并以精确的顺​​序排列-这称为四阶段测试模式。

练习阶段是测试的心脏,执行该功能的过程应在测试中进行检查。该设置可确保此操作在定义明确的上下文中发生。因此,您在本术语中描述的是在安装过程中发生某些故障的情况。这意味着,不满足有效执行要测试功能所需的先决条件。

这是一种常见的情况,这意味着您实际上需要能够区分测试的三个结果:测试可以成功通过,失败或完全没有意义。

幸运的是,在python中有一个答案:您可以跳过测试,并且如果跳过了测试,则将记录下来,但不会失败也不会成功。跳过测试可能是处理示例中所示情况的更好方法。这是一小段代码,演示了一种跳过测试的方法:

import unittest
class TestException(unittest.TestCase):
   def test_skipTest_shallSkip(self):
      self.skipTest("Skipped because skipping shall be demonstrated.")

答案的第二部分:

您的测试似乎具有一些不确定性因素。 self.client.get可以引发异常(但仅在某些时候-有时没有)。这意味着在测试控制下您没有上下文。在单元测试中,您应该尝试避免这种情况。您的测试应该具有确定性的行为。

实现此目标的一种典型方法是将代码与造成不确定性的组件隔离开来,并在测试过程中通过模拟替换这些组件。模拟的行为在测试代码的完全控制之下。因此,如果您的代码使用某些组件进行网络访问,则可以模拟该组件。然后,在某些测试案例中,您可以指示该模拟程序模拟成功的网络通信,以查看您的组件如何处理该通信,而在其他测试中,您可以指示该模拟程序模拟网络故障,以查看您的组件如何应对这种情况。