自动化测试中的失败截图和存log

news2024/11/25 0:38:21

如果我们在执行自动化测试的时候,希望能在失败的时候保存现场,方便事后分析。 对于UI自动化,我们希望截图在测试报告中。 对于api自动化,我们希望截取出错的log在测试报告中。 我开始自己蛮干,写了两个出错截图的方法。

def save_screenshot():
    '''
    页面截屏保存截图
    :return:
    '''
    file_name = IMG_PATH + "\\{}.png".format(time.strftime("%Y%m%d%H%M%S", time.localtime()))
    d.screenshot(file_name)
    with open(file_name, mode='rb') as f:
        file = f.read()
    allure.attach(file, allure.attachment_type.PNG)

出错截图,我写了一个装饰器


def fail_screenshot(func):
    '''
    失败页面截屏保存截图
    :return:
    '''

    def wrapper(*args, **kwargs):
        try:
            func(*args, **kwargs)
        except:
            file_name = FAIL_IMG_PATH + "\\{}_{}.png".format(func.__name__,
                                                             time.strftime("%Y%m%d%H%M%S", time.localtime()))
            d.screenshot(file_name)

            # with open(file_name, mode='rb') as f:
            #     file = f.read()
            # allure.attach(file, allure.attachment_type.PNG)

    return wrapper

似乎能达到我的期望,就是太烦了,每次需要调用或者将装饰器写在函数上。 然后我发现allue里面有一个钩子函数。

from _pytest import runner

# 对应源码
def pytest_runtest_makereport(item, call):
    """ return a :py:class:`_pytest.runner.TestReport` object
    for the given :py:class:`pytest.Item` and
    :py:class:`_pytest.runner.CallInfo`.
    """

这里item是测试用例,call是测试步骤,具体执行过程如下:

先执行when='setup' 返回setup 的执行结果

然后执行when='call' 返回call 的执行结果

最后执行when='teardown'返回teardown 的执行结果

例如:

# conftest.py 
import pytest


@pytest.hookimpl(hookwrapper=True, tryfirst=True)
def pytest_runtest_makereport(item, call):
    print('------------------------------------')

    # 获取钩子方法的调用结果
    out = yield
    print('用例执行结果', out)

    # 3. 从钩子方法的调用结果中获取测试报告
    report = out.get_result()

    print('测试报告:%s' % report)
    print('步骤:%s' % report.when)
    print('nodeid:%s' % report.nodeid)
    print('description:%s' % str(item.function.__doc__))
    print(('运行结果: %s' % report.outcome))

运行用例的过程会经历三个阶段:setup-call-teardown,每个阶段都会返回的 Result 对象和 TestReport 对象,以及对象属性。

如果setup执行失败了,setup的执行结果的failed,后面的call用例和teardown都不会执行了。

如果setup正常执行,但是测试用例call失败了。那么此时运行的结果就是failed。

如果setup正常执行,测试用例call正常执行,teardown失败了,这种情况,最终统计的结果:1 passed, 1 error in 0.16 seconds

只获取call的时候,我们在写用例的时候,如果保证setup和teardown不报错情况,只关注测试用例本身的运行结果,前面的 pytest_runtest_makereport 钩子方法执行了三次。

可以加个判断:if report.when == "call"

import pytest
from _pytest import runner
'''
# 对应源码
def pytest_runtest_makereport(item, call):
    """ return a :py:class:`_pytest.runner.TestReport` object
    for the given :py:class:`pytest.Item` and
    :py:class:`_pytest.runner.CallInfo`.
    """
'''

@pytest.hookimpl(hookwrapper=True, tryfirst=True)
def pytest_runtest_makereport(item, call):
    print('------------------------------------')

    # 获取钩子方法的调用结果
    out = yield
    # print('用例执行结果', out)

    # 3. 从钩子方法的调用结果中获取测试报告
    report = out.get_result()
    if report.when == "call":
        print('测试报告:%s' % report)
        print('步骤:%s' % report.when)
        print('nodeid:%s' % report.nodeid)
        print('description:%s' % str(item.function.__doc__))
        print(('运行结果: %s' % report.outcome))

@pytest.fixture(scope="session", autouse=True)
def fix_a():
    print("setup 前置操作")
    yield
    print("teardown 后置操作")

allure报告集成错误截图 需要使用conftest.py文件,conftest.py需要存在在测试目录中,文件名不能变更,可以根据模块创建层级嵌套。

具体参照pytest的官方文档

@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
    '''
    hook pytest失败
    :param item:
    :param call:
    :return:
    '''
    # execute all other hooks to obtain the report object
    outcome = yield
    rep = outcome.get_result()
    # we only look at actual failing test calls, not setup/teardown
    if rep.when == "call" and rep.failed:
        mode = "a" if os.path.exists("failures") else "w"
        with open("failures", mode) as f:
            # let's also access a fixture for the fun of it
            if "tmpdir" in item.fixturenames:
                extra = " (%s)" % item.funcargs["tmpdir"]
            else:
                extra = ""
            f.write(rep.nodeid + extra + "\n")
        # pic_info = adb_screen_shot()
        with allure.step('添加失败截图...'):
            allure.attach(driver.get_screenshot_as_png(), "失败截图", allure.attachment_type.PNG)

好了,我们可以用在我们自己的项目里面来了。 我们可以在conftest.py里面定义:

import pytest
from selenium import webdriver
import os
import allure



_driver = None


@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
    '''
    获取每个用例状态的钩子函数
    :param item:
    :param call:
    :return:
    '''
    # 获取钩子方法的调用结果
    outcome = yield
    rep = outcome.get_result()
    # 仅仅获取用例call 执行结果是失败的情况, 不包含 setup/teardown
    if rep.when == "call" and rep.failed:
        mode = "a" if os.path.exists("failures") else "w"
        with open("failures", mode) as f:
            # let's also access a fixture for the fun of it
            if "tmpdir" in item.fixturenames:
                extra = " (%s)" % item.funcargs["tmpdir"]
            else:
                extra = ""
            f.write(rep.nodeid + extra + "\n")
        # 添加allure报告截图
        if hasattr(_driver, "get_screenshot_as_png"):
            with allure.step('添加失败截图...'):
                allure.attach(_driver.get_screenshot_as_png(), "失败截图", allure.attachment_type.PNG)


@pytest.fixture(scope='session')
def browser():
    global _driver
    if _driver is None:
        _driver =webdriver.Chrome()
    yield _driver
    print("1111111111")
    _driver.quit()

然后写一个测试用例,如在某度上搜一个关键词。


@allure.feature('self study')
class TestLesson():
    @allure.story('user course page')
    @allure.description('be course')
    def test_be_ge_course(self,browser):
        url = 'http://www.baidu.com'
        browser.get(url)
        time.sleep(2)
        browser.find_element_by_id('kw').send_keys("python")

        with allure.step('查找元素...'):
            browser.find_element_by_id('su').click()
            time.sleep(2)

        assert browser.title == 'python'

这是一个失败的用例,所以执行错误会截图。

这样你的报告就看起来高大上了。 截图还可以直接用allure.attach allure.attach(挺有用的) 作用:allure报告还支持显示许多不同类型的附件,可以补充测试结果;自己想输出啥就输出啥,挺好的

语法:allure.attach(body, name, attachment_type, extension) 

参数列表
body:要显示的内容(附件)
name:附件名字
attachment_type:附件类型,是 allure.attachment_type 里面的其中一种
extension:附件的扩展名(比较少用)

allure.attach.file(source, name, attachment_type, extension) source:文件路径,相当于传一个文件

其他参数和上面的一致:

TEXT = ("text/plain", "txt")
   CSV = ("text/csv", "csv")
   TSV = ("text/tab-separated-values", "tsv")
   URI_LIST = ("text/uri-list", "uri")

   HTML = ("text/html", "html")
   XML = ("application/xml", "xml")
   JSON = ("application/json", "json")
   YAML = ("application/yaml", "yaml")
   PCAP = ("application/vnd.tcpdump.pcap", "pcap")

   PNG = ("image/png", "png")
   JPG = ("image/jpg", "jpg")
   SVG = ("image/svg-xml", "svg")
   GIF = ("image/gif", "gif")
   BMP = ("image/bmp", "bmp")
   TIFF = ("image/tiff", "tiff")

   MP4 = ("video/mp4", "mp4")
   OGG = ("video/ogg", "ogg")
   WEBM = ("video/webm", "webm")

   PDF = ("application/pdf", "pdf")

根据需要,在报告里将更多的信息展现出来。 这周末啥也没干,主要就搞明白了这个。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/588984.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

linux init系统和系统管理器-Systemd学习

一、Systemd 概述 1.1、init 程序介绍及其发展历程 Linux init程序是系统启动时第一个启动的进程,它负责初始化系统资源,加载操作系统核心模块,启动系统服务和用户进程。init程序是系统启动的重要组成部分,它为后续的系统操作提…

2023年上半年信息系统项目管理师上午真题及答案解析

1.“新型基础设施”主要包括信息技术设施、融合基础设施和创新基础设施三个方面。其中信息基础设施包括( )。 ①通信基础设施 ②智能交通基础设施 ③新技术基础设施 ④科教基础设施 ⑤算力基础设施 A.①③⑤ B.①④⑤ C.②③④ D.②…

【JavaSE】Java基础语法(三十六):File IO流

文章目录 1. File1.1 File类概述和构造方法1.2 绝对路径和相对路径1.3 File 类的常用方法1.4 递归删除文件夹及其下面的文件 2. IO2.1 分类2.2 字节输出流2.3 字节输入流2.4 文件的拷贝2.5 文件拷贝效率优化2.6 释放资源2.7 缓冲流2.8 编码表 3. commons-io 工具包3.1 API 1. F…

如何在竞争激烈的市场环境下打造技术铁粉:CSDN的案例分析

如何在竞争激烈的市场环境下打造技术铁粉:CSDN的案例分析 随着互联网的快速发展,技术平台不仅成为了人们获取信息、学习知识和交流经验的重要渠道,也成为了各大企业和个人展示自我、争夺市场份额的关键竞技场。在这个过程中,CSDN…

ts reference 报错 ReferenceError: AA is not defined解决方案

我先说重点&#xff01;你看懂了就不用往下看了 ///<reference path"2.ts" /> 像上面这种代码是要编译后才有效果的&#xff0c;所以有些小伙伴发现教程demo也跑不了&#xff0c;跟命名空间啥的没关系&#xff01; 正文 你如果也报我我下面这种错误&#xff…

【智慧交通项目实战】《 OCR车牌检测与识别》(一)

&#x1f468;‍&#x1f4bb;作者简介&#xff1a; CSDN、阿里云人工智能领域博客专家&#xff0c;新星计划计算机视觉导师&#xff0c;百度飞桨PPDE&#xff0c;专注大数据与AI知识分享。✨公众号&#xff1a;GoAI的学习小屋 &#xff0c;免费分享书籍、简历、导图等&#xf…

西南财经大学李玉周:数智化技术广泛使用推动管理会计加快落地

近日&#xff0c;由用友主办的「智能会计 价值财务」2023企业数智化财务创新峰会收官站圆满举办。来自知名院校的专家学者、央国企等大型企业财务领路人相约成都&#xff0c;一同见证“智能会计”新时代的到来&#xff0c;并肩探讨“价值财务”新主张。 为更好传递智能会计对企…

UnityVR--插件1--新版InputSystem

目录 新版的InputSystem 安装新版InputSystem插件 配置新的InputSystem 在项目中配置新版输入方式实现移动和开火 添加并绑定移动事件 添加并绑定开火事件 总结&#xff08;啰嗦几句&#xff09; 新版的InputSystem 在最初的Unity系统中&#xff0c;只有键盘、鼠标、操作…

html实现好看的浪漫爱情回忆录(附源码)

文章目录 1.设计来源1.1 主界面1.2 主题描述1.3 照片墙详细界面1.4 相关跳转界面 2.效果和源码2.1 效果演示2.2 源代码 源码下载 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418/article/details/130946811 html实现好看的浪漫爱情回忆录…

Unity发布WebGL报错il2cpp.exe did not run properly

解决&#xff1a;路径中不能有任何中文&#xff0c;包括用户名都不能是中文 win10修改用户名为英文&#xff1a; 1、开启administrator账户。 1&#xff09;、右键我的电脑&#xff0c;选择管理。 2&#xff09;、本地用户和组—用户—Administrator 3&#xff09;、右键—属性…

C++11新特性:decltype类型推导

上一节所讲的 auto&#xff0c;用于通过一个表达式在编译时确定待定义的变量类型&#xff0c;auto 所修饰的变量必须被初始化&#xff0c;编译器需要通过初始化来确定 auto 所代表的类型&#xff0c;即必须要定义变量。若仅希望得到类型&#xff0c;而不需要(或不能)定义变量的…

yum安装最新版的PHP、MySQL

本地环境&#xff1a;AlmaLinux9.2 在阿里的镜像源站点有一个叫remi的源&#xff0c;这个源专门提供了php的各种版本&#xff0c;目前这个源只针对Redhat、Centos和Fedora系统 Remi镜像简介 Remi镜像主页 配置Remi镜像源 这里以Enterprise Linux 9 为例 配置向导 根据配置向…

关于机器人状态估计(15)-VIO与VSLAM精度答疑、融合前端、主流深度相机说明与近期工程汇总

VIOBOT种子用户有了一定的数量&#xff0c;日常大家也会进行交流&#xff0c;整理总结一下近期的交流与答疑。 VIO-SLAM(作为三维SLAM&#xff0c;相对于Lidar-SLAM和LIO-SLAM)在工程上落地的长期障碍&#xff0c;不仅在算法精度本身&#xff0c;还有相对严重的鲁棒性问题&…

【Linux】iptables防火墙

文章目录 一、Linux防火墙基础1.Linux防火墙概术2.netfilter/iptables3.四表五链4.规则链之间的匹配顺序 二、iptables 安装1.常用的控制类型2.常用的管理选项 三、示例演示1.添加新的规则2.查看规则列表3.删除规则4.清空规则 四、规则的匹配1.通用匹配2.隐含匹配3.显式匹配 一…

浅谈安科瑞无线测温技术在大功率整流器上的应用

安科瑞 徐浩竣 江苏安科瑞电器制造有限公司 zx acrelxhj 摘要&#xff1a;随着整流器运行电流的增加 &#xff0c;运行温度成为影响整 流器安全运行的主要因素 。针对目前大功率整流器运行温度通过出口水温表和纽扣继电器来监测 &#xff0c;运行人员不能及时、准确地掌握整…

【测试开发】第四节.测试开发(测试分类)

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;Java测试开发 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01;&#xff01; 文章目录 前…

程序员有哪些绝对不能踩的坑?

本文概要 程序员编写高质量、可维护、安全且高效的代码&#xff0c;通常需要大量研究和经验。但也需要避免许多技术陷阱。一起来聊聊程序员有哪些绝对不能踩的坑吧&#xff01; &#x1f31f;&#x1f31f;&#x1f31f;个人简介&#x1f31f;&#x1f31f;&#x1f31f; ☀️…

Spring Boot拦截器与过滤器的区别

Spring Boot拦截器与过滤器的区别 在使用Spring Boot开发Web应用程序时&#xff0c;您可能需要在处理请求之前或之后执行某些操作。这些操作可以包括身份验证、日志记录、性能监测等。在这种情况下&#xff0c;您可以使用两种不同的机制&#xff1a;拦截器和过滤器。本文将介绍…

Spring Boot如何实现缓存的自动刷新

Spring Boot如何实现缓存的自动刷新 在Web应用程序中&#xff0c;缓存是提高性能的重要手段之一。在Spring Boot应用程序中&#xff0c;我们可以使用Spring Cache来实现缓存功能。然而&#xff0c;当缓存的数据发生变化时&#xff0c;我们可能需要手动刷新缓存&#xff0c;这可…

C语言---分支和循环语句

1、什么是语句 C语言语句可以分为五类&#xff1a; 表达式语句函数调用语句控制语句复合语句空语句 C语言有九种控制语句 可以分成一下三类&#xff1a; 条件判断语句也叫分支语句&#xff1a;if语句&#xff0c;switch语句&#xff1b;循环执行语句&#xff1a;do while语…