You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python+Selenium如何自动为截图添加测试名及参数ID/序号

问题:自动生成包含测试名+参数ID/序号的截图文件名

我正在学习基于Page Object模式的Python+Selenium测试编写,现有如下测试代码:

import pytest

@pytest.mark.parametrize("first_name", [double_first_name, empty_form, long_first_name],
                     ids=["double_first_name", "empty_form", "long_first_name"])
def test_reg_form_name(browser, first_name):
    passport_reg_page = RegForm(browser)
    passport_reg_page.go_to_site()
    passport_reg_page.reg_page()
    passport_reg_page.reg_first_name(first_name)
    passport_reg_page.reg_button()
    passport_reg_page = RegFormExpectations(browser)
    passport_reg_page.reg_expect_name()
    assert passport_reg_page.reg_expect_name()  # 修正原代码中的变量名错误
    browser.save_screenshot('screenshots/test_reg_1.png')

我希望截图名称能自动包含测试名+参数ID,或者至少包含测试名+参数运行序号,比如生成类似test_reg_form_name_double_first_name.png或test_reg_form_name_001.png这样的文件名。

曾尝试以下方法:

def test_name(self, request):
    testname = request.node.name
    return testname

但收到提示“Method 'test_name' may be 'static'”;另外,使用test_reg_page.__name__可获取函数名,但手动写入函数名意义不大。


解决方案

方法1:直接在测试函数中使用pytest的request fixture

pytest的request fixture可以直接获取当前测试的元数据,包括测试名称、参数ID、参数索引等,无需额外封装。

修改测试函数,添加request参数,然后构造文件名:

import pytest

@pytest.mark.parametrize("first_name", [double_first_name, empty_form, long_first_name],
                     ids=["double_first_name", "empty_form", "long_first_name"])
def test_reg_form_name(browser, first_name, request):
    passport_reg_page = RegForm(browser)
    passport_reg_page.go_to_site()
    passport_reg_page.reg_page()
    passport_reg_page.reg_first_name(first_name)
    passport_reg_page.reg_button()
    passport_reg_page = RegFormExpectations(browser)
    passport_reg_page.reg_expect_name()
    assert passport_reg_page.reg_expect_name()
    
    # 方案A:测试名+参数ID(处理掉括号特殊字符)
    test_full_name = request.node.name.replace("[", "_").replace("]", "")
    screenshot_path = f"screenshots/{test_full_name}.png"
    
    # 方案B:测试名+参数序号(格式化为3位数字)
    # test_name = request.node.function.__name__
    # param_index = f"{request.node.callspec.index + 1:03d}"  # 序号从1开始,补零到3位
    # screenshot_path = f"screenshots/{test_name}_{param_index}.png"
    
    browser.save_screenshot(screenshot_path)

说明:

  • request.node.name返回完整测试标识(如test_reg_form_name[double_first_name]),替换括号后得到test_reg_form_name_double_first_name
  • request.node.function.__name__可单独获取测试函数名test_reg_form_name
  • request.node.callspec.index返回参数索引(从0开始),加1后格式化为3位数字,得到001、002这类序号

方法2:封装成可复用的工具函数

如果多个测试用例都需要生成这种命名的截图,可以把逻辑封装成工具函数,避免重复代码:

# 工具函数文件(比如utils.py)
def get_screenshot_filename(request, use_id=True):
    """
    根据request生成截图文件名
    :param request: pytest的request fixture
    :param use_id: 是否使用参数ID,False则使用参数序号
    :return: 格式化后的文件名
    """
    test_name = request.node.function.__name__
    if use_id:
        # 获取参数ID,替换特殊字符
        param_id = request.node.callspec.id.replace("[", "_").replace("]", "")
        return f"{test_name}_{param_id}.png"
    else:
        # 获取参数序号,格式化为3位数字
        param_index = f"{request.node.callspec.index + 1:03d}"
        return f"{test_name}_{param_index}.png"

然后在测试函数中调用:

from utils import get_screenshot_filename

@pytest.mark.parametrize("first_name", [double_first_name, empty_form, long_first_name],
                     ids=["double_first_name", "empty_form", "long_first_name"])
def test_reg_form_name(browser, first_name, request):
    # ... 测试逻辑 ...
    
    # 使用参数ID命名
    screenshot_name = get_screenshot_filename(request)
    # 或者使用序号命名
    # screenshot_name = get_screenshot_filename(request, use_id=False)
    
    browser.save_screenshot(f"screenshots/{screenshot_name}")

解决你之前的方法问题

你之前写的test_name函数提示“may be static”,是因为函数不需要self参数(只有类中的方法才需要self)。改成下面这样就可以正常使用:

def get_test_name(request):
    testname = request.node.name
    return testname

然后在测试函数中调用get_test_name(request)即可获取测试名+参数ID的字符串。


内容的提问来源于stack exchange,提问作者VladQA

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 00:46:03