Python 如果你不小心重复了一个测试,unittest 不会注意到

Python unittest does not notice if you accidentally duplicate a test

如果我修改了文档中的 basic example 并且不小心故意复制了一个测试:

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_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()

它 returns 完全一样,就好像它没有被复制一样:

python3 basictest.py 
...
----------------------------------------------------------------------
Ran 3 tests in 0.001s

OK

如果您更改其中一个重复测试使其失败,则失败是否显示取决于您修改的重复测试。所以我在编写彼此略有不同的测试时,真的是偶然地做到了这一点。如果您在一个程序中执行此操作,其中它们不仅彼此相邻而且位于脚本的两端,该怎么办?如果您有重复测试,为什么它不警告您?

不可能在这样定义的 class 中检测到重复项。如您所见,当 class 刚刚通过 metaclass 创建时,已经选择了其中一个重复函数:

class Meta(type):
    def __new__(cls, name, bases, namespace):
        print(name, namespace)

        return super().__new__(cls, name, bases, namespace)

class Dupe(metaclass=Meta):
    def a(self):
        ...

    def a(self):
        ...

这输出:

Dupe {'__module__': '__main__', '__qualname__': 'Dupe', 'a': <function Dupe.a at 0x8f5be84>}

如果您想检测重复项,您需要将 每个函数 包装在装饰器中,并让它决定特定函数是否重复。 如何做出这个决定是另一个问题:例如,您可以跟踪所有已定义函数的名称,然后简单地检查给定函数的名称是否已存在于列表中。

它为什么要警告你?更重要的是,怎么可能呢?单元测试 classes 与任何其他 class 没有区别;与任何其他 class 一样,它们将它们的属性(包括方法)存储在字典中。与任何字典一样,如果您使用相同的键分配两个值,一个将覆盖另一个