7

我正在对我的应用程序进行单元测试。大多数测试所做的是调用具有特定参数的函数并断言返回值与期望值相等。

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

以下是我正在考虑解决这个问题的想法,在我看来,从最好到最差排列:

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

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

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

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

4

2 回答 2

3

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

测试库.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 通过在执行任何测试之前使用将测试装置加载到数据库中来支持这种开箱即用的方式。

于 2012-08-27T10:20:21.900 回答
1

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

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

如果您确实想验证字典是否只包含给定的键,那么单个断言可能是合适的。将您要比较的对象定义在最清晰的位置。如果在单独的文件中定义它(正如康斯坦丁的回答所暗示的那样)使事情更具可读性,那么请考虑这样做。

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

于 2012-08-27T10:38:50.167 回答