Skip to content

第 22 章 · 生产实践:E2E 策略与报告

本章目标:把前 21 章的技术点收拢成一套可持续运营的 E2E 工程体系:分层策略、环境与数据管理、报告与告警、维护清单。

22.1 E2E 的定位:少而精,守关键路径

先校准认知:E2E 测试的单位成本是所有测试层里最高的(慢、易碎、难排查),它的价值在于验证"用户的关键旅程真的能走通",而不是追求覆盖率。健康的分层大致是:

层级数量级运行时机职责
单元测试数千每次 push逻辑正确性(见本站 pytest 教程)
接口/组件测试数百每次 PR服务契约、页面片段
E2E 关键路径20–50 条每次 PR(冒烟)+ 每日全量登录、下单、支付等核心旅程

据此把 E2E 再分三级,用 pytest marker 管理:

python
# pytest.ini 中注册标记
[pytest]
markers =
    smoke: 冒烟集,PR 必跑(约 5 分钟内)
    critical: 关键路径,合并前必跑
    full: 全量回归,每日定时
python
import pytest

@pytest.mark.smoke
def test_login(page):
    ...

@pytest.mark.critical
def test_place_order_end_to_end(page, login_as):
    ...
bash
pytest -m smoke            # PR 流水线
pytest -m "critical or smoke"   # 合并流水线
pytest -m full             # 夜间全量

22.2 环境与测试数据工厂

生产级 E2E 最常见的翻车点是数据。三条原则:

  1. 专用环境:永远不要对生产环境跑写操作;测试环境要能快速重置;
  2. 自造数据:每个测试自己创建所需数据,结束清理(或用一次性数据库快照);
  3. API 造数优先于 UI 造数:UI 造数慢且脆弱。

推荐"API 准备 + UI 验证"的分工模式:

python
import requests
import pytest

API = "https://api.staging.example.com"

@pytest.fixture
def product(api_token):
    """通过 API 创建一件商品,测试结束后删除——UI 只负责验证展示"""
    resp = requests.post(
        f"{API}/products",
        json={"name": "测试商品-勿动", "price": 9.9},
        headers={"Authorization": f"Bearer {api_token}"},
        timeout=10,
    )
    product = resp.json()
    yield product
    requests.delete(f"{API}/products/{product['id']}",
                    headers={"Authorization": f"Bearer {api_token}"}, timeout=10)

def test_product_visible_in_storefront(page, product):
    page.goto(f"https://staging.example.com/products/{product['id']}")
    expect(page.get_by_role("heading", name=product["name"])).to_be_visible()

配合第 9 章的 storage_state 复用登录态、第 13 章的参数化扩展数据维度,就能搭出稳定的数据底座。

22.3 报告:让结果可读、可追溯

pytest-playwright 本身不带 HTML 报告器,生产环境通常叠加一层报告插件:

bash
pip install pytest-html          # 轻量方案
pytest --html=report.html --self-contained-html

需要失败截图自动嵌入时,结合 --screenshot only-on-failure 与 conftest 钩子把图片挂进报告。对更完整的"历史趋势 + 附件 + 步骤"需求,可选 Allure

python
# pip install allure-pytest
import allure

@allure.feature("购物车")
@allure.story("添加商品")
def test_add_to_cart(page, product):
    with allure.step("打开商品详情页"):
        page.goto(f"https://staging.example.com/products/{product['id']}")
    with allure.step("加入购物车并验证角标"):
        page.get_by_role("button", name="加入购物车").click()
        expect(page.get_by_test_id("cart-badge")).to_have_text("1")

无论选哪个,CI 里必须保留的失败工件是三件套:trace.zip、截图、视频(第 11 章的 --tracing retain-on-failure 等 CLI 参数),它们是远程排错的唯一依据。

22.4 失败分类与告警

不要让所有失败都发出同一种噪音。按处理路径分类:

  • A 类 · 产品 Bug:真实缺陷 → 建单修复,这是测试的价值所在;
  • B 类 · 环境问题:服务宕了、证书过期 → 告警给运维,测试标重试;
  • C 类 · 测试自身 Flaky:按第 19 章流程治理;
  • D 类 · 预期变更:产品有意改动导致断言过期 → 更新测试并在 PR 说明。

告警设计上:smoke 集 PR 内失败直接阻塞合并;夜间全量的失败次日晨会通报,附报告链接与失败分类标签。目标是每一条红色都有归属人

22.5 维护清单与上线检查单

每月维护清单:

  • [ ] 重试率是否超过阈值(>1% 需专项治理)?
  • [ ] 是否有用例运行时间超过 60 秒?考虑拆分或下沉到接口层
  • [ ] Playwright / 浏览器内核版本是否落后超过一个大版本?
  • [ ] storage_state、fixture 中的账号权限是否仍有效?

功能上线前的 E2E 检查单:

  • [ ] 新关键路径已有对应 critical 用例;
  • [ ] 新增页面元素使用了稳定的 data-testid(前端联调约定);
  • [ ] 涉及 WS/轮询的实时功能有消息层断言(第 21 章);
  • [ ] 无障碍结构断言已更新(第 20 章);
  • [ ] 测试数据可通过 API 一键构造与清理。

22.6 本章小结

  • E2E 少而精:smoke/critical/full 三级标记,分别绑定 PR、合并、夜间流水线;
  • 数据三原则:专用环境、自造自清、API 造数 UI 验证;
  • 报告选型:pytest-html 轻量起步,Allure 要步骤与趋势;trace/截图/视频是必备失败工件;
  • 失败四分类(Bug/环境/Flaky/预期变更),每条红色必须有归属人;
  • 用月度维护清单和上线检查单让体系持续健康。

🧪 随堂测验

点击你认为正确的选项。答错时会展示正确答案与原因解析。

1. 关于 E2E 测试在生产实践中的定位,符合本章观点的是?

2. "API 造数 + UI 验证"分工的好处不包括?

3. 一次夜间全量失败,排查发现是测试环境的 TLS 证书过期。这属于哪类失败?

4. CI 中 E2E 失败时,最应该保留的工件组合是?

🛠️ 动手实践

  1. 为你现有的 E2E 套件打上 smoke / critical / full 三级标记,统计每级的用例数与耗时,写出你的分级依据。
  2. 把一个目前靠页面上点点点准备数据的用例改造成 API fixture 造数,对比改造前后耗时与稳定性。
  3. 搭一条最小的 GitHub Actions 流水线:PR 触发 -m smoke,失败时上传 trace/截图工件并留评论。

🎉 恭喜完成全部 22 章!返回课程导学复盘学习路线,或继续本站其他教程。