Pytest入门系列之pytest的参数化 pytest
参数化 允许我们在同一个测试函数中运行多个输入组合,避免重复代码,提高测试覆盖率,特别适用于:
✅单元测试(多个输入输出组合) ✅API
测试(不同请求参数) ✅数据库测试(不同数据集) ✅前端 UI 测试(不同浏览器)
@pytest.mark.parametrize 基本用法 🔹 示例:测试加法函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import pytestdef add (x, y ): return x + y@pytest.mark.parametrize("a, b, expected" , [ (1 , 2 , 3 ), (-1 , 5 , 4 ), (0 , 0 , 0 ), ] )def test_add (a, b, expected ): assert add(a, b) == expected
📌 执行测试
📌 测试输出
1 2 3 test_example.py::test_add[1-2-3] PASSED test_example.py::test_add[-1-5-4] PASSED test_example.py::test_add[0-0-0] PASSED
📌 解析
@pytest.mark.parametrize
(“参数名1, 参数名2, 期望值”, [(参数1, 参数2, 期望值)])
每个测试用例都会运行一次,传入不同参数。
避免重复编写多个 test_add_xxx 测试函数,提高可读性。
企业实战:参数化 API 测试 📌 应用场景
✅API
需要测试多个请求参数 ✅检查 API
返回的 HTTP
状态码 ✅验证 API
返回的数据结构
🔹 示例:测试 API 响应
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import pytestimport requests BASE_URL = "https://jsonplaceholder.typicode.com/posts" @pytest.mark.parametrize("post_id, expected_status" , [ (1 , 200 ), (100 , 200 ), (9999 , 404 ), ] )def test_api_response (post_id, expected_status ): response = requests.get(f"{BASE_URL} /{post_id} " ) assert response.status_code == expected_status
📌 执行测试
📌 测试输出
1 2 3 test_api.py::test_api_response[1-200] PASSED test_api.py::test_api_response[100-200] PASSED test_api.py::test_api_response[9999-404] PASSED
📌 解析
不同 post_id
发送 API
请求
检查 response.status_code
是否符合预期
同一函数可测试多个 API
场景,提升测试效率
参数化 UI 自动化测试 📌 应用场景
✅跨浏览器测试 ✅不同用户角色测试
🔹 示例: UI 测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import pytestfrom selenium import webdriver@pytest.mark.parametrize("browser" , ["chrome" , "firefox" ] ) def test_open_google (browser ): if browser == "chrome" : driver = webdriver.Chrome() elif browser == "firefox" : driver = webdriver.Firefox() else : pytest.fail("❌ 不支持的浏览器" ) driver.get("https://www.google.com" ) assert "Google" in driver.title driver.quit()
📌 执行测试
📌 测试输出
1 2 test_ui.py::test_open_google[chrome] PASSED test_ui.py::test_open_google[firefox] PASSED
📌 解析
在 test_open_google
里,自动运行 2 次,分别测试 Chrome
和 Firefox
提升 ``UI` 自动化测试的兼容性
参数组合(笛卡尔积) 📌 测试不同浏览器 + 用户角色的组合
🔹 示例:参数组合
1 2 3 4 5 @pytest.mark.parametrize("browser" , ["chrome" , "firefox" ] ) @pytest.mark.parametrize("user_role" , ["admin" , "guest" ] ) def test_login (browser, user_role ): print (f"🖥️ 浏览器: {browser} , 👤 用户角色: {user_role} " )
📌 执行测试
📌 生成的组合
1 2 3 4 5 test_login[chrome-admin] PASSED test_login[chrome-guest] PASSED test_login[firefox-admin] PASSED test_login[firefox-guest] PASSED
📌 4 组测试组合,自动生成(笛卡尔积)
使用 pytest.param 进行标记 📌 pytest.param
允许:
✅单独设置 pytest.mark.xfail
(预期失败) ✅单独为测试添加 id
方便区分
🔹 示例:部分测试标记 xfail
1 2 3 4 5 6 7 @pytest.mark.parametrize("a, b, expected" , [ (1 , 2 , 3 ), pytest.param(2 , 2 , 5 , marks=pytest.mark.xfail(reason="已知问题" ) ), ] )def test_math (a, b, expected ): assert a + b == expected
📌 执行测试
📌 输出
1 2 test_math[1-2-3] PASSED test_math[2-2-5] XFAIL
📌 适用于
✅标记已知缺陷 ✅跳过特定测试
从 Excel/Yaml/Json/数据库 动态加载参数 从 Excel 读取参数化数据 📌 场景:
Excel
文件 常用于管理 测试数据,比如: ✅ 用户登录测试(账号、密码) ✅ 接口测试(API 参数) ✅ 前端 UI 测试(不同输入数据)
📌 为什么使用 pandas
处理 Excel
?
更快:比 openpyxl
解析速度快
功能更强:可以处理 大规模数据
数据过滤、转换更方便
🔹 安装 pandas
📌 pandas
用于解析 Excel
🔹 创建 Excel
文件(test_data.xlsx)
📌 Excel
示例数据
用户名
密码
预期结果
admin
admin123
success
user1
pass123
success
guest
wrongpwd
failure
🔹 代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import pytestimport pandas as pddef load_excel_data (file, sheet_name ): df = pd.read_excel(file, sheet_name=sheet_name) return df.values.tolist() @pytest.mark.parametrize("username, password, expected" , load_excel_data("test_data.xlsx" , "Sheet1" ) ) def test_login_excel (username, password, expected ): print (f"🔐 测试登录 - 用户名: {username} , 密码: {password} " ) assert (username == "admin" and password == "admin123" ) == (expected == "success" )
🔹 案例: Excel
复杂数据处理
📌 处理数据格式
✅去掉 NaN
值 ✅过滤掉某些列 ✅修改数据格式
🔹 代码示例:
1 2 3 4 5 6 def load_cleaned_excel_data (file, sheet_name ): df = pd.read_excel(file, sheet_name=sheet_name) df = df.dropna() df["username" ] = df["username" ].astype(str ) return df[["username" , "password" , "expected" ]].values.tolist()
📌 使用 pytest.mark.parametrize
1 2 3 4 @pytest.mark.parametrize("username, password, expected" , load_cleaned_excel_data("test_data.xlsx" , "Sheet1" ) ) def test_login_excel_clean (username, password, expected ): print (f"🔐 测试登录 - 用户名: {username} , 密码: {password} " ) assert (username == "admin" and password == "admin123" ) == (expected == "success" )
从 YAML 读取参数化数据 📌 场景:
YAML
适用于 配置类测试(如环境变量、API
测试)
🔹 安装依赖
🔹 创建 YAML
文件 (config.yaml)
1 2 3 4 5 6 7 8 9 10 11 users: - username: "admin" password: "admin123" expected: "success" - username: "user1" password: "pass123" expected: "success" - username: "guest" password: "wrongpwd" expected: "failure"
🔹 代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import pytestimport yamldef load_yaml_data (file ): with open (file, "r" , encoding="utf-8" ) as f: data = yaml.safe_load(f) return [(user["username" ], user["password" ], user["expected" ]) for user in data["users" ]]@pytest.mark.parametrize("username, password, expected" , load_yaml_data("config.yaml" ) ) def test_login_yaml (username, password, expected ): print (f"🔐 YAML 测试登录 - 用户名: {username} , 密码: {password} " ) assert (username == "admin" and password == "admin123" ) == (expected == "success" )
📌 适用于
✅ 测试环境变量、配置类参数 ✅ API
测试数据维护
从 JSON 读取参数化数据 📌 场景:
✅JSON
适用于 API
测试 ✅接口入参存储在 JSON
文件中
🔹 创建 JSON
文件 (test_data.json)
1 2 3 4 5 6 [ { "username" : "admin" , "password" : "admin123" , "expected" : "success" } , { "username" : "user1" , "password" : "pass123" , "expected" : "success" } , { "username" : "guest" , "password" : "wrongpwd" , "expected" : "failure" } ]
🔹 代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import pytestimport jsondef load_json_data (file ): with open (file, "r" , encoding="utf-8" ) as f: data = json.load(f) return [(user["username" ], user["password" ], user["expected" ]) for user in data]@pytest.mark.parametrize("username, password, expected" , load_json_data("test_data.json" ) ) def test_login_json (username, password, expected ): print (f"🔐 JSON 测试登录 - 用户名: {username} , 密码: {password} " ) assert (username == "admin" and password == "admin123" ) == (expected == "success" )
📌 适用于 ✅ REST API
测试 ✅ 数据驱动测试(DDT)
从 MySQL 数据库读取参数化数据 📌 场景:
✅直接从 MySQL 获取测试数据(如用户信息、订单信息) ✅适用于 数据驱动测试(DDT)
🔹 安装 pymysql
🔹 创建测试数据库
1 2 3 4 5 6 7 8 9 10 11 12 13 CREATE DATABASE test_db; USE test_db;CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR (50 ), password VARCHAR (50 ), expected VARCHAR (10 ) );INSERT INTO users (username, password, expected) VALUES ("admin", "admin123", "success"), ("user1", "pass123", "success"), ("guest", "wrongpwd", "failure");
🔹 代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import pytestimport pymysqldef load_mysql_data (): conn = pymysql.connect(host="localhost" , user="root" , password="root" , database="test_db" ) cursor = conn.cursor() cursor.execute("SELECT username, password, expected FROM users" ) data = cursor.fetchall() conn.close() return data@pytest.mark.parametrize("username, password, expected" , load_mysql_data( ) ) def test_login_mysql (username, password, expected ): print (f"🔐 MySQL 测试登录 - 用户名: {username} , 密码: {password} " ) assert (username == "admin" and password == "admin123" ) == (expected == "success" )
📌 适用于 ✅ 数据库测试(如订单、用户数据) ✅ 测试真实业务数据
总结
数据源
适用场景
预期结代码示例
Excel(pandas)
手动维护的测试数据(如账号/密码)
load_excel_data("test_data.xlsx")
YAML(pyyaml)
配置文件、环境变量测试
load_yaml_data("config.yaml")
JSON(json)
API 参数测试
load_json_data("test_data.json")
MySQL(pymysql)
数据库数据驱动测试
load_mysql_data()
以上几种的参数化都会极大的提高我们的工作效率,至于选择什么作为数据源基本都差不多,当然还是要结合你的实际业务选择!