selenium+pytest+allure用例失败自动截图

pytest 有个很好的钩子函数 pytest_runtest_makereport 可以获取到用例执行的结果,所以我们在这个钩子函数里面判断用例失败后截图就可以了。

pytest_runtest_makereport 是 Pytest 中的一个钩子函数,它允许用户在测试用例执行完成后操纵测试报告。通过这个钩子函数,我们可以获取关于测试用例执行结果的信息,并对其进行定制化处理或记录。

@pytest.hookimpl作用

@pytest.hookimpl(tryfirst=True, hookwrapper=True)

  1. 该装饰器作用于pytest的钩子函数上,可以获取到测试用例不同执行阶段的结果(setup,call,teardown)

  2. 可以获取钩子方法的调用结果(返回一个result对象)和调用结果的测试报告(返回一个report对象)

在钩子函数装饰器的yield处,Pytest将执行下一个钩子函数实现,并以Result对象的形式,封装结果或异常信息的实例的形式将其结果返回到yield处。因此,yield处通常本身不会抛出异常(除非存在错误)

conftest.py 文件写用例执行的钩子函数

@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
    """
      每个测试用例执行后,制作测试报告
      :param item:测试用例对象
      :param call:测试用例的测试步骤
               执行完常规钩子函数返回的report报告有个属性叫report.when
                先执行when=’setup’ 返回setup 的执行结果
                然后执行when=’call’ 返回call 的执行结果
                最后执行when=’teardown’返回teardown 的执行结果
      :return:
    """
    # 执行所有其他钩子以获取报告对象
    # 获取常规钩子方法的调用结果,返回一个result对象 
    outcome = yield
    # 获取调用结果的测试报告,返回一个report对象, report对象的属性包括when(steup, call, teardown三个值)、nodeid(测试用例的名字)、outcome(用例的执行结果,passed,failed)
    rep = outcome.get_result() #  # 从钩子方法的调用结果中获取测试报告
    # rep.when表示测试步骤,仅仅获取用例call 执行结果是失败的情况, 不包含 setup/teardown
    if rep.when == "call" and rep.failed:
        mode = "a" if os.path.exists("../../failures") else "w"
        with open(root_path+"failures", mode) as f:
            if "tmpdir" in item.fixturenames:
                extra = " (%s)" % item.funcargs["tmpdir"]
            else:
                extra = ""
            f.write(rep.nodeid + extra + "\n")
        with allure.step('添加失败截图...'):
            allure.attach(driver.get_screenshot_as_png(), "失败截图", allure.attachment_type.PNG)

allure报告添加截图可以使用 allure.attach 方法

这段代码是一个 Pytest 的钩子函数 pytest_runtest_makereport,用于在测试用例执行后制作测试报告。让我来逐步解释它的功能:

  1. @pytest.hookimpl(tryfirst=True, hookwrapper=True):这行代码定义了一个 Pytest 钩子函数,并指定了它的执行顺序和包装方式。hookwrapper=True 表示这是一个包装器钩子函数,tryfirst=True 表示优先级较高。

  2. 在这个钩子函数中,使用了 yield 关键字,这意味着这是一个生成器函数。生成器函数可以在函数执行过程中暂停,并且允许在暂停的地方向调用者产出值。

  3. outcome = yield:这一行代码暂停函数的执行,等待其他钩子函数的调用结果。这里的 yield 会执行其他钩子,在执行完毕后,将结果赋值给 outcome 变量。

  4. rep = outcome.get_result():这一行代码获取了其他钩子函数的调用结果,即测试报告对象 rep

  5. 接下来的代码判断了测试报告的类型和结果,当测试步骤为 "call"(表示测试用例执行)并且结果为失败时,将相关信息写入文件中,并使用 Allure 来添加失败截图。

总体来说,这段代码的作用是在测试用例执行完成后,判断测试结果,如果测试失败,则记录相关信息并添加失败截图到测试报告中。同时,通过使用生成器函数、yield 和获取钩子调用结果的方式,实现了对测试报告的定制化处理。

需要注意的是,代码中的一些细节,比如文件操作的路径、Allure 截图的添加以及相关模块的导入等,可能需要根据具体的项目配置进行调整。

测试用例 test_login.py

import allure
import pytest

from page.login_page import LoginPage
from common.config import WebConfig


@allure.feature("登录")
class TestLogin:
    @allure.title("登录"+WebConfig.username)
    def test_login(self, browser):
        page = LoginPage(browser)
        with allure.step("打开首页"):
            page.open(WebConfig.url)
        with allure.step("点击打开登录页面"):
            page.login_a.click()
        with allure.step("输入用户名"):
            page.username_input = WebConfig.username
        with allure.step("输入密码"):
            page.password_input = WebConfig.password
        with allure.step("点击登录按钮"):
            page.login_span.click()
        with allure.step("断言主页顶部栏用户名"):
            assert page.username_span.text == WebConfig.username


if __name__ == '__main__':
    pytest.main(["-s", "test_login.py"])

这里username故意写错 username = “chenlq”
运行用例后,截图会存到./report 报告目录,allure报告展示如下:

image