news 2026/4/24 20:47:37

第七篇:《数据驱动测试:利用Excel/JSON/CSV管理测试数据》

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
第七篇:《数据驱动测试:利用Excel/JSON/CSV管理测试数据》

当我们需要测试同一个功能(如登录)覆盖多组输入数据时,最笨的方法是复制粘贴测试方法,修改几个参数。更优雅的做法是数据驱动测试:将测试数据与测试逻辑分离,用一个方法执行多组数据。本文将分别用Java(TestNG)和Python(pytest)演示如何从Excel、JSON、CSV读取数据,并给出设计规范与最佳实践。

一、什么是数据驱动测试?

数据驱动测试(DDT):使用不同的输入数据多次运行同一个测试用例,并将预期结果与实际情况比较。

典型的应用场景:

登录功能:多组用户名/密码(正确、错误、空、边界值)

表单验证:不同输入组合下的错误提示

搜索功能:多个关键词组合

配置参数测试:不同配置下的页面行为

优点:

减少重复代码,一个测试方法覆盖所有数据组合

数据与逻辑分离,非技术人员也可维护数据文件

增加测试覆盖率而不增加维护成本

二、数据驱动的方式与工具

本文重点讲解外部文件驱动:Excel、JSON、CSV。

三、Java + TestNG:数据驱动实现

TestNG 提供了 @DataProvider 注解,可以返回 Object[][] 数据。我们结合三大数据源构建 DataProvider。

3.1 准备工作
Maven依赖:

<!-- Apache POI for Excel --><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.2.5</version></dependency><!-- Jackson for JSON --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.15.3</version></dependency><!-- OpenCSV --><dependency><groupId>com.opencsv</groupId><artifactId>opencsv</artifactId><version>5.8</version></dependency>

3.2 从Excel读取数据(.xlsx)
Excel文件 testdata/login_data.xlsx 结构:

工具类:ExcelDataProvider.java

importorg.apache.poi.ss.usermodel.*;importorg.apache.poi.xssf.usermodel.XSSFWorkbook;importjava.io.InputStream;importjava.util.ArrayList;importjava.util.HashMap;importjava.util.List;importjava.util.Map;publicclassExcelDataProvider{publicstaticObject[][]getData(StringfilePath,StringsheetName){try(InputStreamis=ExcelDataProvider.class.getResourceAsStream(filePath);Workbookworkbook=newXSSFWorkbook(is)){Sheetsheet=workbook.getSheet(sheetName);RowheaderRow=sheet.getRow(0);intcolCount=headerRow.getLastCellNum();List<Map<String,String>>dataList=newArrayList<>();for(inti=1;i<=sheet.getLastRowNum();i++){Rowrow=sheet.getRow(i);if(row==null)continue;Map<String,String>rowMap=newHashMap<>();for(intj=0;j<colCount;j++){Cellcell=row.getCell(j,Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);Stringheader=headerRow.getCell(j).getStringCellValue();Stringvalue=getCellValueAsString(cell);rowMap.put(header,value);}dataList.add(rowMap);}// 转换为Object[][]Object[][]data=newObject[dataList.size()][1];for(inti=0;i<dataList.size();i++){data[i][0]=dataList.get(i);}returndata;}catch(Exceptione){thrownewRuntimeException("读取Excel失败",e);}}privatestaticStringgetCellValueAsString(Cellcell){if(cell==null)return"";returnswitch(cell.getCellType()){caseSTRING->cell.getStringCellValue();caseNUMERIC->String.valueOf((long)cell.getNumericCellValue());caseBOOLEAN->String.valueOf(cell.getBooleanCellValue());default->"";};}}

测试用例:

java

importorg.testng.annotations.DataProvider;importorg.testng.annotations.Test;importjava.util.Map;publicclassLoginDDTTest{@DataProvider(name="loginExcelData")publicObject[][]excelData(){returnExcelDataProvider.getData("/testdata/login_data.xlsx","Sheet1");}@Test(dataProvider="loginExcelData")publicvoidtestLoginWithExcel(Map<String,String>data){Stringusername=data.get("username");Stringpassword=data.get("password");Stringexpected=data.get("expected_result");Stringmessage=data.get("message");// 使用Page Object执行登录LoginPageloginPage=newLoginPage(driver);if("success".equals(expected)){HomePagehome=loginPage.loginAs(username,password);Assert.assertTrue(home.isWelcomeDisplayed(),message);}else{loginPage.loginAs(username,password);Stringerror=loginPage.getErrorMessage();Assert.assertTrue(error.contains(message),"错误信息不匹配");}}}

3.3 从JSON读取数据
JSON文件 login_data.json:

json
[
{
“username”: “admin”,
“password”: “123456”,
“expected”: “success”,
“message”: “登录成功”
},
{
“username”: “admin”,
“password”: “wrong”,
“expected”: “fail”,
“message”: “密码错误”
}
]
数据提供者:

importcom.fasterxml.jackson.databind.ObjectMapper;importjava.io.InputStream;importjava.util.List;importjava.util.Map;publicclassJsonDataProvider{publicstaticObject[][]getData(StringjsonPath){try(InputStreamis=JsonDataProvider.class.getResourceAsStream(jsonPath)){ObjectMappermapper=newObjectMapper();List<Map<String,String>>list=mapper.readValue(is,List.class);Object[][]data=newObject[list.size()][1];for(inti=0;i<list.size();i++){data[i][0]=list.get(i);}returndata;}catch(Exceptione){thrownewRuntimeException("读取JSON失败",e);}}}

使用方法与Excel类似。

3.4 从CSV读取数据
CSV文件 login_data.csv:

csv
username,password,expected,message
admin,123456,success,登录成功
admin,wrong,fail,密码错误
,any,fail,用户名不能为空
使用OpenCSV:

importcom.opencsv.CSVReader;importcom.opencsv.exceptions.CsvException;importjava.io.InputStreamReader;importjava.util.List;publicclassCsvDataProvider{publicstaticObject[][]getData(StringcsvPath){try(CSVReaderreader=newCSVReader(newInputStreamReader(CsvDataProvider.class.getResourceAsStream(csvPath)))){List<String[]>allRows=reader.readAll();String[]headers=allRows.get(0);Object[][]data=newObject[allRows.size()-1][1];for(inti=1;i<allRows.size();i++){String[]row=allRows.get(i);Map<String,String>rowMap=newHashMap<>();for(intj=0;j<headers.length;j++){rowMap.put(headers[j],row.length>j?row[j]:"");}data[i-1][0]=rowMap;}returndata;}catch(Exceptione){thrownewRuntimeException("读取CSV失败",e);}}}

四、Python + pytest:数据驱动实现

pytest 主要使用 @pytest.mark.parametrize 装饰器,也可借助 pytest-csv、pytest-excel 或手动读取。

4.1 从CSV读取(最轻量)
CSV文件同上。

读取辅助函数:

importcsvimportpytestdefload_csv_data(file_path):data=[]withopen(file_path,mode='r',encoding='utf-8')asfile:reader=csv.DictReader(file)forrowinreader:data.append(row)returndata

测试用例:

importpytestfrompages.login_pageimportLoginPage test_data=load_csv_data("testdata/login_data.csv")@pytest.mark.parametrize("case",test_data,ids=lambdax:x.get("message",""))deftest_login_with_csv(driver,case):login_page=LoginPage(driver)ifcase["expected"]=="success":home=login_page.login_as(case["username"],case["password"])asserthome.is_welcome_displayed(),case["message"]else:login_page.login_as(case["username"],case["password"])error=login_page.get_error_message()assertcase["message"]inerror

4.2 从JSON读取

importjsondefload_json_data(file_path):withopen(file_path,'r',encoding='utf-8')asf:data=json.load(f)returndata# list of dicts# 使用同上 parametrize

4.3 从Excel读取(openpyxl)
安装:pip install openpyxl

importopenpyxldefload_excel_data(file_path,sheet_name):wb=openpyxl.load_workbook(file_path,data_only=True)sheet=wb[sheet_name]headers=[cell.valueforcellinsheet[1]]data=[]forrowinsheet.iter_rows(min_row=2,values_only=True):row_dict=dict(zip(headers,row))data.append(row_dict)returndata

五、数据文件设计规范

列命名清晰:使用username而非un,便于理解和维护。

包含标识列:可加case_id或description列,便于定位失败数据。

预期结果描述明确:expected_result可以是success/fail,message是断言内容。

处理空值:CSV和Excel中空单元格要统一转化为空字符串或None。

敏感数据脱敏:不要将真实密码提交到代码仓库,可加密或使用环境变量。

六、数据驱动的优缺点总结

七、最佳实践与注意事项

一个数据文件对应一个测试类:按业务模块组织数据。

测试数据独立于环境:不要在数据文件中硬编码URL,从配置读取。

使用数据ID标记:测试报告中显示正在运行哪一组数据,快速定位。

TestNG: @Test(dataProvider = “…”, dataProviderClass = …) 配合 ITestContext 可设置测试名称。

pytest: ids参数可为每条数据生成描述。

定期清理无用数据:避免数据文件膨胀。

八、总结

核心要点:

数据驱动将测试逻辑与测试数据分离,显著降低维护成本。

TestNG的@DataProvider配合外部文件(Excel/JSON/CSV)灵活强大。

pytest的@pytest.mark.parametrize装饰器配合文件读取同样高效。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/24 20:47:27

YoptaScript测试驱动开发:确保你的街头代码质量

YoptaScript测试驱动开发&#xff1a;确保你的街头代码质量 【免费下载链接】YoptaScript Joke programming language for gopniks in Russia. Back from 2016! 项目地址: https://gitcode.com/gh_mirrors/yo/YoptaScript YoptaScript作为一款源自2016年的俄罗斯"街…

作者头像 李华
网站建设 2026/4/24 20:45:59

5分钟上手Zotero-Style:让文献管理焕然一新的终极美化插件

5分钟上手Zotero-Style&#xff1a;让文献管理焕然一新的终极美化插件 【免费下载链接】zotero-style Ethereal Style for Zotero 项目地址: https://gitcode.com/GitHub_Trending/zo/zotero-style 还在为Zotero单调的界面发愁吗&#xff1f;想让学术文献管理变得既美观…

作者头像 李华
网站建设 2026/4/24 20:45:49

SAP VF01/VF02/VF03 屏幕增强实战:在抬头区集成自定义子屏幕

1. 理解需求背景与核心概念 最近接到一个典型的SAP SD模块增强需求&#xff1a;在VF02/VF03标准开票事务的抬头区域&#xff0c;增加一个用于显示和录入"金税发票号"的自定义子屏幕。这个需求看似简单&#xff0c;但涉及SAP标准程序的深度定制&#xff0c;需要系统性…

作者头像 李华
网站建设 2026/4/24 20:44:58

PDF文档对比终极解决方案:diff-pdf深度解析与实战指南

PDF文档对比终极解决方案&#xff1a;diff-pdf深度解析与实战指南 【免费下载链接】diff-pdf A simple tool for visually comparing two PDF files 项目地址: https://gitcode.com/gh_mirrors/di/diff-pdf 你是否曾经为了找出两个PDF文档的细微差异而头疼不已&#xff…

作者头像 李华
网站建设 2026/4/24 20:42:04

RoseTTAFold代码架构深度剖析:理解模块化设计的精髓

RoseTTAFold代码架构深度剖析&#xff1a;理解模块化设计的精髓 【免费下载链接】RoseTTAFold This package contains deep learning models and related scripts for RoseTTAFold 项目地址: https://gitcode.com/gh_mirrors/ro/RoseTTAFold RoseTTAFold是一个包含深度学…

作者头像 李华
网站建设 2026/4/24 20:42:02

Ubuntu 22.04编译Linux 5.16.5内核,解决‘BTF加载失败’报错的完整指南

Ubuntu 22.04编译Linux 5.16.5内核实战&#xff1a;深度解析BTF加载失败与精准修复方案 在Linux系统维护和开发领域&#xff0c;内核编译是一项既基础又关键的高级技能。当Ubuntu 22.04用户尝试将内核从默认的5.15版本升级到5.16.5时&#xff0c;往往会遇到一个令人困惑的报错…

作者头像 李华