前言

本节将介绍如何使用 ddt 模块进行参数化测试,以及如何从外部输入参数。

知识点

  • 结合 ddt 模块进行参数化测试

  • 实例:参数化测试

  • 进阶:从外部输入参数

结合 ddt 模块进行参数化测试

在自动化测试中,有时候我们需要对同一个测试用例使用不同的输入数据进行多次测试,以确保测试的覆盖性。为了实现这样的参数化测试,我们可以使用 ddt 模块。

安装 ddt 模块

首先,确保你已经安装了 ddt 模块。如果没有安装,可以使用以下命令进行安装:

1
pip install ddt

使用 ddt 进行参数化测试

ddt 模块允许我们使用装饰器 @ddt@data 来实现参数化测试。以下是一个简单的示例:

1
2
3
4
5
6
7
8
9
10
import unittest
from ddt import ddt, data, unpack

@ddt
class TestMathOperations(unittest.TestCase):
@data((1, 1, 2), (2, 3, 5), (0, 0, 0))
@unpack
def test_addition(self, operand1, operand2, expected_result):
result = operand1 + operand2
self.assertEqual(result, expected_result, f"加法运算错误:{operand1} + {operand2} 不等于 {expected_result}")

在这个示例中,test_addition 方法被装饰为参数化测试,通过 @data 装饰器传入了多组输入数据和期望的结果。这样,这个测试用例会根据传入的数据进行多次测试。

实例:参数化测试

实例中出现的 LoginPage 在 自动化测试(9)——实例:使用 Page Object 设计模式编写测试用例 中已经介绍过,这里不再赘述。

接下来,我们将结合一个实例,使用 ddt 模块进行参数化测试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import ddt
import unittest
from selenium import webdriver
from login_page import LoginPage

@ddt.ddt
class TestLoginPage(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Chrome()
self.driver.implicitly_wait(10)

def tearDown(self):
self.driver.quit()

@ddt.unpack
@ddt.data(("admin", "rootadmin", "登录成功"), ("user", "password", "用户名或密码错误"))
def test_login(self, username, password, expected_result):
login_page = LoginPage(self.driver)
login_page.open()
login_page.input_username(username)
login_page.input_password(password)
login_page.click_login_button()
result = login_page.get_result()
self.assertEqual(result, expected_result, f"登录测试失败:{result} 不等于 {expected_result}")

在这个示例中,test_login 方法被装饰为参数化测试,通过 @data 装饰器传入了多组用户名、密码和期望的结果。这样,这个测试用例会对登录功能进行多次测试,验证不同输入数据的登录结果。

进阶:从外部输入参数

在上面的示例中,我们将参数直接写在了测试用例中。这样做的缺点是,当参数发生变化时,我们需要修改测试用例代码。为了解决这个问题,我们可以将参数从外部输入。

从 csv 文件输入参数

我们可以将参数写在 csv 文件中,然后通过 csv 模块读取 csv 文件,将参数传入测试用例。

csv 内容如下:

username password expected_result
admin rootadmin 登录成功
user password 用户名或密码错误
csv文件内容
1
2
3
username,password,expected_result
admin,rootadmin,登录成功
user,password,用户名或密码错误
1
2
3
4
5
6
7
8
9
10
11
# csvv.py
import csv

def get_data():
with open('data.csv', 'r', encoding='utf-8') as f:
reader = csv.reader(f)
result = []
for i, e in enumerate(reader):
if i == 0: continue # 跳过第一行
result.append(e)
return result

将输入的参数传入测试用例

编写完 csvv.py 文件后,我们可以在测试用例中调用 get_data() 方法,将参数传入测试用例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import ddt
import unittest
from selenium import webdriver
from login_page import LoginPage
from csvv import get_data

@ddt.ddt
class TestLoginPage(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Chrome()
self.driver.implicitly_wait(10)

def tearDown(self):
self.driver.quit()

# 从 csv 文件中读取参数
datas = get_data()
@ddt.unpack
@ddt.data(*datas)
def test_login(self, username, password, expected_result):
login_page = LoginPage(self.driver)
login_page.open()
login_page.input_username(username)
login_page.input_password(password)
login_page.click_login_button()
result = login_page.get_result()
self.assertEqual(result, expected_result, f"登录测试失败:{result} 不等于 {expected_result}")

运行测试用例

在运行测试用例前,我们需要将 data.csv 文件放在与测试用例同一目录下。

保证文件结构如下:

1
2
3
4
5
.
│ csvv.py # 读取 csv 文件
│ data.csv # 参数文件
│ login_page.py # 页面对象
│ main.py # 测试用例

运行位于 main.py 的测试用例,得到的结果如下: