Python 单元测试的最佳实践——多个函数适用于同一个对象

我有一堆适用于类似对象的函数,例如代表 n 维框的 Numpy 数组:


# 3-D box parameterized as:

#     box[0] = 3-D min coordinate

#     box[1] = 3-D max coordinate

box = np.array([

    [1, 3, 0],

    [4, 5, 7]

])

现在我有一大堆要在框列表上运行的函数,例如。volumes, intersection,smallest_containing_box等。在我看来,这是我希望设置的方式:


# list of test functions:

test_funcs = [volume, intersection, smallest_containing_box, ...]

# manually create a bunch of inputs and outputs

test_set_1 = (

    input = [boxA, boxB, ...], # where each of these are np.Array objects

    output = [

        [volA, volB, ...], # floats I calculated manually

        intersection, # np.Array representing the correct intersection

        smallest_containing_box, # etc.

    ]

)

# Create a bunch of these, eg. test_set_2, test_set_3, etc. and bundle them in a list:

test_sets = [test_set_1, ...]

# Now run the set of tests over each of these:

test_results = [[assertEqual(test(t.input), t.output) for test in test_funcs] for t in test_sets]

我想以这种方式构建它的原因是,我可以创建多组(输入、答案)对,并在每个组上运行所有测试。除非我遗漏了什么,否则unittest这种方法的结构似乎不太好。相反,它似乎希望我为每对函数和输入创建一个单独的 TestCase 对象,即


class TestCase1(unittest.TestCase):

    def setUp(self):

        self.input = [...]

        self.volume = [volA, volB, ...]

        self.intersection = ...

        # etc.


    def test_volume(self):

        self.assertEqual(volume(self.input), self.volume)


    def test_intersection(self):

        self.assertEqual(intersection(self.input), self.output)


    # etc.


# Repeat this for every test case!?

这似乎是大量的样板文件。我错过了什么吗?


慕的地10843
浏览 234回答 2
2回答

慕无忌1623718

试试unittest.TestSuite()。这为您提供了一个可以添加测试用例的对象。在您的情况下,创建套件,然后遍历您的列表,创建TestCase所有实例都只有一个测试方法。将测试数据传递给构造函数并将它们保存到那里的属性而不是 in setUp()。当您在调用的方法中创建套件suite()并运行所有套件时,单元测试运行器将检测套件。注意:为每个TestCase实例分配一个名称或找出哪个失败将非常困难。

精慕HU

让met 尝试描述我如何理解您的方法:您已经实现了许多具有相似性的不同函数,即它们对相同类型的输入数据进行操作。在您的测试中,您尝试利用这种相似性:您创建一些输入数据并将该输入数据传递给您的所有函数。这种以测试数据为中心的方法是不寻常的。典型的单元测试方法是以代码为中心的。原因是,单元测试的一个主要目标是发现代码中的错误。不同的函数有(显然)不同的代码,因此错误的类型可能不同。因此,测试数据通常经过精心设计,以识别相应代码中的某些类型的错误。测试设计方法是有条不紊地设计测试用例的方法,以便在理想情况下可以检测到所有可能的错误。我怀疑使用以测试数据为中心的方法,您是否会同样成功地找到不同函数中的错误:对于该volume函数,可能存在不适用于intersectionor 的溢出场景(以及下溢场景)smallest_containing_box。相比之下,必须有空交叉点、一点交叉点等。因此,似乎每个功能都可能需要专门设计的测试场景。关于似乎是以代码为中心的单元测试结果的样板代码:有几种方法可以限制它。同意,您将针对不同的测试功能使用不同的测试方法。但是,您可以使用参数化测试来避免进一步的代码重复。而且,对于您仍然看到为不同功能使用(至少有时)通用测试数据的优势的情况:对于这种情况,您可以使用创建测试数据的工厂函数,并且可以从不同的测试用例中调用. 例如,您可以make-unit-cube在不同的测试中使用一个工厂函数。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python