- 示例工程
- 教程
- 后端
【免费下载链接】aws-doc-sdk-examples
Welcome to the AWS Code Examples Repository. This repo contains code examples used in the AWS documentation, AWS SDK Developer Guides, and more. For more information, see the Readme.md file below.
导读
本文基于 python/example_code/devicefarm/browser_testing 目录下的官方示例,讲解如何用 PyTest 与 Selenium 在 AWS Device Farm 的浏览器测试(browser testing)特性上运行 Web 自动化测试,并把它接入 CI 流水线。读完本文,你将掌握:通过 Device Farm API 获取远程浏览器会话、用资源标签 API 为每次会话自动打标、在测试中断言前抓取屏幕截图,以及如何把整个测试套件跑在 AWS 托管的真实浏览器中。
示例概览:Device Farm 浏览器测试的三大能力
AWS Device Farm 是一项移动应用与 Web 测试服务,官方仓库对其的定位是:"Device Farm is an app testing service that enables you to test your iOS, Android and Fire OS apps on real, physical phones and tablets that are hosted by AWS."。其中浏览器测试(browser testing)特性让开发者可以在 AWS 托管的真实浏览器中运行基于 WebDriver 的测试。
仓库中的 browser_testing/README.md 明确说明了本示例要演示的三件事:
- 使用 Device Farm API 启动浏览器会话:通过
create_test_grid_url获取一个仅供 Selenium 客户端使用的远端驱动地址(driver hub URL); - 使用 Resource Tagging API 为浏览器会话打标签:通过
get_test_grid_session找到会话 ARN,再用tag_resources为会话标记测试套件名称与 Git 提交号; - 从浏览器会话中抓取截图:在每个测试断言之前保存页面截图,便于定位失败原因。
它的典型定位是"作为 CI 系统的一部分,用 Selenium 测试 Web 应用"。示例有一个硬性约束:它必须在 Git 仓库内运行,因为输出目录基于最近一次 Git 提交的短哈希生成;如果不在仓库内运行,哈希会被替换为norepo(见下文源码分析)。
示例的完整实现位于 python/example_code/devicefarm/browser_testing/test_suite.py,依赖定义见同目录下的 Pipfile 与 Pipfile.lock。
运行前置条件(Prerequisites)
原文档列出了三类前置条件,缺一不可:
- 一个 Device Farm 浏览器测试项目。项目的创建与管理在 Device Farm 控制台完成,创建后可拿到项目的 ARN,形如
aws:arn:devicefarm:us-west-2:...。 - 具备最小权限的 AWS 编程凭证。按最小权限原则,仅需以下三个动作:
devicefarm:createTestGridUrl—— 创建测试网格(TestGrid)会话 URL;devicefarm:getTestGridSession—— 按项目 ARN 与会话 ID 查询会话详情(用于取会话 ARN);resourcetaggingapi:tagResources—— 为会话 ARN 添加资源标签。
- Pipenv:示例用 Pipenv 隔离依赖。所需依赖如下:
| 依赖包 | 作用 | 备注 |
|---|---|---|
| boto3 | AWS SDK for Python,调用 Device Farm 与 Resource Tagging API | 锁文件中版本为1.17.105 |
| selenium | Web 自动化客户端,驱动远程浏览器 | 锁文件中版本为3.141.0 |
| pytest | 测试框架,组织测试套件与参数化用例 | 锁文件中版本为6.2.4 |
| pytest-xdist | 可选,若需要并行跑多个测试 | 锁文件中版本为2.3.0 |
从 Pipfile 可以看到依赖被定义在[packages]段且版本均为通配符*,实际锁定版本记录在 Pipfile.lock 中。
运行命令:两条命令完成启动
原文档给出的运行方式非常简洁,只有两步:
安装依赖到 Pipenv 生成的虚拟环境中:
pipenv install运行测试套件,并把 Device Farm 浏览器测试项目的 ARN 通过环境变量
PROJECT_ARN传入:PROJECT_ARN="aws:arn:devicefarm:us-west-2:..." pipenv run pytest -s
注意-s参数:它关闭 pytest 的输出捕获,让 Selenium/浏览器相关的实时输出(包括测试中的打印与警告)直接显示在终端,方便 CI 日志排查。
原文档特别标注了一句话:"Note: Not all tests are designed to pass."(并非所有测试都被设计为通过。)这一点在源码中有所体现——例如test_redirect_titles的用例故意覆盖了"预期跳转/不跳转"及含特殊字符的页面标题,其中部分用例断言失败正是为了演示失败时截图能力(详见下文测试用例分析)。
关于区域与费用,原文档同时强调了两点注意事项:
- 本代码仅在
us-west-2(俄勒冈)区域有效,因为 Device Farm 是唯一部署在该区域的 AWS 服务; - 运行这段代码可能产生 AWS 账户费用,因为每次测试都会在 AWS 托管的真实浏览器中消耗会话时长。
源码深度剖析:test_suite.py 的完整执行链路
示例的全部逻辑集中在 test_suite.py(被官方 snippet 标记Scenario_BrowserTesting包裹)。整个执行流程可以概括为:
setup_method(每个测试前) ├─ boto3.client("devicefarm") ├─ create_test_grid_url(projectArn, expiresInSeconds=300) → 驱动 URL ├─ 按 Git 哈希+日期创建 results 目录 ├─ DesiredCapabilities.FIREFOX(platform=windows, 最新版) ├─ webdriver.Remote(url, cap) → 建立 Selenium 远程会话 └─ get_test_grid_session → session ARN └─ resourcegroupstaggingapi.tag_resources(打标签) test_xxx(参数化用例,断言前 save_screenshot) teardown_method(每个测试后) └─ driver.quit() 结束会话,停止计费下面逐段拆解关键实现,并给出对应的源码行号。
1. 获取 Git 短哈希:决定输出目录名
get_git_hash()(test_suite.py)通过git rev-parse --short HEAD拿到当前提交的短哈希,作为结果目录的唯一标识。若命令失败(即不在 Git 仓库内运行),则返回字符串"norepo"。这也印证了原文档"必须在 Git 仓库内运行"的约束。
2. setup_method:启动会话并自动打标签
每个测试方法运行前都会执行setup_method(test_suite.py),其内部完成了四件事:
(1)校验并创建会话 URL
devicefarm_client = boto3.client("devicefarm") project_arn = os.environ.get("PROJECT_ARN", None) if project_arn is None: raise ValueError("Must set PROJECT_ARN") testgrid_url_response = devicefarm_client.create_test_grid_url( projectArn=project_arn, expiresInSeconds=300 )项目 ARN 必须通过环境变量PROJECT_ARN提供,未设置直接抛异常。expiresInSeconds=300表示该驱动 URL 在 300 秒(5 分钟)内有效,需保证在会话建立前完成连接。
(2)创建按提交与日期命名的结果目录
self.screenshot_path = os.path.join( ".", "results", get_git_hash() + "-" + (datetime.date.today().isoformat()) ) if not os.path.exists(self.screenshot_path): os.makedirs(self.screenshot_path, exist_ok=True)截图会保存到./results/<git短哈希>-<日期>/目录下,例如./results/abc1234-2026-09-26/。这样同一提交、同一日期的多次运行共享一个目录,便于 CI 中按提交归档测试产物。
(3)配置 Selenium 远端驱动
desired_cap = DesiredCapabilities.FIREFOX desired_cap["platform"] = "windows" desired_cap["BrowserVersion"] = "latest" self.driver = webdriver.Remote(testgrid_url_response["url"], desired_cap)这里直接使用 Selenium 的DesiredCapabilities.FIREFOX模板,并指定平台为windows、浏览器版本为latest。webdriver.Remote的端点正是上一步create_test_grid_url返回的url字段——Device Farm 在这里充当了 Selenium Grid 的角色。
(4)查询会话 ARN 并自动打标签
testgrid_session_arn_response = devicefarm_client.get_test_grid_session( projectArn=project_arn, sessionId=self.driver.session_id ) self.session_arn = testgrid_session_arn_response["testGridSession"]["arn"] tag_client = boto3.client("resourcegroupstaggingapi") tag_client.tag_resources( ResourceARNList=[self.session_arn], Tags={"TestSuite": f"testsuite {method.__name__}", "GitId": get_git_hash()}, )这段是示例的核心亮点之一:Selenium 驱动会话建立后,用driver.session_id配合项目 ARN 调用get_test_grid_session反查出会话 ARN;随后改用resourcegroupstaggingapi客户端为该 ARN 打上两个标签:
TestSuite:值为testsuite <当前测试方法名>(例如testsuite test_first_paragraph_text);GitId:值为当前 Git 短哈希。
这样每次测试会话都能在 AWS 侧被追踪到"来自哪个测试方法、对应哪个代码提交",为 CI 审计和成本归因提供了依据。
3. teardown_method:优雅结束会话
def teardown_method(self, method): self.driver.quit()每个测试结束后立即调用driver.quit()关闭远程浏览器。源码注释写得很直白:"End the Selenium session so we're off the clock."(结束 Selenium 会话,停止计费。)因为 Device Farm 按会话时长计费,及时退出是控制成本的关键。
两个参数化测试用例:如何在断言前抓截图
示例套件TestHelloSuite包含两个基于pytest.mark.parametrize的测试,全部以英文 Wikipedia 为被测站点。
用例一:test_first_paragraph_text(首段文本比对)
定义于 test_suite.py,共 6 组参数(Seattle、Selenium、Amazon Locker、Kootenai Falls、Dorayaki、Robot Face)。执行逻辑:
- 打开 Wikipedia 主页,定位
#searchInput搜索框; - 输入查询词并回车;
- 用
WebDriverWait(self.driver, 5).until(expected_conditions.staleness_of(search_input))等待搜索框元素失效——元素变为 stale 说明页面已跳转完成,比固定sleep更健壮; - 用 XPath
//div[@class='mw-parser-output']//p[not(@class)]定位文章首段(排除带 class 的段落,通常是编辑提示或消歧义框); - 在断言之前调用
self.save_screenshot(f"leadingpara_{query}.png")保存截图; assert our_text.startswith(lead)校验首段是否以期望文本开头。
由于截图在最终断言之前拍摄,即使断言失败,也能拿到失败时刻的完整页面状态用于调试。
用例二:test_redirect_titles(跳转标题比对)
定义于 test_suite.py,共 8 组参数,覆盖"预期跳转"(如DevOps→DevOps)、"常见同义词跳转"(如Jackdaws Love My Big Sphinx Of Quartz→Pangram)、"特殊字符无法用键盘输入"(如N//ng language→Nǁng language)、以及"包含 $&% 等被过滤字符"(如Who the Frick Is Jackson Pollock?)等场景。
流程与第一个用例类似,但断言对象是页面#firstHeading的标题文本,截图文件名为redirect_<query>.png。由于部分参数组合(例如特殊字符输入)在真实浏览器中并不总是产生预期结果,这类用例正是"并非所有测试都被设计为通过"的直接体现——它们的失败演示了截图归档与断言失败的可观测性。
产物组织与 CI 集成建议
结合原文档与源码,可以从三个角度总结这套示例的工程价值:
- 结果可归档:所有截图按
results/<git短哈希>-<日期>/落盘,天然适配 CI 中的 artifact 上传逻辑;短哈希保证同一分支不同提交的运行互不覆盖。 - 会话可审计:
TestSuite与GitId标签让每个 Device Farm 会话都能追溯到测试方法与代码提交,配合成本报表即可分析"哪个提交/哪个测试最耗时"。 - 依赖可复现:
pipenv install依据 Pipfile.lock 生成完全一致的环境;锁文件显示selenium锁定在3.141.0、pytest锁定在6.2.4、boto3锁定在1.17.105,团队可按此版本基线复现。
与仓库中其他 Device Farm 示例的关系
本示例隶属于 python/example_code/devicefarm/README.md 所汇总的两个场景之一,另一个是 device_testing/run_tests.py(上传编译好的 Android/iOS 应用与测试包、启动设备测试并汇总结果)。两者互为补充:
- browser_testing面向 Web 应用的 Selenium 自动化测试;
- device_testing面向移动 App 的包上传与真机测试。
从代码组织看,browser testing 示例采用"Pipenv + PyTest + 每个测试前后自动启停远程会话"的结构,而 device testing 示例则是一次性上传、启动、轮询结果的长任务模式,二者代表了 Device Farm 的两条典型接入路径。Python 总目录 python/README.md 提供了通用的凭证配置(默认~/.aws/credentials或AWS_ACCESS_KEY_ID/AWS_SECRET_KEY环境变量)与虚拟环境使用说明,可作为运行本示例前的环境准备参考。
常见问题与排查要点
ValueError: Must set PROJECT_ARN:未在运行命令前导出PROJECT_ARN环境变量,检查项目 ARN 是否复制完整(形如aws:arn:devicefarm:us-west-2:123456789012:testgrid-project:...)。- 提示不在 Git 仓库内:结果目录名会退化为
norepo-<日期>,因为get_git_hash()的subprocess调用失败并被捕获;若需要按提交归档,请在 Git 仓库内运行。 - 截图目录始终生成:
setup_method中os.makedirs(..., exist_ok=True)保证目录可复用、不抛异常。 - 费用控制:每个测试的
setup_method都会新开一个远程浏览器会话,teardown_method负责关闭。并行跑测试时(安装pytest-xdist)会话数量会成倍增加,务必评估成本。
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
- 示例工程
- 教程
- 后端
【免费下载链接】aws-doc-sdk-examples
Welcome to the AWS Code Examples Repository. This repo contains code examples used in the AWS documentation, AWS SDK Developer Guides, and more. For more information, see the Readme.md file below.
相关推荐
aws-doc-sdk-examples 中的 AWS Device Farm Python(Boto3)代码示例:浏览器测试与设备包测试实战
aws doc sdk examples 中的 AWS Device Farm Python(Boto3)代码示例:浏览器测试与设备包测试实战 本指南以 pyt
示例工程教程后端Karma 测试运行器实战指南:在多个真实浏览器中执行 JavaScript 测试
Karma 测试运行器实战指南:在多个真实浏览器中执行 JavaScript 测试 本篇技术指南以 Karma 官方 README 为主体,结合仓库源码与官方文
测试开发工具CoffeeScript 浏览器端测试指南:在 Node 与浏览器中运行语言测试套件
CoffeeScript 浏览器端测试指南:在 Node 与浏览器中运行语言测试套件 CoffeeScript 仓库自带一整套覆盖语法、编译输出与运行时行为的测
编程语言编译器
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考