Python unittest 统计测试次数

Python unittest counting the number of tests

这是我第一次在 Python 的学校作业中进行单元测试。我基本上有一个 Circle 对象,我在其中使用 pyunit 来确保正确存储数据。

我注意到 Python 只计算作为测试用例的方法的数量,而不是 assert 语句的数量。

例如,我想测试方法是否正常工作,尽管有 4 个断言语句,Python 仅将以下计为 2 个测试。这真的让我措手不及,因为对于 Java 的 JUnit,它会计算 assert 语句的数量。

def test_xcrd(self): 
    self.assertTrue(self.point.xcrd() == 1) 
    self.assertFalse(self.point.xcrd() == 5)

def test_ycrd(self): 
    self.assertTrue(self.point.ycrd() == 2) 
    self.assertFalse(self.point.ycrd() == 10)

python 中的 "norm" 是什么?每个方法应该只有一个断言语句吗?

Python 的 unittest 包允许您像您注意到的那样以单独的方法构建单元测试。这在您想要测试非常密切相关且不需要单独的单元测试的情况下很有用。

unittest 测试从子类化 unittest.Test 开始,然后向其添加方法。因此,您可以在相关性较低的不同单元测试之间添加多层分隔。

Python Docs 中的一个示例演示了被认为是 Python 单元测试的最佳实践:

import unittest

class TestStringMethods(unittest.TestCase):

    def test_upper(self):
        self.assertEqual('foo'.upper(), 'FOO')

    def test_isupper(self):
        self.assertTrue('FOO'.isupper())
        self.assertFalse('Foo'.isupper())

    def test_split(self):
        s = 'hello world'
        self.assertEqual(s.split(), ['hello', 'world'])
        # check that s.split fails when the separator is not a string
        with self.assertRaises(TypeError):
            s.split(2)

if __name__ == '__main__':
    unittest.main()

您可以在这里观察到许多事情:

  1. TestStringMethods的三个方法是单独的单元测试。
  2. test_isuppertest_split 都包含两个断言,因为它们密切相关。为 test_isupper 中存在的两个断言添加单独的测试会给代码增加很多膨胀,并且可能导致非常奇怪的问题。

例如,如果 str.isupper() 会以一种奇怪的方式中断,则覆盖该单个函数的单个单元测试就会中断。但是,如果 "FOO""Foo" 的两个测试是分开的,则一个测试可能通过,而另一个失败。因此,测试单个函数的功能最好保存在具有多个断言的单个单元测试中。

同样适用于test_split方法;检查 str.split() 是否工作和检查它是否引发 TypeError 密切相关,因此最好在代码中也保持紧密联系。

因此,回到您的问题:每个方法可以(有时应该)有多个断言,因为它可以使代码更简单、更清晰,并减少混淆。引用 "Zen of Python"(由 运行 import this 在 python shell 中找到):"Simple is better than complex"。因此,通过将相似的断言分组到一个方法中,让您的单元测试保持简单和结构化。

您的问题'''python 中的 "norm" 是什么?每个方法应该只有一个 assert 语句吗?''' 是 "No"。有些人可能会说 'yes' 但包括我在内的 CPython 核心开发人员经常在测试方法中使用多个断言。查看 Lib/test 中的 test_xyz 文件(如果您的安装包含该目录)。

的确,一种方法应该测试一个单元,甚至是一个单元的一种行为。