资讯详情

资讯详情

Robot Framework循环读取Excel:数据驱动测试实战指南

做自动化测试久了你会发现一个规律凡是涉及业务人员参与维护数据的项目测试数据最后几乎都会落到Excel里。Robot Framework这个关键字驱动的框架跟Excel的配合度一直很高——用例逻辑写在Robot脚本里测试数据由Excel表维护两边各管各的。但真正上手之后不少人会在“循环读取Excel表”这一环卡住表格里有几十行甚至上百行数据怎么让框架自动一行一行读出来再把它变成一次次的测试执行这篇文章就来把这个需求彻底拆开讲清楚从选库、装环境、写循环到排坑实战一条龙给你捋明白。我自己在做接口自动化和Web UI自动化时被这个需求折腾了不少次也踩过一些文档里根本不写的坑。下面这篇内容适合正在用Robot Framework做数据驱动测试、或者准备把Excel作为测试数据源的读者不管你是刚接触RF的新手还是已经写了几个月用例的“半熟手”都能在这篇文章里找到能直接抄走的方案。1. 开始之前这个需求到底在解决什么问题1.1 数据驱动测试中Excel扮演的角色在自动化测试里数据驱动是一种很常见的思路测试步骤和测试数据分离同样的操作逻辑喂进去不同的输入就能得到一组互相独立的测试场景。举一个很典型的例子登录功能。所有人都会断言“用户名密码正确能登录成功”但业务方还会提一堆不那么典型的场景用户名为空会怎样、密码错误会怎样、账号被锁定会怎样。这些场景的预期结果如果用代码硬编码在脚本里业务同事看不懂想加一条case还得找你改代码。这时候Excel的作用就体现出来了——它本身就是一张表天然适合存放“一行一条数据”的测试用例。Robot Framework读取Excel本质上就是在解决这么一件事把表格中每一行数据转换成一次独立的测试执行。第2行是一条“正常登录”的数据执行一遍登录流程并断言成功第3行是一条“密码错误”的数据执行一遍登录流程并断言出现错误提示。循环读取就是让这个动作自动重复下去。1.2 选对Excel操作库能少写一半坑Robot Framework本身不带Excel操作能力需要装第三方库。社区里常用的有三个robotframework-excellibrary、RobotFramework-ExcelLibrary、robotframework-excelrobot。名字很像但差别不小。库名底层依赖支持的Excel格式能否写入适合场景robotframework-excellibrary老版xlrd / xlwt主要是.xls能写但功能弱老项目遗留RobotFramework-ExcelLibrary社区维护版openpyxl.xlsx为主支持推荐日常使用robotframework-excelrobotopenpyxl.xlsx为主支持还能设样式需要写Excel报告时你可能会问为什么老库只认.xls因为它底层用的是xlrd这个库对.xlsx的支持一直不完整。而以openpyxl为底层的库可以直接处理.xlsx也就是现在Excel默认保存的格式兼容性好很多。我个人建议直接安装社区维护的RobotFramework-ExcelLibrary。它的关键字跟老库基本一致学过老用法的人迁移成本很低而且能读.xlsx文件这个太关键了。现在稍微新一点的业务系统导出和保存的表格基本都是.xlsx你要还在为一个.xls文件反复“另存为”效率直接被打对折。还有一个特别值得提醒的坑这两个库在PyPI上的包名大小写有区别一个首字母小写一个首字母大写pip install的时候千万别搞混。装错了导入时大概率报Importing library failed排查起来还挺绕。我的习惯是装完之后先跑一条空用例确认Library能正常导入再进行下一步。2. 环境准备与数据读取原理2.1 安装依赖先把基础跑通在Robot Framework的虚拟环境里安装ExcelLibrary命令很简单pip install RobotFramework-ExcelLibrary如果你的环境里既有老库又有新库建议先卸载干净再装否则两个库的类名可能冲突导入时会报错。装完后可以在Robot脚本里这样引入*** Settings *** Library ExcelLibrary如果你是第一次在这个环境里用Robot Framework还需要确认已安装了RF核心pip install robotframework装完之后写一个最简单的脚本打印出Excel文件的行数能跑通就说明环境没问题。实在不确定库装没装对可以用Robot Framework自带的关键字查看功能robot --listkeywords ExcelLibrary -L INFO这个命令会把库里的所有关键字列出来非常直观。我第一次用这个命令的时候甚至解决了一个“纠结半天以为代码写错、其实是关键字名记错”的问题——没事儿多看看关键字列表比反复翻文档管用。2.2 读取Excel必须弄懂的API细节从Robot Framework操作Excel多数场景只需要掌握几个关键字。以RobotFramework-ExcelLibrary为例最常见的三个是Open Excel打开指定Excel文件参数是文件路径也可以指定Sheet名。Get Row Count获取某个Sheet的总行数返回整数。Read Cell Data读取指定单元格需要传Sheet名、行号、列号。这里有一个非常容易踩的细节ExcelLibrary里的行号和列号从1开始计数。也就是说第一行第一列是(1, 1)不是(0, 0)。做开发久了的人很容易下意识从0开始写一读就错位而且这种错位往往不会报错而是跑到别人的数据上排查起来非常难受。另外Read Cell Data返回的值在Robot Framework看来是一个字符串。就算Excel单元格里存的是数字读出来之后参与字符串拼接或者断言时也要注意类型上的处理。比如你断言“返回码是200”从Excel读出来的是字符串200在RF里做Should Be Equal时与接口返回的整数200比较会失败。这种问题藏得深但好在有固定套路——读出来后用Convert To String或Convert To Integer显式转换一下。关于Sheet的指定方式多数情况下直接用Sheet名称即可。如果Excel里Sheet名包含中文或空格只要Robot环境的编码没问题一般也能正常传参。我建议维护Excel数据源时Sheet名不要起得太随意最好跟业务含义对应比如LoginData、UserInfo后续脚本里看起来一目了然。还有一点Open Excel之后默认会把文件句柄保持打开状态。如果你的测试用例很多建议在整个Suite的Setup里打开在Teardown里关闭避免每条用例都重复打开文件造成性能浪费。3. 循环读取核心写法与进阶用法3.1 FOR循环遍历全表最基础也最常用的写法Robot Framework从4.0版本开始正式把循环语法改成了无冒号的FOR...END形式。循环读取Excel的最基础写法是这样的*** Test Cases *** 循环读取Excel全部行 [Setup] Open Excel ${CURDIR}/testdata.xlsx ${row_count} Get Row Count LoginData Log Excel总行数${row_count} ${last_row} Evaluate ${row_count} 1 FOR ${idx} IN RANGE 2 ${last_row} ${username} Read Cell Data LoginData ${idx} 1 ${password} Read Cell Data LoginData ${idx} 2 Log 第${idx}行用户名${username}密码${password} END [Teardown] Close Excel这里有几个点必须解释清楚不然很多人会在这上面绕半天。第一为什么循环从2开始因为Excel表的第一行通常是表头放的是用户名、密码、预期结果这些列名。从第2行开始才是真正的测试数据。第二为什么结束位置要计算成${row_count}1Robot Framework的IN RANGE是左闭右开区间也就是IN RANGE 2 6会循环2、3、4、5不会跑到6。如果表里一共有10行数据第2行到第11行Get Row Count可能返回11那循环就得写成IN RANGE 2 12也就是${row_count}1。这个“1”是多人的共同泪点忘掉它的结果就是永远读不到最后一行。第三${idx}这个循环变量在RF 4.0之后是循环体内部的局部变量循环结束就访问不到了。所以如果你希望在循环结束后拿到某个值得在循环体内部用Set Global Variable或者Set Suite Variable把它保存下来。3.2 WHILE循环处理动态数据如果只是从头到尾把表遍历一遍FOR循环完全够用。但有些场景下你不知道Excel到底有多少行或者想让循环在某些条件下自己停下来这时候可以用WHILE循环。Robot Framework从5.0版本开始支持WHILE...END。*** Test Cases *** 用WHILE读取Excel直到遇到结束标记 [Setup] Open Excel ${CURDIR}/testdata.xlsx ${idx} Set Variable 2 WHILE ${idx} 100 ${flag} Read Cell Data LoginData ${idx} 4 Exit Loop If ${flag} END ${username} Read Cell Data LoginData ${idx} 1 Log 当前处理${username} ${idx} Evaluate ${idx} 1 END [Teardown] Close Excel这个例子里的逻辑是数据表最后一列放了一个标记位如果某个单元格的值是END就说明后面的数据不用再读了。这种场景在实际工作中很常见比如导出的Excel可能带了汇总行、备注行直接按总行数遍历会读到一堆不该读的内容。WHILE循环在RF 5.0之前没有原生支持如果你用的还是老版本RF要么升级要么用FOR循环加Exit For Loop If模拟。我个人建议能用FOR尽量用FOR因为可读性更好也不容易因为忘记更新循环变量造成死循环。3.3 循环体内部的条件跳转与容错循环本身不难难的是在循环里处理各种“意外情况”。Robot Framework提供了一组循环控制关键字配合读取Excel使用非常顺手Continue For Loop If满足条件时跳过当前这次循环继续下一次。Exit For Loop If满足条件时直接退出整个循环。Run Keyword And Continue On Failure执行某个关键字即使失败了也不中断当前用例。举个例子Excel里有一列数据叫“是否执行”如果值为“否”你希望跳过这一行不执行这条用例。那代码可以写成FOR ${idx} IN RANGE 2 ${last_row} ${execute_flag} Read Cell Data LoginData ${idx} 5 Continue For Loop If ${execute_flag} 否 # 继续执行具体测试步骤 ... END而容错方面如果你希望某一行数据执行失败后循环不要中断、而是接着跑下一行可以用Run Keyword And Continue On Failure把所有关键步骤包起来。这样跑完一整轮之后你拿到的是一个“所有数据行都尝试过了”的结果汇总而不是执行到第3行就断掉后面90多行都没跑。批量回归类的测试尤其依赖这个特性。4. 完整实操从Excel数据到自动化用例4.1 准备一份规范的测试数据文件在真正写代码之前先把测试数据文件准备好。我按登录功能的例子来做演示Excel表的Sheet命名LoginData表头设计如下用户名密码预期结果是否执行admin123456登录成功是test01wrongpass密码错误是test02用户名为空是locked123456账号锁定否注意几个细节。第一表头最好用中文或英文完整描述别用a、b、c这种无意义命名后期维护的人会谢你。第二“是否执行”这一列很有价值它让你不用删除用例只需把状态改成“否”就能临时跳过某条数据。第三文件路径建议统一放在项目下的data目录用${CURDIR}做相对定位跟脚本放一起避免因为路径写死导致换台电脑就跑不了。4.2 单行读取先跑通一个用例再说一上来就写完整循环容易把问题复杂化。我的习惯是先固定读某一行把整个链路跑通再改成循环。比如先读第2行*** Test Cases *** 单行读取验证 [Setup] Open Excel ${CURDIR}/data/login_data.xlsx ${username} Read Cell Data LoginData 2 1 ${password} Read Cell Data LoginData 2 2 ${expected} Read Cell Data LoginData 2 3 Log To Console 读取到${username} / ${password} / ${expected} [Teardown] Close Excel这一步的目的是确认三件事文件能打开、Sheet名正确、行列坐标没有偏移。如果这一条跑通了循环就只是把固定的2换成循环变量${idx}的事。很多人一上来就写完整循环一旦报错就分不清是循环语法错了还是读取数据错了排查成本反而更高。4.3 循环驱动让用例批量跑起来链路通了之后把固定行号换成循环变量用FOR循环遍历所有行。下面是一个结合Web UI登录的完整示例*** Settings *** Library ExcelLibrary Library SeleniumLibrary *** Variables *** ${BASE_URL} http://127.0.0.1:8080/login ${TEST_DATA} ${CURDIR}/data/login_data.xlsx ${SHEET_NAME} LoginData *** Test Cases *** 根据Excel数据循环执行登录测试 [Setup] Open Excel ${TEST_DATA} ${row_count} Get Row Count ${SHEET_NAME} ${last_row} Evaluate ${row_count} 1 FOR ${idx} IN RANGE 2 ${last_row} ${username} Read Cell Data ${SHEET_NAME} ${idx} 1 ${password} Read Cell Data ${SHEET_NAME} ${idx} 2 ${expected} Read Cell Data ${SHEET_NAME} ${idx} 3 ${execute} Read Cell Data ${SHEET_NAME} ${idx} 4 Continue For Loop If ${execute} 否 Log To Console 开始执行第${idx}行${username} Open Browser ${BASE_URL} chrome Input Text idusername ${username} Input Text idpassword ${password} Click Button idloginBtn ${result} Get Text idloginMsg Should Be Equal ${result} ${expected} Close Browser END [Teardown] Close Excel这段代码虽然不长但已经是日常项目里一个非常典型的“Robot Framework Excel数据驱动”模板了。每次循环从Excel取出一行数据拼成一个完整的UI登录场景跑完断言再进入下一行。很多人在这一步会遇到的第一个挫折是浏览器启动速度太慢几十行数据要跑很久。我的建议是如果只是验证数据读取逻辑先把Open Browser那几行注释掉只打日志确认循环和Excel读取没问题了再把UI步骤加回来。分步调试永远比一口气全写出来再从头排查要快。4.4 让每条数据有独立的日志和报错信息上面示例里如果第5行数据断言失败Robot Framework默认只会告诉你“Should Be Equal失败了”但不会指出来是“哪一行、哪条数据”。这在数据量大的时候特别致命。我的做法是在关键步骤前加日志把当前行号和标识性数据打出来Log To Console 当前行${idx}数据${username} 另外数据驱动循环里每一行相当于一条“业务用例”但它们在Robot Framework里属于同一个测试用例。如果你希望每行数据失败时错误信息能直接体现出行号和数据内容可以在断言失败后重新设置测试用例的失败信息${result} Get Text idloginMsg ${pass} Run Keyword And Return Status Should Be Equal ${result} ${expected} Run Keyword If not ${pass} ... Set Test Message 第${idx}行数据失败${username}期望${expected}实际${result} Should Be True ${pass}这样做的好处是测试报告里能看到“到底哪一行、哪条数据出了问题”而不是只有一个干巴巴的Should Be Equal失败。别小看这个细节当Excel里有上百条数据跑完一轮之后这条信息能帮你省下至少半小时的翻日志时间。5. 常见问题与排查技巧实录5.1 文件读取失败路径、扩展名与文件占用最常见的报错就是打不开Excel文件或者加载库失败。我从多个项目里总结大致逃不出这几类原因。第一路径问题。相对路径在Robot Framework里是以运行目录为基准的如果你在不同目录执行robot命令结果可能完全不一样。最稳妥的做法是用${CURDIR}变量拼接路径——它代表当前测试文件所在目录。比如${TEST_DATA} ${CURDIR}/data/login_data.xlsx第二扩展名与实际格式不匹配。有的Excel文件后缀是.xlsx但实际是.xls格式保存的或者是从某个业务系统导出的伪Excel文件。遇到这种文件openpyxl底层打开时会直接报格式错误。解决办法是用Excel软件把文件另存为正确的.xlsx格式或者在代码里换一个兼容层库。第三文件被占用。Excel文件正在被WPS或Office打开时Robot Framework读取往往失败提示文件被占用或没有权限。这个场景特别常见——业务同事正开着Excel改数据你这边自动化跑了一半直接崩掉。我习惯在自动化任务开始前明确跟业务同事约定“跑批期间不要打开数据文件”从源头上把这个坑填掉。5.2 中文乱码与编码问题读出的中文变成乱码这个在早期RF版本里偶有发生。排查时先确认两件事一是Excel文件本身内容正常二是Robot Framework脚本文件保存为了UTF-8格式。脚本文件编码有问题时你在脚本里写的中文常量会乱但是读Excel返回的中文一般不会受影响因为openpyxl底层处理的是Unicode字符串。如果你遇到的是Read Cell Data返回中文后日志里显示为\uXXXX这种转义形式那只是日志展示问题数据本身没坏直接拿去断言或写入系统是没问题的。5.3 单元格内容不对日期、公式与合并单元格这一节是干货中的干货。用ExcelLibrary读取数据时有几类单元格特别容易出问题。第一日期类型。Excel里的日期存储本质是序列号比如45000这种。直接读出来你不会得到2023-03-15而是一串数字。如果你需要在测试里用日期字符串建议在Excel里就把该列设置成文本格式或者写入的时候就存字符串。第二公式单元格。如果Excel里某个单元格是公式比如A2B2Robot Framework读取时拿到的通常不是公式本身而是公式计算后缓存的值。这通常没问题但如果你修改了公式关联的单元格而Excel没有重新计算并保存读出来的缓存值可能是旧的。我的经验是数据驱动的源文件里尽量不用公式要算就让业务同事在Excel里算好再另存为静态数据。第三合并单元格。这是最隐蔽的坑。假设A2到A5合并成了一个单元格用Read Cell Data读取第2行能拿到值但读取第3、4、5行时得到的往往是空字符串。数据文件里遇到合并单元格要么取消合并要么在读取时先判断是否为空再决定是否取上一行的值。如果你打算做深度的Excel数据处理这块需要花点心思单独写一个处理逻辑。5.4 大批量数据下的性能优化循环读取Excel在数据量几百行时性能几乎无感。但如果数据量上千行且每一行都伴随UI自动化操作跑批时间会变得非常长。这种情况下首先要确认的是Open Excel只调用了一次而不是在循环体里反复打开文件。其次如果只是读取数据不要用带写入功能的库函数减少不必要的IO。如果你的数据量级到了几千上万行Robot Framework直接循环的方式已经不够优雅了。我通常的处理方式是不在Robot里做复杂循环而是先用Python脚本或pandas把Excel数据预处理成更友好的格式比如json或csv再交给Robot Framework读取。这样既利用了Python生态处理数据的强项也保持了Robot脚本的可读性。不过对于绝大多数测试场景几百行数据用ExcelLibrary直接循环完全够用没必要过早优化。写在最后的一点经验我实际做项目时发现“Robot Framework循环读取Excel”这个需求真正的难点不在于循环语法也不在于读取API而在于把“数据文件的设计”和“测试用例的组织”想清楚。表头怎么定、哪些列是输入、哪些列是预期、哪些行要跳过、跑挂了一条要不要继续这些问题在设计阶段想好了后面就是纯粹的体力活。最后分享一个小技巧数据文件里留一列“备注”哪怕平时不读它也能在数据出错时帮你在Excel里快速定位那一行的意图。另外自动化跑批之前把Excel备份一份到backup目录我曾经因为同事误改了一个单元格整批测试数据跑出了完全不同的结果当时要不是有备份定位起来要花好几倍时间。测试数据也是资产别嫌麻烦。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →