Python单元测试中对象的长定义

时间:2012-08-27 09:14:34

标签: python unit-testing coding-style

我正在测试我的应用程序。大多数测试所做的是调用具有特定参数的函数,并声明返回值与期望值的相等性。

在某些测试中,预期的回报值是一个相对较大的对象。例如,其中之一是将5个字符串映射到元组列表的字典。它需要40-50个重复的代码行来定义该对象,但该对象是我正在测试的函数之一的期望值。我不想在测试函数中定义40-50行代码来定义预期的返回值,因为我的大多数测试函数都包含3-6行代码。我正在寻找这种情况的最佳实践。将冗长的定义放在测试中的正确方法是什么?

我正在考虑解决这个问题的想法,从我看到的最好到最差的排名:

  • 测试对象的样本:根据键的子集进行一些相等的断言。为了代码优雅,这将牺牲测试的彻底性。

  • 在单独的模块中定义对象:在单独的.py文件中编写冗长的40-50行代码,在测试中导入模块,然后进行相等的断言。这将使测试简洁明了,但我不喜欢单独的文件作为测试的补充;毕竟,对象定义是测试的一部分。

  • 在测试函数中定义对象:这是我希望避免的简单解决方案。我的测试非常简单明了,而且该对象的冗长定义也不合适。

也许我太痴迷于干净的代码,但我不喜欢上述解决方案。还有其他一些我没有想到的常见做法吗?

2 个答案:

答案 0 :(得分:3)

我建议使用测试代码测试数据的分离。出于这个原因,我通常创建一个抽象基类,其中包含我想要测试的方法,并创建几个特定的​​测试用例类,以将方法与数据联系起来。 (我使用Django框架,所以我放入testbase.py)的所有抽象测试类:

testbase.py

class TestSomeFeature(unittest.TestCase):
    test_data_A = ...

    def test_A(self):
        ... #perform test

现在 test.py

中的实现
class TestSomeFeatureWithDataXY(testbase.TestSomeFeature):
    test_data_A = XY

测试数据也可以外部化,例如JSON文件:

class TestSomeFeatureWithDataXYZ(testbase.TestSomeFeature):
    @property
    def test_data_A(self): 
        return json.load("data/XYZ.json")

我希望我的观点足够明确。在您的情况下,我强烈选择使用数据文件。 Django通过在执行任何测试之前使用测试装置加载到数据库中来支持这种开箱即用。

答案 1 :(得分:1)

这实际上取决于你想要测试的内容。

如果你想测试一个字典包含某些具有某些值的键,那么我会建议单独的断言来检查每个键。这样,如果字典被扩展,您的测试仍然有效,并且测试失败应该清楚地识别问题(一条错误消息告诉您一个50行长字典不等于第二个50行长字典并不完全清楚)

如果您确实想要验证字典是否只包含给定的键,那么单个断言可能是合适的。定义要比较的对象与最清楚的对象。如果在一个单独的文件中定义它(如Constantinius的答案所示)使事情更具可读性,那么考虑这样做。

在这两种情况下,指导原则只是测试您关心的行为。如果你测试你不关心的行为,你可能会发现你的测试套件在重构时比有用的更具阻碍性。