跳至内容
Web 自动化测试框架

Web 自动化测试框架

在 Api 自动化测试框架的基础上,再加上浏览器自动化工具的支持,就能完成 Web 自动化测试框架。

集成 playwright

浏览器自动化工具,这里我选择 playwright。本文只是简短介绍,读者务必查阅 playwright官方文档 了解如何使用。

关于环境要求,官方这样描述:

  • Python 3.8 或更高版本。

  • Windows 11+、Windows Server 2019+ 或适用于 Linux 的 Windows 子系统 (WSL)。

  • macOS 14 Ventura 或更高版本。

  • Debian 12、Ubuntu 22.04、Ubuntu 24.04,基于 x86-64 和 arm64 架构。

pip pytest-playwright

执行上述命令,会同时安装 pytest、playwright 和 pytest-playwright。pytest 是主测试框架,用于编写和运行测试用例,playwright 是一个用于自动化浏览器测试的库,提供核心Api,pytest-playwright 是 pytest 的一个插件,用于在 pytest 中使用 playwright 进行浏览器自动化测试。

浏览器

要使 playwright 正常工作,必须给它指定对应的浏览器。当前市场有三种浏览器引擎,分别是 Google 的 Chromium(Blink)、苹果的 WebKit(Blink的近亲)、Mozilla 的 Firefox(Gecko)。

WebKit 是 Safari、邮件、App Store 以及 macOS、iOS 和 Linux 上许多其他应用使用的网页浏览器引擎。

基于 Chromium 内核的浏览器比较多,市场占比最多,最出名的是 Google Chrome 和 Edge 浏览器。

基于 Firefox 内核的浏览器,多用于 Linux 系统上,市场占比较少。

根据项目需要合理选择浏览器用于测试。

安装浏览器

可以手动下载安装浏览器,也可以使用 playwright install 命令安装,推荐命令安装。如果你选择 playwright install 命令安装,首先需要知道它的作用。

运行 playwright install --help,打印信息如下:

playwright install --help

用法:playwright 安装 [选项] [浏览器...]

确保安装了此版本 Playwright 所需的浏览器。

选项:
--with-deps  安装浏览器的系统依赖项
--dry-run    不执行安装,仅打印信息
--force      强制重新安装稳定浏览器通道
--only-shell 安装 Chromium 时仅安装无头 shell
--no-shell   安装 Chromium 时不安装无头 shell
-h, --help   显示命令的帮助信息



示例:
- $ install
安装默认浏览器,包括 Chromium、Firefox 和 WebKit 三种引擎开源浏览器

- $ install chrome firefox
安装自定义浏览器,支持 chromium、chromium-headless-shell、chromium-tip-of-tree-headless-shell、chrome、chrome-beta、msedge、msedge-beta、msedge-dev、bidi-chromium、firefox、webkit。

先安装浏览器的系统依赖项:

playwright install-deps

然后按需安装浏览器:

# 安装默认浏览器,包括 Chromium、Firefox 和 WebKit 三种引擎开源浏览器
playwright install
# 安装特定浏览器,比如 Chromium
playwright install Chromium

在浏览器上运行测试

可是使用如下参数选择在不同的浏览器上测试:

# 使用开源 chromium 浏览器(默认),--headed 会显示画面,调试时使用。实际测试时无需使用
python run.py --headed

# 使用开源 webkit 浏览器
python run.py --browser=webkit --headed

# 使用开源 Firefox 浏览器
python run.py --browser=firefox --headed

# 使用 Goole Chrome 浏览器(基于 Chromium 引擎)
python run.py --browser=chromium --browser-channel=chrome --headed

# 使用 Edge 浏览器(基于 Chromium 引擎)
python run.py --browser=chromium --browser-channel=msedge --headed

测试生成器

生成器是 playwright 的一个神功能,它能提供 codegen 窗口,在浏览器窗口的各种操作都会作为响应代码被记录下来,可以复制这些代码用于测试用例。

还是先看一下 codegenhelp 信息:

playwright codegen --help

用法:playwright codegen [选项] [网址]

打开页面并为用户操作生成代码

选项:
-o, --output <文件名>             将生成的脚本保存到文件中
--target <语言>                  生成的目标语言,可选值为 javascript、playwright-test、python、python-async、python-pytest、csharp、csharp-mstest、csharp-nunit、java、java-junit(默认值:"python")
--test-id-attribute <属性名>     使用指定的属性生成数据测试 ID 选择器
-b, --browser <浏览器类型>        使用的浏览器类型,可选值为 cr、chromium、ff、firefox、wk、webkit(默认值:"chromium")
--block-service-workers         阻止服务工作线程
--channel <渠道>                 Chromium 分发渠道,例如 "chrome"、"chrome-beta"、"msedge-dev" 等
--color-scheme <方案>            模拟首选颜色方案,可选值为 "light" 或 "dark"
--device <设备名称>               模拟设备,例如 "iPhone 11"
--geolocation <坐标>             指定地理位置坐标,例如 "37.819722,-122.478611"
--ignore-https-errors           忽略 https 错误
--load-storage <文件名>          从文件加载上下文存储状态,该文件之前使用 --save-storage 保存--lang <语言>                    指定语言/区域设置,例如“en-GB”
--proxy-server <代理>            指定代理服务器,例如“http://myproxy:3128”或“socks5://myproxy:8080”
--proxy-bypass <绕过>            以逗号分隔的要绕过代理的域名,例如“.com,chromium.org,.domain.com”
--save-har <文件名>              在结束时保存包含所有网络活动的 HAR 文件
--save-har-glob <通配符模式>      根据此通配符模式与 URL 匹配来筛选 HAR 中的条目
--save-storage <文件名>          在结束时保存上下文存储状态,以便稍后使用 --load-storage
--timezone <时区>                要模拟的时区,例如“Europe/Rome”
--timeout <超时时间>             Playwright 操作的超时时间(以毫秒为单位),默认无超时
--user-agent <用户代理字符串>     指定用户代理字符串
--user-data-dir <目录>           使用指定的用户数据目录,而不是新上下文
--viewport-size <大小>           以像素为单位指定浏览器视口大小,例如“1280, 720”
-h, --help                     显示命令的帮助信息

示例:

$ codegen
$ codegen --target=python
$ codegen -b webkit https://example.com

参数 –browser 可以指定浏览器类型,如果不指定,默认使用 Chromium。

参数 –channel 用于指定 Chromium 浏览器的分发渠道,例如 “chrome”、“chrome-beta”、“msedge-dev” 等。

试试打开测试生成器,导航至百度网站:

playwright codegen https://baidu.com/

测试生成器用法

录制功能:打开后可以生成在浏览器上的所有操作代码

选择定位器:选择该工具后,点击浏览器里任何元素会在 Inspector 的 “Locator” 窗口显示推荐的 Playwright 定位器。

断言元素可见性:录制中选择该工具,在浏览器里点某个元素,会生成断言代码。检验目标元素是否在页面中渲染并且对用户可见(非隐藏、非遮挡、非透明)。

断言文本内容:录制中选择该工具,在浏览器里点某个元素,会生成断言代码。检验目标元素的可见文本与预期字符串是否一致。

断言表单值:录制中选择该工具,在浏览器里点具有 value 属性的元素,会生成断言代码。检验该元素的 value 属性值是否与预期一致。

断言 ARIA 语义快照:录制中选择该工具,在浏览器里当前页面,会生成断言代码。对比元素在可访问性树(Accessibility Tree)里的语义和文本结构是否与预期一致(非图片对比)。

自动截图并附加到测试报告

测试用例未通过时,附加截图无疑能提供视图信息,我们可以把截图附件发送到测试报告里。

cases/conftest.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import allure
import pytest

SCREENSHOT_NAME = "Failure_Screenshot"
SCREENSHOT_TYPE = allure.attachment_type.PNG


def pytest_runtest_makereport(item: pytest.Item, call: pytest.CallInfo) -> None:
    """
    测试失败时自动截图并附加到 Allure 报告。

    在测试用例的 setup、call 或 teardown 任一阶段失败时,
    自动截取 Playwright page 对象的画面并将其作为附件添加到 Allure 测试报告中。

    Args:
        item (pytest.Item): 当前执行的测试项对象。
        call (pytest.CallInfo): 包含测试调用结果和异常信息的对象。
    """

    is_test_failed = call.excinfo is not None
    is_critical_phase = call.when in ("setup", "call", "teardown")
    
    if is_critical_phase and is_test_failed:
        
        page = getattr(item, "funcargs", {}).get("page")

        if page is not None:
            try:
                screenshot_bytes = page.screenshot()
                
                allure.attach(
                    screenshot_bytes,
                    name=f"{SCREENSHOT_NAME}_{item.name}",
                    attachment_type=SCREENSHOT_TYPE
                )
            except Exception as e:
                error_message = f"在测试 '{item.name}' 失败后尝试截图时发生错误: {repr(e)}"
                allure.attach(
                    body=error_message,
                    name="Screenshot_Error_Message",
                    attachment_type=allure.attachment_type.TEXT
                )
        else:
            no_page_msg = (
                f"测试 '{item.name}' 失败,但在其 fixtures 中未找到 'page' 对象。"
                f"无法生成自动截图。"
            )
            allure.attach(
                body=no_page_msg,
                name="No_Page_Fixture_Available",
                attachment_type=allure.attachment_type.TEXT
            )
最后更新于