1. 项目概述:为什么我们需要Selenium2Library的高级技巧?
如果你正在用Robot Framework做UI自动化测试,并且已经熟练掌握了Click Element、Input Text这些基础关键字,那么恭喜你,你已经成功迈出了第一步。但很快,你就会遇到一些更“磨人”的问题:测试脚本在本地跑得好好的,一到CI/CD流水线就间歇性失败;页面加载慢一点,元素定位就报错;处理动态弹窗和iframe手忙脚乱;测试报告里除了“PASS”和“FAIL”,看不出任何有价值的上下文信息。这些问题,正是基础API无法覆盖的“深水区”。
Selenium2Library是Robot Framework生态中用于Web自动化的核心库,它封装了Selenium WebDriver的能力。但仅仅会调用它的关键字,就像只学会了汽车的油门和刹车,远谈不上“老司机”。真正的效率与稳定性提升,来自于对浏览器行为、网络环境、框架机制和工程实践的深度理解与巧妙运用。本文分享的10个高级技巧,并非来自官方文档的简单罗列,而是我在多年实战中,从无数次的脚本调试、性能优化和稳定性攻坚中提炼出的“生存法则”。它们的目标很明确:让你的自动化测试脚本从“能跑”变得“健壮、高效、易维护”,真正成为研发流程中值得信赖的一环。
2. 技巧一:构建坚如磐石的“智能等待”策略
几乎所有不稳定的UI自动化脚本,第一个病根都出在“等待”上。Sleep 5s这种简单粗暴的方式是万恶之源,它让测试时间不可控且极度低效。Selenium2Library提供了Wait Until系列关键字,但如何用好它们,才是关键。
2.1 理解等待的三种境界
- 硬性等待(Sleep):死等固定时间。除非模拟人类思考停顿(且不推荐),否则应避免使用。
- 隐式等待(Implicit Wait):通过
Set Selenium Implicit Wait设置一个全局超时时间。WebDriver在查找任何元素时,如果没立即找到,会轮询DOM直到超时。它的最大问题是只对Find Element类操作有效,对元素状态(如是否可点击、是否可见)无效,且会拖慢所有元素查找。我的建议是,要么不用,要么设一个很小的值(如2秒)作为安全网。 - 显式等待(Explicit Wait):针对特定条件进行等待,条件满足则立即继续,超时则报错。这是稳定性保障的基石。Selenium2Library的
Wait Until Page Contains、Wait Until Element Is Visible等都属于此类。
2.2 设计分层等待策略
不要只依赖单一的关键字。我通常构建一个三层等待策略:
*** Settings *** Library Selenium2Library timeout=10s implicit_wait=2s # 第一层:库级别全局超时和隐式等待(安全网) *** Keywords *** 智能等待元素可操作 [Arguments] ${locator} # 第二层:核心显式等待 - 等待元素存在且可见 Wait Until Element Is Visible ${locator} timeout=15s error=元素“${locator}”在15秒内未变得可见 # 第三层:额外状态检查 - 等待元素可交互(非必须,针对复杂UI) ${is_enabled}= Run Keyword And Return Status Element Should Be Enabled ${locator} Run Keyword If not ${is_enabled} Fail 元素“${locator}”可见但处于禁用状态,无法操作实操心得:timeout参数不要一刀切。对于主要页面加载,可以设10-15秒;对于一个普通的按钮,5秒可能就够了。超时信息error一定要自定义,这样失败时能立刻知道是哪个元素出了问题,而不是一个笼统的“TimeoutException”。
2.3 自定义等待条件,应对极端场景
有些场景内置关键字不够用,比如等待某个元素的特定属性值变化,或者等待页面某个JavaScript变量被赋值。这时就需要用到Wait Until Keyword Succeeds这个“万能钥匙”。
等待订单状态变为“已完成” # 每隔2秒检查一次,最多等待30秒,直到条件满足 Wait Until Keyword Succeeds 30s 2s 订单状态应为已完成 订单状态应为已完成 ${status}= Get Text css=.order-status Should Be Equal As Strings ${status} 已完成注意:
Wait Until Keyword Succeeds内部的检查关键字如果失败,会抛出异常并被捕获,然后重试。因此,这个内部关键字必须能在失败时抛出异常(比如使用Should系列断言),而不是静默返回False。
3. 技巧二:高级定位器策略与动态元素处理
定位器(Locator)是自动化脚本的“眼睛”。id和name是最优选择,但现实项目中,面对层出不穷的动态ID和复杂组件,我们必须掌握更强大的定位技术。
3.1 优先使用CSS Selector而非XPath
虽然Selenium2Library两者都支持,但在绝大多数情况下,CSS Selector的性能和可读性都优于XPath。浏览器原生支持CSS查询,速度更快。
- XPath:
//div[@id='container']//button[contains(text(), '提交')] - CSS (更优):
css=div#container button:contains('提交')(注意::contains是jQuery扩展,标准CSS需用其他方法) 更标准的做法是结合其他属性:css=div#container button[type='submit']
对于简单的属性匹配,CSS非常简洁:
Input Text css=input[name='username'] myUser Click Element css=button.btn-primary3.2 处理动态ID和类名
现代前端框架(如React、Vue)常生成动态ID,如id="input-12345"。不要尝试定位完整的动态值。
- 使用属性部分匹配:
# 使用CSS的属性开头匹配 Click Element css=[id^='input-'] # 使用XPath的contains函数 Click Element xpath=//*[contains(@id, 'input-')] - 寻找稳定的父容器,再向下定位:如果元素本身动态,但其父级或兄弟元素是稳定的,可以先定位稳定元素,再使用相对定位。
# 假设有一个稳定的标题栏,其下的按钮是动态的 ${parent}= Get Webelement xpath=//h2[text()='用户列表'] # 使用XPath轴定位下一个兄弟节点里的按钮 Click Element xpath=${parent}/following-sibling::div//button
3.3 使用Get Webelement与链式调用
当定位步骤复杂或需要复用某个元素对象时,直接获取WebElement对象再进行操作会更灵活高效。
*** Keywords *** 获取用户表格第一行的编辑按钮 ${table}= Get Webelement css=.user-data-table # 在找到的table元素内部继续查找,避免全局搜索,更精准快速 ${first_row}= Get Webelement ${table} tag=tr ${edit_button}= Get Webelement ${first_row} css=button.edit-btn [Return] ${edit_button} 测试用例示例 ${btn}= 获取用户表格第一行的编辑按钮 Click Element ${btn} # 直接操作WebElement对象 # 还可以获取该元素的更多属性 ${text}= Get Text ${btn} Log 编辑按钮的文本是:${text}这种方法将复杂的定位逻辑封装在关键字内部,让测试用例更清晰,也提高了定位的复用性和精度。
4. 技巧三:利用JavaScript执行突破Selenium的限制
Selenium WebDriver的API虽然强大,但终究受限于浏览器安全策略和标准交互模型。有些操作,比如直接修改元素属性、触发非标准事件、执行复杂DOM查询或获取浏览器性能数据,需要通过执行JavaScript来实现。
4.1Execute JavaScript关键字的妙用
Execute JavaScript关键字让你能在当前页面的上下文中执行任意JS代码,并将结果返回给Robot Framework。
场景1:直接修改元素属性或值有时候,前端设置了输入框的readonly属性,或者用自定义组件屏蔽了直接输入。你可以用JS绕过。
# 将输入框设置为可编辑并输入值 Execute JavaScript document.querySelector('#readonly-input').removeAttribute('readonly'); Input Text id=readonly-input 新的内容 # 或者更直接地设置值(不触发input事件) Execute JavaScript arguments[0].value = '直接设置的值'; ARGUMENTS ${input_element}场景2:触发复杂的事件有些自定义组件需要触发特定事件才能响应。
# 模拟鼠标悬停 ${element}= Get Webelement css=.dropdown-toggle Execute JavaScript arguments[0].dispatchEvent(new MouseEvent('mouseover', {bubbles: true})); ARGUMENTS ${element}场景3:获取页面性能数据或复杂状态
# 获取页面加载时间(Navigation Timing API) ${load_time}= Execute JavaScript return performance.timing.loadEventEnd - performance.timing.navigationStart; Log 页面完全加载耗时:${load_time} 毫秒 # 检查jQuery Ajax是否正在进行 ${ajax_active}= Execute JavaScript return (typeof jQuery !== 'undefined') && jQuery.active > 0; Run Keyword If ${ajax_active} Log 页面尚有Ajax请求未完成4.2 封装常用JS操作为自定义关键字
为了提高可读性和复用性,将常用的JS操作封装起来。
*** Keywords *** 滚动到元素并居中 [Arguments] ${locator} ${element}= Get Webelement ${locator} Execute JavaScript ... arguments[0].scrollIntoView({behavior: 'smooth', block: 'center'}); ... ARGUMENTS ${element} 设置本地存储项 [Arguments] ${key} ${value} ${json_value}= Evaluate json.dumps(${value}) json Execute JavaScript localStorage.setItem('${key}', ${json_value});重要警告:虽然JS执行很强大,但切勿滥用。它破坏了测试对真实用户操作的模拟。优先使用标准的Selenium交互关键字(Click, Input等)。仅在标准方法无法实现、或需要获取内部状态进行断言时,才使用JS作为补充手段。同时,注意JS执行是同步的,对于大量操作可能阻塞页面。
5. 技巧四:精通浏览器驱动与多窗口/Frame导航
Web应用不再是简单的单页,弹窗、iframe、多标签页是常态。处理不好这些,脚本就会卡死或定位错误。
5.1 稳健的Frame和Iframe切换
进入和离开Frame必须成对出现,否则后续定位都会在错误的上下文中进行。
处理登录iframe # 1. 首先确保在主页面 Unselect Frame # 可选,确保回到默认顶层 # 2. 定位并切换到iframe Select Frame css=iframe[name='login-frame'] # 3. 在iframe内部操作 Input Text id=username testuser Input Text id=password testpass Click Button 登录 # 4. 操作完成后,必须切回主文档! Unselect Frame # 现在可以继续操作主页面的元素了 Page Should Contain 登录成功常见坑点:如果iframe是动态加载的,必须在Select Frame前使用Wait Until Element Is Visible等待iframe出现。切换回主文档后,如果后续操作需要等待主页面的元素,同样要加上等待,因为切换上下文后页面可能还在变化。
5.2 多窗口(标签页)的精准操控
点击一个链接可能打开新标签页,你需要能准确地在窗口间切换。
点击链接打开新窗口并验证 ${main_window}= Get Window Handle # 获取当前(主)窗口句柄 Click Link css=a[target='_blank'] # 点击打开新窗口的链接 # 等待新窗口出现 Wait Until Keyword Succeeds 5s 1s 新窗口应已打开 # 切换到新窗口 Switch Window NEW # 在新窗口操作 Title Should Be 新页面标题 # ... 执行一些测试 ... Close Window # 关闭新窗口 # 切回主窗口 Switch Window ${main_window} # 继续主窗口的操作 新窗口应已打开 ${handles}= Get Window Handles Should Be True len(${handles}) > 1实操心得:Get Window Handle(单数)返回当前活动窗口的句柄。Get Window Handles(复数)返回所有打开窗口的句柄列表。Switch Window可以使用NEW(最新窗口)、MAIN(最初窗口)或具体的窗口句柄。最佳实践是:在打开新窗口前,先保存主窗口句柄,像锚点一样,确保总能切回来。
5.3 浏览器日志与网络控制(高级)
对于调试或需要验证前端错误、网络请求的场景,可以配置浏览器驱动来获取日志或模拟网络条件。
*** Settings *** Library Selenium2Library *** Test Cases *** 示例:获取浏览器控制台日志 Open Browser https://example.com chrome ... desired_capabilities=${DESIRED_CAPS} # 需要通过desired_capabilities开启日志 *** Variables *** ${DESIRED_CAPS} Evaluate {'goog:loggingPrefs': {'browser': 'ALL', 'performance': 'ALL'}}之后,你可以使用Get Log关键字(注意:不同浏览器支持不同)来获取日志内容,分析JS错误或警告。这在对前端质量有要求的测试中非常有用。
6. 技巧五:数据驱动测试与动态测试用例生成
当需要用多组数据测试同一个业务流程时,手动复制粘贴测试用例是低效且难以维护的。Robot Framework内置了强大的数据驱动测试能力。
6.1 使用Template和Test Template标签
这是最直接的数据驱动方式。将一个关键字设置为测试用例的模板,该用例下的每一行数据都会作为一次独立的测试执行。
*** Settings *** Test Template 登录测试模板 *** Test Cases *** 用户名 密码 预期结果 无效登录测试用例 invalid_user wrong_pass 登录失败 empty_user ${EMPTY} 登录失败 valid_user ${EMPTY} 登录失败 *** Keywords *** 登录测试模板 [Arguments] ${username} ${password} ${expected_result} Go To Login Page Input Username ${username} Input Password ${password} Click Login Button Run Keyword If '${expected_result}' == '登录成功' ... Page Should Contain 欢迎回来 ... ELSE ... Page Should Contain 用户名或密码错误这种方式清晰地将测试数据与逻辑分离,报告会显示每个数据行的执行结果。
6.2 利用外部数据文件(CSV, Excel, 数据库)
对于大量、复杂的数据,最好将数据存储在外部文件中。
*** Settings *** Library DataDriver file=login_data.csv encoding=utf-8-sig Test Template 通用登录测试 *** Test Cases *** 使用CSV数据驱动登录测试 ${username} ${password} ${expected} *** Keywords *** 通用登录测试 [Arguments] ${username} ${password} ${expected} # ... 登录逻辑 ... Should Contain ${actual_result} ${expected}你需要安装DataDriver库 (pip install robotframework-datadriver)。CSV文件login_data.csv内容如下:
username,password,expected user1,pass1,登录成功 user2,wrong,登录失败 ,pass3,登录失败6.3 动态生成测试用例
有时测试用例本身需要根据运行时的环境或数据动态决定。可以使用Run Keyword If、For循环结合Set Test Variable或Set Suite Variable来实现一定程度的动态性,但更复杂的动态生成需要借助robot变量文件或自定义的测试库在初始化阶段生成用例。
一个简单的动态循环示例:
*** Test Cases *** 测试多个搜索关键词 @{keywords}= Create List Robot Framework Selenium Python Automation FOR ${keyword} IN @{keywords} Log 正在测试关键词: ${keyword} 执行搜索并验证 ${keyword} END注意,这仍然是一个测试用例。如果循环中某次失败,整个用例就失败了。对于需要完全独立报告和数据隔离的场景,外部数据驱动是更好的选择。
7. 技巧六:自定义关键字的艺术与封装策略
当你的测试套件越来越大时,维护一堆直接调用Selenium2Library关键字的测试用例会是一场噩梦。自定义关键字是提升可维护性、复用性和可读性的核心手段。
7.1 设计高内聚、低耦合的关键字
一个好的自定义关键字应该像一个小函数,只做一件事,并且做好。
- 反面教材:一个叫
完成用户注册的关键字,里面包含了打开浏览器、导航到注册页、填写10个字段、点击提交、检查邮件、登录验证……这太长了,难以复用和调试。 - 正面教材:
这样,*** Keywords *** 导航到注册页面 Go To ${REGISTER_URL} 等待注册表单加载完成 填写必填用户信息 [Arguments] ${username} ${email} ${password} Input Text id=username ${username} Input Text id=email ${email} Input Text id=password ${password} 提交注册表单 Click Button css=button[type='submit'] 等待页面跳转完成 验证注册成功提示 Wait Until Page Contains 注册成功 Page Should Contain Element css=.success-message # 高层级业务关键字 完成用户注册流程 [Arguments] ${user_data} 导航到注册页面 填写必填用户信息 @{user_data}[username] @{user_data}[email] @{user_data}[password] 提交注册表单 验证注册成功提示填写必填用户信息可以被其他测试(如编辑用户信息)复用。高层级关键字组合了低层级操作,读起来就像自然语言。
7.2 使用参数和返回值
充分利用[Arguments]和[Return]让关键字更灵活。
获取订单总金额并格式化 [Arguments] ${订单号} ${金额元素}= Get Webelement xpath=//tr[td[contains(text(),'${订单号}')]]/td[@class='amount'] ${原始文本}= Get Text ${金额元素} ${清理后文本}= Remove String ${原始文本} $ , # 移除美元符号和逗号 ${浮点数}= Convert To Number ${清理后文本} [Return] ${浮点数} # 在测试用例中使用 ${订单金额}= 获取订单总金额并格式化 ORD-2023-001 Should Be True ${订单金额} > 100.07.3 创建资源文件与变量文件
将通用的关键字和变量抽取到独立的资源文件(.resource)和变量文件(.py或.yaml)中,是大型项目架构的关键。
common_keywords.resource: 存放等待元素可操作、安全点击、截图并附加到日志等通用关键字。page_objects.resource: 存放按页面组织的关键字,如LoginPage.robot、DashboardPage.robot,实现Page Object模式。config.py: 用Python定义变量,可以执行逻辑。# config.py import os BASE_URL = os.getenv('TEST_BASE_URL', 'https://staging.example.com') BROWSER = os.getenv('TEST_BROWSER', 'chrome') IMPLICIT_WAIT = int(os.getenv('IMPLICIT_WAIT', '5'))- 在Robot文件中引用:
*** Settings *** Resource common_keywords.resource Resource pages/LoginPage.resource Variables config.py
这种架构使得底层UI定位符变化时,只需修改对应的资源文件,所有测试用例都自动受益。
8. 技巧七:异常处理与失败场景的优雅恢复
自动化测试不可能永远一帆风顺。网络抖动、环境差异、临时弹窗都会导致失败。一个健壮的测试脚本应该能处理预期内的异常,并提供清晰的失败信息,甚至尝试恢复。
8.1 使用Run Keyword And Ignore Error与Run Keyword And Return Status
这两个关键字是处理“可接受失败”或“条件检查”的利器。
Run Keyword And Return Status: 执行一个关键字,返回True(成功)或False(失败),不抛出异常。用于条件判断。${登录框可见}= Run Keyword And Return Status Page Should Contain Element id=login-modal Run Keyword If ${登录框可见} Click Element css=.modal-close # 如果有弹窗,关闭它Run Keyword And Ignore Error: 执行一个关键字,返回一个包含状态(PASS/FAIL)和消息(或返回值)的列表。当你不关心关键字是否失败,但需要知道结果时使用。${status} ${message}= Run Keyword And Ignore Error Click Element css=unstable-button Run Keyword If '${status}' == 'FAIL' Log 按钮点击失败,可能未加载,尝试备用方案 WARN ... ELSE Log 按钮点击成功
8.2 实现“安全点击”和“安全输入”关键字
将等待、重试和异常处理封装到基础操作中,能极大提升脚本稳定性。
*** Keywords *** 安全点击元素 [Arguments] ${locator} ${timeout}=10s [Documentation] 点击元素,如果失败,尝试滚动到视图再点击,并记录详细日志。 Wait Until Element Is Visible ${locator} timeout=${timeout} Scroll Element Into View ${locator} ${click_status} ${msg}= Run Keyword And Ignore Error Click Element ${locator} Run Keyword If '${click_status}' == 'FAIL' ... Run Keywords ... Log 标准点击失败,尝试通过JavaScript点击: ${msg} WARN ... AND Execute JavaScript arguments[0].click(); ARGUMENTS ${locator} ... ELSE ... Log 元素 ${locator} 点击成功。 安全输入文本 [Arguments] ${locator} ${text} ${clear_first}=${True} Wait Until Element Is Visible ${locator} Scroll Element Into View ${locator} Run Keyword If ${clear_first} Clear Element Text ${locator} # 有时Clear后直接Input会失败,先点击一下激活 Click Element ${locator} Input Text ${locator} ${text}8.3 设置全局的测试Teardown和Suite Setup
利用Test Teardown和Suite Teardown,确保无论测试成功还是失败,都能执行一些清理工作,比如关闭浏览器、清理测试数据、发送通知等。
*** Settings *** Suite Setup 全局测试准备 Suite Teardown 全局测试清理 Test Setup 打开测试浏览器 Test Teardown Run Keywords 捕获失败截图 AND 关闭测试浏览器 *** Keywords *** 捕获失败截图 Run Keyword If Test Failed Capture Page Screenshot filename=FAILURE-{TEST NAME}-{index}.pngRun Keyword If Test Failed是一个非常有用的内置关键字,它只在测试用例失败时才执行其中的操作。
9. 技巧八:测试报告与日志的增强与定制
默认的Robot Framework报告和日志已经很详细,但我们可以做得更好,让问题定位更快。
9.1 使用Log和Log To Console输出关键信息
在关键步骤添加有意义的日志,而不是依赖自动生成的步骤记录。
登录到管理员后台 Log 正在尝试登录管理员账户... console=True # 同时输出到控制台,便于实时查看 Input Text id=username ${ADMIN_USER} Input Text id=password ${ADMIN_PASS} ${点击前URL}= Get Location Click Button 登录 Wait Until Location Contains /admin/dashboard timeout=15s ${点击后URL}= Get Location Log 登录成功,从 ${点击前URL} 跳转至 ${点击后URL} level=INFOconsole=True在长时间运行的测试中非常有用,你可以从CI/CD工具的实时输出中看到进度。
9.2 为失败断言提供自定义错误信息
所有Should系列的断言关键字都支持自定义错误信息。
Page Should Contain 订单创建成功 ... error=页面未找到‘订单创建成功’提示,当前页面内容为:${CURPAGE_CONTENT}当断言失败时,这个自定义的错误信息会直接显示在报告和日志中,省去你再去查看页面源码的步骤。你可以创建一个关键字来自动获取当前页面的部分文本作为错误信息的一部分。
9.3 集成Allure等高级报告框架
对于大型项目,可以考虑集成Allure报告,它能生成更美观、交互性更强的测试报告,支持附件(截图、日志)、步骤描述、标签分类等。
- 安装依赖:
pip install allure-robotframework - 在测试中标记:
*** Settings *** Library allure_robotframework *** Test Cases *** 示例测试用例 [Tags] smoke login Allure Description 这是一个验证用户登录功能的冒烟测试用例。 Log 开始登录测试 level=INFO # ... 测试步骤 ... Run Keyword If Test Failed Allure Attach File ${SCREENSHOT_PATH} name=失败截图 - 运行测试时添加
--listener allure_robotframework参数生成Allure结果文件,然后用Allure命令行工具生成HTML报告。
10. 技巧九:与CI/CD流水线的深度集成
自动化测试的价值在持续集成/持续部署(CI/CD)中才能最大化体现。集成不仅仅是“能跑”,更要“跑得稳”、“报告清”、“失败快”。
10.1 无头模式与远程执行
在CI服务器上,通常没有图形界面,需要使用无头(Headless)模式。
*** Settings *** Library Selenium2Library *** Variables *** ${HEADLESS} ${True} # 通过环境变量控制 *** Keywords *** 打开测试浏览器 ${options}= Evaluate sys.modules['selenium.webdriver'].ChromeOptions() sys Run Keyword If ${HEADLESS} Call Method ${options} add_argument --headless=new Call Method ${options} add_argument --disable-gpu Call Method ${options} add_argument --no-sandbox # Docker等容器环境常用 Call Method ${options} add_argument --disable-dev-shm-usage # 解决共享内存问题 Create Webdriver Chrome chrome_options=${options} Set Selenium Implicit Wait 5s Maximize Browser Window使用Create Webdriver可以更精细地控制浏览器选项。--headless=new是Chrome较新版本的推荐参数。
10.2 使用Selenium Grid进行分布式测试
当测试套件很大时,可以利用Selenium Grid在多台机器、多个浏览器上并行运行测试,极大缩短反馈时间。
- 启动Grid Hub和Node。
- 在Robot Framework中,使用
Open Browser时指定远程地址和所需能力(Desired Capabilities)。
你可以通过变量控制Open Browser https://example.com browser=chrome ... remote_url=http://grid-hub:4444/wd/hub ... desired_capabilities=browserName:chrome, platform:LINUXremote_url,使得同一套脚本可以在本地(连接http://localhost:4444)和CI环境(连接真正的Grid Hub)无缝切换。
10.3 测试结果的处理与通知
CI流水线需要根据测试结果决定是否继续部署。
- 结果输出:使用
--outputdir指定输出目录,使用--log、--report、--xunit生成不同格式的报告。XUnit格式的报告容易被Jenkins等CI工具解析。robot --outputdir results --log mylog.html --report myreport.html --xunit xunit.xml my_tests/ - 失败处理:在CI脚本中,检查Robot的退出码(0表示所有测试通过,非0表示有失败)。可以配置在测试失败时自动重跑失败的用例(使用
--rerunfailed选项)。 - 通知:集成Slack、Teams或邮件通知,在测试失败时第一时间通知相关人员。可以编写一个后处理脚本,解析
output.xml,提取失败信息并发送。
11. 技巧十:性能优化与脚本维护性提升
当你有成百上千个测试用例时,执行速度和维护成本就成为关键问题。
11.1 优化测试套件结构
- 按功能模块划分套件:不要把所有测试用例放在一个
.robot文件里。按登录、订单、用户管理等模块划分,便于并行执行和定位问题。 - 使用标签(Tags)进行灵活筛选:为测试用例打上
smoke(冒烟)、regression(回归)、slow(慢速)等标签。
运行时可以只跑冒烟测试:*** Test Cases *** 快速登录测试 [Tags] smoke login # ... 步骤 ... 完整的用户旅程测试 [Tags] regression e2e slow # ... 步骤 ...robot --include smoke tests/,或者排除慢速测试:robot --exclude slow tests/。
11.2 减少不必要的浏览器启动
浏览器启动和关闭是耗时操作。对于一组紧密相关的测试用例,可以考虑使用Suite Setup打开一次浏览器,在Suite Teardown中关闭,而不是每个用例都开关(Test Setup/Test Teardown)。但这需要确保测试用例之间是独立的,不会相互影响状态(如cookie、localStorage)。通常,更推荐每个测试用例独立运行,以避免状态污染,虽然牺牲了一些时间,但获得了更高的稳定性和可并行性。可以通过Selenium Grid并行执行来弥补时间损失。
11.3 定期重构与代码审查
自动化测试代码也是代码,需要像对待生产代码一样进行维护。
- 定期重构:删除重复代码,更新过时的定位器,优化等待策略。
- 进行代码审查:在团队中,对测试脚本的修改也应进行代码审查,确保遵循共同的编码规范,关键字设计合理。
- 建立定位器仓库:对于大型项目,可以考虑将页面元素的定位器统一管理在一个变量文件中,任何定位器的更改只需在一处进行。
# locators.py LOGIN = { '用户名输入框': 'id=username', '密码输入框': 'id=password', '登录按钮': 'css=button.login-btn', '错误提示': 'css=.alert-error' }*** Settings *** Variables locators.py *** Test Cases *** 测试登录 Input Text ${LOGIN}[用户名输入框] user1 Input Text ${LOGIN}[密码输入框] pass1 Click Element ${LOGIN}[登录按钮]
11.4 监控与告警
将自动化测试的通过率、执行时长、稳定性(如Flaky Tests——时过时不过的测试)纳入监控。定期分析失败原因,如果是产品Bug就提缺陷,如果是测试脚本不稳定就优化脚本,如果是环境问题就改善环境。让自动化测试成为一个持续反馈和优化的闭环系统,而不仅仅是一个被定时执行的任务。