pytest实现用例参数化(@pytest.mark.parametrize)

1. 前言

在软件测试过程中,我们常常需要针对同一功能或场景进行多次测试,对于一些特定的测试,我们需要检查多组数据的输入及输出。这种情况下,用例参数化是一个非常强大的技术。

2. 什么是用例参数化

简单来说,用例参数化指的是在执行同一函数或方法的不同输入时,将输入参数作为测试用例的多组数据来测试。这样的好处在于,我们无需新建多个测试用例,只需要把不同的输入参数作为参数传递给同一函数或方法即可。

2.1 为什么需要用例参数化

使用用例参数化主要有以下几个好处:

提高测试效率,减少冗余的测试用例编写;

提高测试覆盖率,我们可以用不同的参数组合来测试系统的不同行为;

提高代码复用率,我们可以避免编写大量重复的代码。

2.2 pytest中的用例参数化

pytest是一个流行的Python测试框架。pytest中的标准用例参数化功能可以通过使用pytest.mark.parametrize装饰器来实现。下面是一个演示示例:

import pytest

@pytest.mark.parametrize("input1, input2, expected_output", [

("hello", "world", "helloworld"),

("foo", "bar", "foobar"),

("one", "two", "onetwo"),

])

def test_concatenation(input1, input2, expected_output):

assert input1 + input2 == expected_output

上述示例中,我们在 pytest.fixture下编写了一个名为“test_concatenation”的测试函数,然后在函数上应用了pytest.mark.parametrize装饰器。装饰器用于指定测试函数的输入参数(input1和input2)以及预期输出(expected_output) 的多个值-这是用例的不同值的组合,用于测试该函数。

3. 特殊的参数化案例temperature=0.6

接下来我们演示一下, 如何实现特殊的参数化案例 temperature=0.6。

假设我们有以下函数, 它的功能是将摄氏度转换为华氏度:

def celsius_to_fahrenheit(celsius):

if not isinstance(celsius, (int, float)):

raise TypeError("Celsius must be numerical")

return (celsius * 1.8) + 32;

根据华氏度和摄氏度之间的公式, 我们可以将摄氏度转换为华氏度:f = (c × 1.8)+32,其中f是华氏温度,c是摄氏温度。

我们现在想测试这个celsius_to_fahrenheit函数。我们有一个特殊的测试要求,即只有在温度为0.6摄氏度以下时,它才能正常工作。

我们可以使用Python中的doctest模块来实现这样的测试。我们在一个名为“testtemperaturerange”的测试函数中使用pytest.mark.parametrize装饰器。具体来说,我们将带有三个参数的单个元组作为 pytest.mark.parametrize装饰器的参数传递。第一个参数表示摄氏温度,第二个参数表示应该返回的华氏温度,第三个参数表示摄氏温度是否小于0.6。如果摄氏度小于0.6,则期望由测试断言引发ValueError,否则期望得到正确的华氏温度。

import pytest

from doctest import testmod

def celsius_to_fahrenheit(celsius):

if not isinstance(celsius, (int, float)):

raise TypeError("Celsius must be numerical")

return (celsius * 1.8) + 32

def testtemperaturerange():

for test in testcases:

celsius, fahrenheit, should_fail = test

if should_fail:

with pytest.raises(ValueError):

celsius_to_fahrenheit(celsius)

else:

assert round(celsius_to_fahrenheit(celsius),2) == fahrenheit

testcases = [

(-2,28.4,True),

(0.5,32.9,False),

(200, 392,False),

]

pytest.mark.parametrize("celsius,fahrenheit,should_fail",

[(case[0], case[1], case[2]) for case in testcases])

在上面的代码中,doctest.testmod()用于测试函数的文档字符串, 并在第一次失败后返回错误。如果有多个测试失败,则doctest.testmod()会抛出一个异常。这个异常会被pytest捕获,从而会展示出全部断言失败信息而不是停止在第一个断言失败。 通过运行我们的测试函数,我们可以测试出这个celsius_to_fahrenheit函数仅在摄氏度小于0.6时才能正常工作,否则会抛出ValueError。

4. 总结

在本文中,我们介绍了用例参数化的概念及其优势,重点讲解了pytest中的用例参数化。最后,我们演示了一个特殊的用例参数化案例temperature=0.6,通过这个案例,读者可以更深入地理解用例参数化的应用场景和价值。

后端开发标签