ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Robot Framework接口自动化实践:关键字驱动、数据驱动与持续集成

Robot Framework接口自动化实践:关键字驱动、数据驱动与持续集成 1. 为什么我推荐用Robot Framework做接口自动化先说说我的背景做了这些年测试从手工点点点到搭建自动化框架中间换过不少工具。接口自动化这块我用过Pythonrequests手写脚本也试过PostmanNewman做数据驱动最后反而回到了Robot Framework这个“老家伙”身上。很多人一听Robot Framework第一反应是“这不是做UI自动化的吗”其实它做接口自动化同样顺手甚至是团队落地接口自动化最平滑的路径。原因很简单第一关键字驱动天然适合接口测试。接口测试本质上就是“发送请求→校验响应”这个流程写成关键字就是POST、GET、Should Be Equal As Strings这些。相比用Python写一堆函数Robot Framework把这些动作全变成了表格里的关键字测试用例的可读性直接拉满。第二团队成员上手门槛低。我自己带过不少刚入行的测试同学让一个只会手工测试的人看Python代码他大概率一脸懵但让他看Robot Framework的用例哪怕没写过代码也能看懂“哦这是发送一个GET请求检查返回的code是不是200”。这个优势在大规模推广自动化时极其重要——写用例的人不一定是会写代码的人。第三生态里有现成的接口测试库。RequestsLibrary封装了requests库的绝大部分功能Collections库处理JSON数据也很方便再加上Robot Framework强大的报告系统一套完整的接口自动化方案基本是开箱即用的。当然它也有槽点比如语法灵活性不如纯代码、Debug体验一般等。但我这篇文章不吹不黑把实际用得顺的、踩过坑的都盘一遍尤其适合准备入门接口自动化、或者正在纠结选什么框架的测试同学。2. 环境搭建从零到跑通第一个接口用例2.1 环境准备与版本选择Robot Framework是个Python生态的工具所以第一步还是得先把Python装好。我建议装Python 3.8以上的版本太老的3.6在某些依赖上会遇到兼容性问题太新的比如3.12刚出那阵子对部分第三方库的wheel包支持还不全。实测下来Python 3.10是目前兼容性最稳的选择。装完Python后用pip安装三个核心库pip install robotframework pip install robotframework-requests pip install robotframework-pythonlibcore第一个是Robot Framework本体第二个是接口测试要用的RequestsLibrary第三个算是依赖库安装时通常会自动带上不过手动指定一下版本更保险。验证安装是否成功终端执行robot --version如果能正常输出版本号比如Robot Framework 6.1.1 (Python 3.10.11 on linux)那环境基本就绪。注意Windows系统下建议不要用系统自带的PowerShell直接装更不要用pip install装到系统Python目录。最好用虚拟环境venv或者Anaconda管理不然以后项目多了依赖冲突会让人想砸电脑。我第一次就是直接装系统Python里后来另一个项目要用旧版robotframework两个版本打架打到怀疑人生。2.2 第一个接口用例请求一个公开API环境准备好了我们直接上手第一个用例。我习惯先用公开的免费API做实验比如httpbin.org这个站点专门用来测试HTTP请求的各种场景。先建一个测试套件文件命名为first_api_test.robot*** Settings *** Library RequestsLibrary Library Collections *** Test Cases *** 第一个GET请求测试 Create Session mysession https://httpbin.org ${response} GET On Session mysession /get Log ${response.text} Should Be Equal As Integers ${response.status_code} 200在终端运行robot first_api_test.robot跑完后会生成output.xml、log.html、report.html三个文件用浏览器打开log.html就能看到详细的请求和响应日志。这里逐行解释一下这个用例Create Session就是建立一个HTTP会话第一个参数是会话别名第二个参数是Base URL。后续同一个域名下的接口请求都用这个session发复用连接池速度更快。GET On Session是RequestsLibrary提供的关键字做GET请求用。类似的还有POST On Session、PUT On Session、DELETE On Session。${response}是响应对象里面包含status_code、text、json()等属性和方法。Should Be Equal As Integers是断言关键字校验返回码是200。这套“建会话→发请求→校验响应”的模式就是Robot Framework接口自动化的基本骨架后面所有复杂场景都是在这个骨架上长出来的。2.3 目录结构设计从一开始就别随意很多新手学自动化上来就一个.robot文件走天下。短时间没问题但用例一多维护成本直接爆炸。我一般会按这个结构组织项目api_test_project/ ├── test_cases/ │ ├── user_module/ │ │ ├── user_login.robot │ │ └── user_info.robot │ └── order_module/ │ └── order_create.robot ├── resources/ │ ├── common_keywords.robot │ ├── variables.py │ └── data/ │ ├── user_data.robot │ └── order_data.robot ├── results/ └── run_all.pytest_cases/放测试用例文件按业务模块建子目录。resources/放公共关键字、全局变量、测试数据。results/运行后的报告和日志统一输出到这里方便Jenkins之类的CI工具收集。这样的好处是用例、关键字、数据三层分离改数据不动用例改公共逻辑不动业务用例后期维护时痛苦程度能降一个量级。3. 核心库与关键写法RequestsLibrary的深度用法3.1 请求方式全覆盖POST、PUT、DELETE、上传文件GET请求只能算开胃菜接口自动化里POST请求才是常态。我拿一个登录接口举例展示完整的POST请求写法*** Test Cases *** 用户登录测试 Create Session login_session https://api.example.com ${headers} Create Dictionary Content-Typeapplication/json ${body} Create Dictionary usernameadmin password123456 ${response} POST On Session login_session /api/login headers${headers} json${body} Log ${response.text} Should Be Equal As Integers ${response.status_code} 200这里有个关键点RequestsLibrary里POST On Session传JSON数据用的是json参数直接传Python字典。很多新手会去拼JSON字符串再自己用json.loads转换完全没必要框架已经帮你处理好了。上传文件用files参数${file_content} Get Binary File /path/to/test.png ${files} Create Dictionary file(${file_content}, image/png) ${response} POST On Session upload_session /api/upload files${files}PUT、DELETE、PATCH和POST用法基本一致只是关键字换一下这里不赘述。3.2 JSON响应处理从响应到断言的完整链路接口返回的JSON数据是接口自动化里打交道最多的东西。Robot Framework处理JSON有两个层级第一层直接用响应对象的json()方法把JSON转成字典。但这个方法返回的是Python对象在Robot Framework里操作起来需要对Collections库的方法很熟才能用得顺手。第二层用Evaluate关键字直接调Python方法处理${response_json} Evaluate $response.json() ${token} Get From Dictionary ${response_json[data]} token Should Not Be Empty ${token}如果项目里嵌套JSON结构特别深比如返回一个多层嵌套的订单对象一层层Get From Dictionary会写得很痛苦。我的做法是直接用列表推导式或者jsonpath库${token} Evaluate jsonpath.jsonpath(${response.text}, $.data.token)[0] modulesjsonpath通过modulesjsonpath参数把jsonpath库加载进来就能用JSONPath表达式直接提取深层字段比一层层剥洋葱省太多事了。3.3 断言的艺术不只是比对状态码接口自动化的核心目标是验证“接口行为是否符合预期”。不少新手把断言简单理解成“检查状态码是不是200”这远远不够。一个完整的接口断言我习惯分三层第一层HTTP状态码断言Should Be Equal As Integers ${response.status_code} 200这层断言验证请求是否被服务器正常处理。注意状态码200不代表业务成功很多接口用200返回业务错误码。第二层业务状态码断言${response_json} Evaluate $response.json() Should Be Equal As Strings ${response_json[code]} 0公司内部接口通常会在body里返回业务码比如code0表示成功code10001表示参数错误。这层断言才是验证业务逻辑是否通过的关键。第三层关键业务字段断言Should Be Equal As Strings ${response_json[data][userName]} 张三 Should Be True ${response_json[data][balance]} 0这层验证具体的业务数据是否正确。比如登录接口返回的用户名是不是预期用户余额是否大于0订单状态是否已支付等等。三层断言写下来才算真正验证了一个接口的完整行为。单查状态码接口内部返回500的那种错误你根本测不出来。3.4 自定义关键字与公共方法封装同一套业务里很多接口都要用到“先登录拿token”这个前置动作。如果每个用例都复制一遍登录逻辑用例文件会又臭又长后期改个登录接口名都得全局搜索替换。我的做法是把这个动作封装成公共关键字。在resources/common_keywords.robot里写*** Keywords *** 获取用户Token [Arguments] ${username} ${password} Create Session auth_session https://api.example.com ${headers} Create Dictionary Content-Typeapplication/json ${body} Create Dictionary username${username} password${password} ${response} POST On Session auth_session /api/login headers${headers} json${body} Should Be Equal As Integers ${response.status_code} 200 ${response_json} Evaluate $response.json() ${token} Get From Dictionary ${response_json[data]} token [Return] ${token}然后在具体用例里引入这个资源文件*** Settings *** Library RequestsLibrary Resource ../resources/common_keywords.robot *** Test Cases *** 查询用户信息 ${token} 获取用户Token admin 123456 Create Session user_session https://api.example.com ${headers} Create Dictionary AuthorizationBearer ${token} ${response} GET On Session user_session /api/user/info headers${headers} ...这样写的好处是token获取逻辑只维护一份登录接口如果从/api/login改成/api/v2/login只改公共关键字一处即可。4. 数据驱动Excel和CSV参数化的完整方案4.1 为什么必须做数据驱动接口测试最烦的是什么一是一个接口几十上百条测试数据一条条写在用例里二是测试数据和用例代码耦合在一起产品改了个字段名用例要跟着改一堆。数据驱动的核心思想是把测试数据从用例里剥离出去放到Excel、CSV、YAML或Python变量文件里用例通过参数引用的方式读取。这样加一条测试数据只需要在数据文件里加一行完全不用动用例代码。4.2 用Excel做数据驱动的实操Robot Framework官方推荐用robotframework-excelibrary处理Excel但这个库好久没更新了在Python 3.10环境下经常报依赖错误。我自己更常用robotframework-datadriver这个库它天然支持Excel和CSV作为测试数据源。先安装pip install robotframework-datadriver然后在测试套件里这样写*** Settings *** Library DataDriver ../resources/data/user_cases.xlsx sheet_name登录用例 *** Test Cases *** 登录接口_${case_name} [Template] 登录接口通用用例 ${username} ${password} ${expect_code} ${expect_msg}对应的Excel结构是case_nameusernamepasswordexpect_codeexpect_msg正确账号密码admin1234560登录成功密码错误adminwrong10002密码错误用户不存在nobody12345610001用户不存在然后写通用用例模板*** Keywords *** 登录接口通用用例 [Arguments] ${username} ${password} ${expect_code} ${expect_msg} Create Session data_session https://api.example.com ${headers} Create Dictionary Content-Typeapplication/json ${body} Create Dictionary username${username} password${password} ${response} POST On Session data_session /api/login headers${headers} json${body} Should Be Equal As Integers ${response.status_code} 200 ${response_json} Evaluate $response.json() Should Be Equal As Strings ${response_json[code]} ${expect_code} Should Be Equal As Strings ${response_json[msg]} ${expect_msg}运行的时候DataDriver会自动遍历Excel里的每一行数据把每一行当作一个独立用例执行。Excel里三行数据最终会生成三个测试用例报告里一目了然。提示Excel文件的第一个sheet默认被读取如果你把数据放在第二个sheet要用sheet_name参数指定。另外Excel文件不要用.xls老格式用.xlsx新格式兼容性更好。4.3 CSV格式与中文乱码处理CSV是比Excel更轻量的选择Git diff也方便适合存常量级的测试数据。但CSV有个经典问题中文乱码。原因很简单Robot Framework默认用UTF-8编码读取CSV但Excel另存的CSV通常带着BOM头\ufeff或者直接是GBK编码。解决方案有两个方案一在CSV文件开头加上BOM头——用记事本打开CSV另存为“UTF-8 with BOM”格式Robot Framework就能正常识别。方案二在Settings里声明编码*** Settings *** Library DataDriver ../resources/data/user_cases.csv encodingutf-8-sig我个人建议直接用方案二一劳永逸。utf-8-sig编码会先去掉BOM再按UTF-8解析Excel保存的乱码CSV基本都能救回来。4.4 从数据驱动到关键字驱动的架构升级做数据驱动一段时间后你会发现一个现象接口数量一多用例模板代码还是重复。每个接口都有一套“发起请求→解析响应→断言”的模板粘贴复制多了代码维护变成了灾难。这时候就要升级到关键字驱动了。核心思路是把“发起请求→解析响应→断言”这个过程抽象成通用关键字把“请求地址、请求方法、请求参数、断言规则”全部作为数据传入。我在实际项目里维护过一套这样的通用关键字*** Keywords *** 调用接口并断言 [Arguments] ${api_name} ${method} ${path} ${params} ${expected} Create Session kw_session ${BASE_URL} ${response} Run Keyword ${method} On Session kw_session ${path} json${params} Should Be Equal As Integers ${response.status_code} ${expected[status_code]} ${response_json} Evaluate $response.json() FOR ${key} IN {expected[body_assertions]} ${actual} Evaluate $response_json[${key}] Should Be Equal As Strings ${actual} ${expected[body_assertions][${key}]} END然后测试数据里只描述“我要测什么、预期是什么”调用订单接口 [Template] 调用接口并断言 # api_name method path params expected 创建订单 POST /api/order {goods_id:123} {status_code:200,body_assertions:{code:0,msg:成功}}这套架构跑稳之后新接一个接口的测试基本就是“增加一行数据的事”不用写任何新代码。团队推广自动化的时候操作门槛直接降到“会用Excel就会写接口用例”。5. 工程化落地报告、日志、CI集成5.1 报告与日志出了bug怎么看Robot Framework最强的地方之一就是它的测试报告。跑完一次测试log.html里记录了每个用例每一步的详细执行日志包括请求URL、请求头、请求体、响应状态码、响应体、每个断言的执行结果。接口联调时出了问题直接打开log.html就能看到请求到底发了什么、服务端返回了什么比对着抓包工具反复截屏效率高太多了。这里分享一个提高排障效率的写法在断言失败时把响应信息嵌入日志。比如Run Keyword And Continue On Failure Should Be Equal As Integers ${response.status_code} 200 Run Keyword And Continue On Failure Should Be Equal As Strings ${response_json[code]} 0用Run Keyword And Continue On Failure包裹断言关键字失败时不会立刻中断用例而是继续往下执行这样一次运行能把所有断言问题全暴露出来不用改一次跑一次。报告默认生成在用例文件所在目录我建议运行命令里指定输出目录robot -d results test_cases/user_module/user_login.robot把output.xml、log.html、report.html全部输出到results/目录既保持项目根目录干净也方便后续CI收集产物。5.2 Jenkins集成每天自动跑接口用例接口自动化的最大价值在持续回归。手工回归一轮接口要半天自动化跑一遍只要几分钟。我当时的做法是用Jenkins做定时任务第一步在Jenkins里新建一个自由风格的任务。第二步源码管理里配置代码仓库地址每次构建自动拉最新代码。第三步构建步骤选“Execute shell”填入pip install -r requirements.txt robot -d results test_cases/第四步构建后操作里选择“Publish Robot Framework test report”把results/目录的路径配置进去这样Jenkins的页面就能直接展示测试报告、统计通过率、失败用例等。第五步配置定时触发。接口回归不需要每次代码提交都跑全量一般每天凌晨跑一次就够了。Jenkins里填每天凌晨2点H 2 * * *如果公司有比较完善的CI流程也可以把接口自动化接到流水线里GitLab MR时触发冒烟子集。这个看团队情况灵活调整。5.3 测试数据准备与清理隔离环境的重要性接口自动化跑到后期最头疼的不是脚本问题而是测试数据问题。我踩过最经典的坑是跑回归时创建了一个订单第二次再跑同一个订单号重复创建接口直接报“订单号已存在”。用例本身没问题就是数据重复了。解决方案有三个层次第一每个测试用例尽量自己准备数据自己清理数据。比如用例最后调一个“删除订单”接口把测试过程产生的数据清掉。第二使用Suite Setup和Suite Teardown在套件级别做统一的数据准备和清理*** Settings *** Suite Setup 批量准备测试数据 Suite Teardown 批量清理测试数据第三如果公司有独立的测试环境可以在测试环境里做“环境重置”操作——每晚把数据库恢复到基线状态这样第二天跑用例时数据永远是干净的。这三个层次按需使用最简单的场景也至少保证“每个用例的数据是可重复执行的”。6. 学习路径建议接口自动化到底该按什么顺序学6.1 先基础后框架不要一上来就学Robot Framework写这篇文章之前我特意看了下短视频平台上关于“接口自动化学习顺序”的内容发现一个普遍问题很多人上来就推荐某个框架然后让你学一堆库学完还是不知道怎么落地一个完整项目。根据我带新人的经验接口自动化的学习顺序应该是这样的第一步先把HTTP协议搞明白。请求方法、请求头、请求体、状态码、RESTful风格这些基础概念都不清楚用任何框架都是空中楼阁。第二步先用Postman把接口基本功能测通学会Postman的断言、变量、环境切换。不要跳过这一步Postman是理解接口交互最快的工具。第三步学Python基础语法重点学字典、列表、JSON处理、字典取值这四块是接口自动化里最常用的Python知识。第四步学requests库用纯Python写接口请求脚本感受一下怎么用代码发请求、处理响应。第五步再回到Robot Framework用关键字驱动的方式把之前写的Python脚本重构成Robot Framework用例这时候你对这个框架的语法、关键字、数据驱动会理解得非常透彻。第六步学习如何搭建完整项目目录结构、公共关键字、数据驱动、测试报告、CI集成。按这个顺序走大约两到三周就能建立起完整的接口自动化能力。直接跳第一步上Robot Framework的大概率会在“怎么处理JSON返回”“怎么断言变量”这些基础问题上卡壳很久。6.2 学习Robot Framework时最值得投入的三个方向如果你已经决定用Robot Framework做接口自动化学习精力建议集中在三个方向第一个方向是RequestsLibrary的常用关键字。这个不用死记硬背Create Session、GET/POST/PUT/DELETE On Session、Get Request这些高频关键字用几次就熟了。偶尔遇到冷门用法直接看官方文档的关键字列表。第二个方向是Collections库和Evaluate的组合使用。这两个是处理JSON、断言字段的核心工具。Get From Dictionary、Get From List、Dictionary Should Contain Item、Evaluate这些用熟接口返回什么结构都不慌。第三个方向是数据驱动和关键字驱动的架构设计。这个决定了你写的自动化脚本能不能规模化、能不能让团队其他人参与编写。架构学好了一个200条用例的项目你也能维护得很轻松架构没学好50条用例就能把你折磨疯。6.3 常见问题速查表最后整理一份接口自动化实战里最高频的问题和解决方案都是我实打实踩过的坑供直接参考现象原因解决方案中文响应乱码响应编码不是UTF-8用Evaluate $response.encoding utf-8后再取text登录token提取不到返回JSON结构比自己预想的深先Log ${response.text}看真实结构不要瞎猜路径POST请求传JSON报错用data参数误传了字符串POST On Session传字典用json参数用例超时导致卡住接口慢或者环境网络问题给请求加时间限制用requests库的timeout参数Excel数据读不出来.xls格式或sheet名称不对改用.xlsx格式用sheet_name指定sheet多个用例互相影响共享了同一个测试数据用例间数据尽量隔离用Suite Setup统一造数循环接口取值错误Robot Framework的${}取值作用域问题循环内变量赋值后用Set Test Variable提升作用域接口有加密参数请求体需要动态签名用Evaluate调用Python函数计算签名再拼入请求体其中“登录token提取不到”这个坑我几乎在每次培训里都能遇到。很多新手不看实际返回凭感觉去取字段一取就是None。排这类问题最有效的方式就是先Log ${response.text}把响应体完整打出来看清真实结构再去写取值代码。另外一个容易被忽略的坑是Robot Framework的变量作用域。循环里直接赋值变量循环体外部是取不到的。需要跨作用域用必须加Set Test Variable。这类隐性问题不实测几次很难注意到。做接口自动化这几年我自己的体会是框架本身不难难的是对HTTP协议的理解、对接口业务逻辑的把握以及从“能跑”到“跑得稳、维护得起”的工程化能力。Robot Framework给了一个足够低的上手门槛和足够高的扩展天花板你既能用它在两天内出一个能跑的冒烟脚本也能靠它撑起上千条用例的接口回归体系。关键是别一上来就想搞个大而全的框架先把一个接口跑通再跑通五个、五十个、五百个问题会自然浮出来解决它们的过程才是真正长本事的过程。如果看完这篇文章你打算动手了我最后一条建议是不要光看不练照着第二节的例子先跑通一个GET请求然后再慢慢往里面加东西。接口自动化这行动手永远是第一位的。
返回列表