4、自动化测试框架整合:Selenium/Appium/Requests与CI的集成、测试报告生成(Allure/ExtentReports)、失败重跑机制

这一章,我们来聊聊自动化测试框架的整合。说实话,很多团队自动化搞不起来,不是因为不会写脚本,而是卡在了「整合」这一步。脚本写了一大堆,跑起来全靠人工点按钮,那还不如不写。

我个人习惯把自动化测试框架的整合分成三个层次:工具层(Selenium/Appium/Requests)、报告层(Allure/ExtentReports)、机制层(失败重跑)。这三层打通了,你的自动化才算真正「活」了。

4.1 工具层整合:Selenium/Appium/Requests与CI的集成

先说说工具层。Selenium搞Web、Appium搞移动端、Requests搞接口,这三兄弟各司其职。但问题是,怎么把它们塞进CI流水线里?

我在项目中遇到过最典型的场景:开发改了后端接口,前端页面也跟着变了,移动端App也得同步测试。如果每个工具各自为战,CI流水线会乱成一锅粥。

我的做法是:统一入口,分层执行。

具体来说,在CI配置文件(比如Jenkinsfile或GitLab CI的.gitlab-ci.yml)里,定义三个Stage:

stages:
  - api_test
  - web_test
  - mobile_test

api_test:
  stage: api_test
  script:
    - pytest tests/api/ --alluredir=./allure-results/api
  artifacts:
    paths:
      - ./allure-results/api

web_test:
  stage: web_test
  script:
    - pytest tests/web/ --alluredir=./allure-results/web
  artifacts:
    paths:
      - ./allure-results/web

mobile_test:
  stage: mobile_test
  script:
    - pytest tests/mobile/ --alluredir=./allure-results/mobile
  artifacts:
    paths:
      - ./allure-results/mobile

你看,每个Stage独立运行,互不干扰。接口测试跑得最快,先执行;Web和移动端可以并行跑。这样整个流水线的时间能压缩不少。

小技巧: 我建议把测试数据准备也放到CI里。比如接口测试需要先登录获取token,那就写一个fixture,在CI的before_script里统一执行。别让每个脚本自己去登录,否则维护起来想哭。

4.2 报告层整合:Allure与ExtentReports

报告这东西,说白了就是给别人看的。你跑了一堆测试,老板问「测完了吗?结果怎么样?」你总不能甩给他一个控制台日志吧?

我个人偏爱Allure,因为它生成的报告颜值高、信息全。但ExtentReports也有它的优势——轻量、不需要额外服务。怎么选?看场景。

4.2.1 Allure报告集成

Allure的集成其实不复杂,核心就三步:

  1. 安装Allure命令行工具
  2. 在pytest中配置allure-pytest插件
  3. 在CI中生成并发布报告

代码示例:

# conftest.py
import allure
import pytest

@pytest.fixture(scope="session")
def driver():
    # 这里初始化WebDriver
    driver = webdriver.Chrome()
    yield driver
    driver.quit()

# 测试用例
@allure.feature("登录模块")
@allure.story("用户登录")
@allure.severity(allure.severity_level.CRITICAL)
def test_login(driver):
    with allure.step("打开登录页面"):
        driver.get("https://example.com/login")
    with allure.step("输入用户名密码"):
        driver.find_element(By.ID, "username").send_keys("admin")
        driver.find_element(By.ID, "password").send_keys("123456")
    with allure.step("点击登录"):
        driver.find_element(By.ID, "login-btn").click()
    with allure.step("验证登录成功"):
        assert "欢迎" in driver.page_source

在CI里生成报告的命令:

allure generate ./allure-results --clean -o ./allure-report
allure open ./allure-report
注意: 我曾经踩过一个坑——Allure报告里的截图路径是绝对路径,换到CI服务器上就找不到了。后来我改成用相对路径,并且在CI的artifacts里把截图目录一起打包,才解决这个问题。

4.2.2 ExtentReports集成

ExtentReports更适合轻量级场景。比如你只是跑个接口测试,不想折腾Allure那套服务,用ExtentReports就挺方便。

# 使用extentreports的Python版本
from extentreports import ExtentReports, ExtentTest

report = ExtentReports()
test = report.create_test("登录接口测试")
test.log(Status.PASS, "登录成功")
report.flush()

嗯,这里要注意:ExtentReports的Python版本更新不太勤快,如果你用Java写测试,那ExtentReports的体验会好很多。

4.3 失败重跑机制

自动化测试最让人头疼的是什么?不是用例写不出来,而是用例跑挂了,但不知道是真挂还是假挂

你想想看,一个Web页面偶尔加载慢了点,元素没找到,测试就挂了。这种「假失败」最消耗团队信任。所以,失败重跑机制必须安排上。

4.3.1 pytest-rerunfailures插件

最简单的方式是用pytest-rerunfailures插件。用法很直接:

# 命令行方式
pytest --reruns 3 --reruns-delay 2

# 或者用装饰器
@pytest.mark.flaky(reruns=3, reruns_delay=2)
def test_something():
    # 你的测试逻辑
    pass

这个插件默认会在用例失败后立即重跑。但我建议加上--reruns-delay参数,给系统一点缓冲时间。我在项目中遇到过,页面刚刷新完就去找元素,结果元素还没渲染出来。加个2秒延迟,问题就解决了。

4.3.2 自定义重跑逻辑

有时候,简单的重跑不够用。比如接口返回500,重跑3次可能还是500。这时候需要更智能的重跑策略。

我写过这样一个自定义重跑器:

import time
from functools import wraps

def retry_on_failure(max_retries=3, delay=1, exceptions=(Exception,)):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            for attempt in range(max_retries):
                try:
                    return func(*args, **kwargs)
                except exceptions as e:
                    if attempt == max_retries - 1:
                        raise
                    print(f"第{attempt+1}次失败,{delay}秒后重试...")
                    time.sleep(delay)
            return None
        return wrapper
    return decorator

# 使用
@retry_on_failure(max_retries=5, delay=2, exceptions=(ConnectionError, TimeoutError))
def test_api():
    response = requests.get("https://api.example.com/status")
    assert response.status_code == 200
核心原则: 重跑机制是用来处理「环境不稳定」的,不是用来掩盖「代码有bug」的。如果同一个用例重跑3次都失败,那大概率是真挂了,赶紧去修代码吧。

4.4 整合后的CI流水线示例

最后,给你看一个完整的CI流水线配置。这是我之前在项目中用过的,效果还不错:

# .gitlab-ci.yml
stages:
  - test
  - report
  - notify

test:
  stage: test
  script:
    - pip install -r requirements.txt
    - pytest tests/ --reruns 2 --reruns-delay 3 --alluredir=./allure-results
  artifacts:
    when: always
    paths:
      - ./allure-results
      - ./screenshots

report:
  stage: report
  script:
    - allure generate ./allure-results --clean -o ./allure-report
  artifacts:
    paths:
      - ./allure-report

notify:
  stage: notify
  script:
    - python send_report.py
  only:
    - main

这个流水线做了三件事:跑测试(带重跑)、生成报告、发送通知。注意看when: always这个参数,意思是即使测试失败了,也要保留artifacts。这样你才能看到失败的截图和日志。

好了,这一章的内容就这些。说白了,自动化测试框架整合没那么玄乎,就是把工具、报告、重跑这三件事串起来。你按照这个思路去搭,基本不会出大问题。