迹忆客 专注技术分享

当前位置:主页 > 学无止境 > 编程语言 > Python >

Python 中的参数化单元测试

作者:迹忆客 最近更新:2023/06/22 浏览次数:

单元测试是维护软件质量的一种强大工具。 软件单元测试是对一段代码进行的一系列检查,以确保软件的开发符合软件设计规范,并按照最终用户的预期行为或响应。

在 Python 中,我们可以使用参数化单元测试为每个项目或测试用例生成一个测试。 本文将探讨 Python 的参数化单元测试。


Python 中参数化单元测试的目的

当开发人员编写单元测试时,他们通常采用一种测试一种情况的方法。 然后将最相似或相关的测试组合成一个套件。

查看下面代码中的测试套件:

class TestSuite(TestCase):
    def test_first_case(self):
        assert example_test()
    def test_second_case(self):
        assert more_example_tests()
    def test_third_case(self):
        assert another_example_test()

通过像这样的套件进行测试意味着每个测试用例都必须经历一系列自定义阶段的准备、执行和最后的断言。 如果这些测试用例中的每一个都相似,那么生成的套件将是一团乱七八糟的重复或冗余代码,这在软件开发人员的世界中无异于诅咒。

这些套件还会导致代码库庞大,在进行更改时极难维护(这是预料之中的)。 为了解决这个问题,我们在 Python 中得到了动态或参数化单元测试的祝福,使我们能够为多个案例生成单一测试。


Python 中参数化单元测试的示例

让我们深入研究一个示例测试场景或方法,我们可以以此为基础来理解 Python 中的参数化单元测试以及它如何使我们作为软件开发人员的生活变得更加轻松。

下面是我们要测试的一个简单函数:

def compute(a, b):
    return (a + b) / (a * b)

现在,就像任何测试一样,我们知道我们需要将多个输入应用到上面的函数以测试它是否以所需的方式运行。 为了更详细地指定测试参数,我们需要根据以下参数测试该方法:

  • 正整数
  • 负整数
  • 长整数
  • 正则整数
  • 浮点数
  • 其中一个或两个数字为零
  • 一个或两个参数未定义
  • 一个或两个参数是字符串或其他类型的对象

如果要使用每种情况一个测试的方法进行测试,我们将为单行方法编写一长串重复代码。 您可以想象,对于基于涉及循环和条件的多行代码的方法来说,这是多么忙碌和乏味。

通过参数化,我们只需要这样做:

def test_compute(self, a, b, expected, raises=None):
    if raises is not None:
        with self.assertRaises(raises):
            compute(a, b)
    else:
        assert compute(a, b) == expected

这样,我们需要准备一个参数列表,以最好地测试计算方法的所有可能性。 参数列表可以是我们想要的那么长,也可以只是我们需要测试的案例的集合。

以下是可以传递到上面的单元测试中的参数列表的示例。

代码的输出:

a           | b   | expected | raises
------------+-----+----------+-------
-2          | 2   | 0        |
0           | 2   |          | ZeroDivisionError
2           | 2   | 1        |
0.5         | 0.4 | 4.5      |
None        | 2   |          | TypeError
"10"        | "1" |          | TypeError
3000000000L | 2   | 0.5      |

可以看出,这个列表和上面的参数化单元测试使我们能够更有效地测试可以传递给 compute() 方法的参数的各种场景。 它还使记录不同的结果变得更加容易。


Python 中参数化单元测试的好处

编写定期的单元测试可能是高度重复的、详尽的、耗时的和伤脑筋的,尤其是当我们希望测试遍历每个软件场景并确保一切都符合标准时。

在 Python 中使用参数化单元测试意味着我们作为开发人员不必担心编写数百行代码来测试正在开发的软件中可能出现的各种场景以保持其质量。 我们只需要一个测试来测试所有需要测试的场景。

这意味着测试代码库将始终易于维护,几乎没有重复,从而产生高效的测试用例和节省时间的结果。

此外,参数化单元测试迫使相关开发人员更清楚、更明确地思考进入该方法的所有可能输入。 它有助于跟踪边缘情况,例如上面示例中的大整数或不一致的输入类型,以及任何错误情况,例如未定义的输入。

该测试自然也迫使开发人员更多地考虑如何处理边缘情况,而不是仅仅考虑可能破坏其代码的输入类型。 它通过迫使我们预测函数在特定情况组合下的预期功能来帮助保持代码的质量,并导致针对所面临的任何问题开发概念和有效的解决方案。

更重要的是,如果我们决定使用更详尽或更广泛的参数列表来测试我们的方法,我们最终可能会得到测试用例的结果和解决方案,我们最初认为这些测试用例太琐碎而无法为其编写测试用例。 然而,有了我们可以使用的参数化测试,我们只需要输入我们想要测试的组合,看看代码如何响应。


支持参数化单元测试的 Python 库

Python 通过参数化库让我们的生活更轻松,这使得测试方法的开发变得简单明了。 我们所要做的就是导入参数化并通过测试套件中我们的方法中的参数化装饰器传递我们想要测试的参数,如下所示:

from parameterized import parameterized
class TestSuite(TestCase):
    @parameterized.expand([
        ("test_1", 0, 0, 0),
        ("test_2", 0, 1, 1)
    ])
    def test_my_feature(self, name, in_1, in_2, expected):
        assert my_feature(in_1, in_2) == expected

另一种方法是创建一个包含所有参数列表的 .csv 文件。 然后,我们将它传递给装饰器进行测试,如下所示:

def load_test_cases():
    return load_from_csv("my_feature_parameters.csv")
class TestSuite(TestCase):
    @parameterized.expand(load_test_cases)
    def test_my_feature(self, name, in_1, in_2, expected):
        assert my_feature(in_1, in_2) == expected

我们已经涵盖了从为什么需要使用动态(参数化)单元测试到实现它的不同方法及其在软件开发生命周期中的好处的所有内容。 我们希望本文有助于您理解如何在 Python 中生成单元测试。

转载请发邮件至 1244347461@qq.com 进行申请,经作者同意之后,转载请以链接形式注明出处

本文地址:

相关文章

Pandas read_csv()函数

发布时间:2024/04/24 浏览次数:254 分类:Python

Pandas read_csv()函数将指定的逗号分隔值(csv)文件读取到 DataFrame 中。

Pandas 追加数据到 CSV 中

发布时间:2024/04/24 浏览次数:352 分类:Python

本教程演示了如何在追加模式下使用 to_csv()向现有的 CSV 文件添加数据。

Pandas 多列合并

发布时间:2024/04/24 浏览次数:628 分类:Python

本教程介绍了如何在 Pandas 中使用 DataFrame.merge()方法合并两个 DataFrames。

Pandas loc vs iloc

发布时间:2024/04/24 浏览次数:837 分类:Python

本教程介绍了如何使用 Python 中的 loc 和 iloc 从 Pandas DataFrame 中过滤数据。

扫一扫阅读全部技术教程

社交账号
  • https://www.github.com/onmpw
  • qq:1244347461

最新推荐

教程更新

热门标签

扫码一下
查看教程更方便