UI自动化测试:异常截图和page_source

news2025/1/18 7:02:02

自动化测试过程中,是否遇到过脚本执行中途出错却不知道原因的情况?测试人员面临的不仅是问题的复现,还有对错误的快速定位和分析。而异常截图与页面源码(Page Source)的结合,正是解决这一难题的利器。

在实际的自动化测试中,您是否清楚异常发生时的具体页面状态?单凭日志信息往往无法全面还原错误背景。通过自动化实现异常截图和保存页面源码的功能,您可以大幅提升定位问题的效率和准确性。

在UI自动化测试行业,随着业务复杂性增加,定位问题的效率和深度成为测试团队竞争力的核心。以异常截图和页面源码为代表的增强调试工具,已成为优秀测试框架的标配。例如 Allure 的报告集成截图功能,TestNG 的详细异常日志,都表明这种趋势在逐步标准化。

为什么需要异常截图和Page Source?
  1. 截图直观定位问题:UI界面异常、元素定位失败等问题可通过截图直接查看。
  2. 源码辅助排查:页面源码保存可帮助分析DOM结构变化、动态加载等问题。
  3. 联动使用效果更佳:截图展示表面,源码剖析细节,二者结合为测试提供全方位视角。

实际案例分享

例如,使用 Selenium 进行电商网站的自动化测试时,在支付页面的验证中,偶尔会出现按钮未加载的问题。通过启用异常捕获机制,截图显示支付按钮缺失,而源码内容揭示了JS脚本未执行的原因,最终确认问题出在接口超时。

01 场景

  • 增加自动化测试代码的可测性

  • 丰富报告

02 实现代码异常时

实现代码异常的时候,实现截图和打印page_source

实现方法:try except 配合截图和page_source操作

特别注意1:

  • 在保存截图和页面源码时,一定先创建好images、source_path路径

  • 保存截图:driver.save_screenshot(路径名称)

  • 获取页面源码:driver.page_source()

  • 异常处理会影响用例本身的结果;

    解决办法:在except之后,再把异常抛出

    代码最后加上:raise Exception;

    如果用例失败,抛出异常;否则即使捕获到异常,用例也会通过

特别注意2:

  • 将截图保存到allure报告中

allure.attach.file(截图路径,name=‘image’,attachment_type=allure.attachment_type.PNG)

  • 将页面源码保存到allure中,以文本的形式存储

allure.attach.file(源码路径,name=‘text’,attachment_type=allure.attachment_type.TEXT)

import sys
import time

import allure
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains


class TestBaidu:

    def setup_class(self):
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(2)

    def teardown_class(self):
        self.driver.quit()

    def test_baidu(self):
        self.driver.get('https://www.baidu.com')
        try:
            self.driver.find_element(By.ID, 'su1')
        except Exception:
            # 时间戳
            time_stamp = int(time.time())
            # 注意:一定要创建好images路径、source_path路径
            image_path = f'./images/image_{time_stamp}.PNG'
            page_source_path = f'./page_source/page_source_{time_stamp}.html'
            # 保存截图
            self.driver.save_screenshot(image_path)
            # 保存获取到的页面源码
            with open(page_source_path, 'w', encoding='utf-8') as f:
                f.write(self.driver.page_source)

            # 将截图添加到allure报告中
            allure.attach.file(image_path,
                               name='image',
                               attachment_type=allure.attachment_type.PNG)

            # 将页面源码添加到allure报告中
            allure.attach.file(page_source_path,
                               name='text',
                               attachment_type=allure.attachment_type.TEXT)

        # 如果用例失败,抛出异常;否则即使捕获到异常,用例也会通过
        raise Exception

03 代码优化

异常捕获处理代码是公共方法和业务代码无关,不能耦合

解决办法,使用装饰器装饰用例或者相关方法。

思路

  • 先把装饰器架子搭建好

  • 把相关逻辑嵌套进来

特别注意

使用装饰器执行用例,被装饰函数还没有执行,所以还没有self.driver,获取被装饰方法的self,也就是实例对象,通过self就可以拿到声明的实例变量driver

driver = args[0].driver

前提条件:被装饰的方法是一个实例方法,实例需要有实例变量self.driver

  • 解决方法1:获取driver放到函数执行之后

import sys
import time

import allure
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys


# 采用装饰器
def ui_exception_record(func):

    def inner(*args, **kwargs):

        try:
            return func(*args, **kwargs)

        except Exception:
            driver = args[0].driver
            # 时间戳
            time_stamp = int(time.time())
            # 注意:一定要创建好images路径、source_path路径
            image_path = f'./images/image_{time_stamp}.PNG'
            page_source_path = f'./page_source/page_source_{time_stamp}.html'
            # 保存截图
            driver.save_screenshot(image_path)
            # 保存获取到的页面源码
            with open(page_source_path, 'w', encoding='utf-8') as f:
                f.write(driver.page_source)

            # 将截图添加到allure报告中
            allure.attach.file(image_path,
                               name='image',
                               attachment_type=allure.attachment_type.PNG)

            # 将页面源码添加到allure报告中
            allure.attach.file(page_source_path,
                               name='text',
                               attachment_type=allure.attachment_type.TEXT)

            # 如果用例失败,抛出异常;否则即使捕获到异常,用例也会通过
            raise Exception

    return inner
class TestBaidu2:

    def setup_class(self):
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(2)

    def teardown_class(self):
        self.driver.quit()

    @ui_exception_record
    def test_baidu(self):
        self.driver.get('https://www.baidu.com')
        self.driver.find_element(By.ID, 'su1')

  • 解决方法2:保证使用装饰器的时候,driver已经声明:driver = args[0].driver

import sys
import time

import allure
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys


# 采用装饰器
def ui_exception_record(func):

    def inner(*args, **kwargs):
        driver = args[0].driver

        try:
            return func(*args, **kwargs)

        except Exception:
            # 时间戳
            time_stamp = int(time.time())
            # 注意:一定要创建好images路径、source_path路径
            image_path = f'./images/image_{time_stamp}.PNG'
            page_source_path = f'./page_source/page_source_{time_stamp}.html'
            # 保存截图
            driver.save_screenshot(image_path)
            # 保存获取到的页面源码
            with open(page_source_path, 'w', encoding='utf-8') as f:
                f.write(driver.page_source)

            # 将截图添加到allure报告中
            allure.attach.file(image_path,
                               name='image',
                               attachment_type=allure.attachment_type.PNG)

            # 将页面源码添加到allure报告中
            allure.attach.file(page_source_path,
                               name='text',
                               attachment_type=allure.attachment_type.TEXT)

            # 如果用例失败,抛出异常;否则即使捕获到异常,用例也会通过
            raise Exception

    return inner
return inner


class TestBaidu2:

    def setup_class(self):
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(2)

    def teardown_class(self):
        self.driver.quit()

    @ui_exception_record
    def test_baidu(self):
        self.driver.get('https://www.baidu.com')
        self.driver.find_element(By.ID, 'su1')

  • 一旦被装饰的方法有返回值,会丢失返回值

    解决方案:return func(*args, **kwargs)

当用例执行失败allure报告中可以查看截图

图片

当用例执行失败allure报告中可以查看page_source源码

图片

异常截图和Page Source的结合,不仅帮助测试人员快速还原问题背景,更为问题定位提供了关键依据。这种看似简单的操作,却是提升测试效率的关键一步。

测试的目标从来不是证明程序正确,而是帮助发现问题。学会利用工具,还原问题真相,才是真正的测试之道!

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

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

相关文章

OSI七层协议——分层网络协议

OSI七层协议,顾名思义,分为七层,实际上七层是不存在的,是人为的进行划分,让人更好的理解 七层协议包括,物理层(我),数据链路层(据),网络层(网),传输层(传输),会话层(会),表示层(表),应用层(用)(记忆口诀->我会用表…

浅谈计算机网络04 | 现代网络需求与技术支撑

现代网络需求与技术支撑 一、网络和因特网流量的类型剖析1.1 弹性流量的自适应特征1.2 非弹性流量的刚性特征1.3 实时流量特性 二、特定领域的网络需求解析2.1 大数据环境下的网络需求分析2.2 云计算环境下的网络需求分析2.3 移动数据环境下的网络需求分析 三、QoS和QoE&#x…

微服务架构下的负载均衡:Spring Cloud如何实现高效流量分配

在Spring Cloud中,实现服务的负载均衡,主要是为了让多个服务实例能够均匀分担请求压力,就像把一堆东西分给几个人拿,确保大家都不太累。 假设你开了一个网店,有很多顾客会同时来买东西(这就是并发请求&…

L3自动驾驶开始落地,AI交通时代离我们有多远?

2025年,自动驾驶领域迎来了一个重要的里程碑——L3级别自动驾驶技术的逐步落地。据《中国汽车报》报道,多家汽车制造商已获得L3级自动驾驶的量产资质,这意味着车辆能够在特定条件下完全接管驾驶任务,而驾驶员可以在车内进行其他活…

动手学大数据-2常见的查询优化器

目录 什么是查询优化器 查询优化器分类 Top-downOptimizer Bottom-upOptimizer RBO-关系代数 RBO-优化原则 RBO-列裁剪 RBO-谓词下推 RBO-传递闭包 RBO-RuntimeFilter 小结 CBO(Cost-basedOptimizer) 概念 CBO-统计信息 CBO-统计信息…

ctfshow复现2024ciscn第一场web

2024ciscn第一场 本章内容均在ctfshow复现 图片若显示失败请参考我的blog👇 ddl08.github.io sanic python污染 源码 from sanic import Sanic from sanic.response import text, html from sanic_session import Session import pydash # pydash5.1.2 ​ ​…

Java快速入门之数组、方法

一、数组 1、数组的概念: 数组指的是一种容器,可以用来存储同种数据类型的多个值,但是数组容器在存储数据的时候,需要结合隐式转换考虑。 例如: 定义了一个int类型的数组,那么boolean、double类型的数据是…

STM32 FreeRTOS任务通知

目录 任务通知的简介 任务通知相关API函数介绍 任务通知的简介 任务通知是 FreeRTOS 中一种用于任务间通信的机制,它允许一个任务向其他任务发送简单的通知或信号,以实现任务间的同步和协作。任务通知通常用于替代二值信号量或事件标志组,提…

Chrome谷歌浏览器如何能恢复到之前的旧版本

升级了谷歌最新版不习惯,如何降级版本 未完待续。。 电脑中的Chrome谷歌浏览器升级到了最新版本,但是有种种的不适应,如何能恢复到之前的旧版本呢?我们来看看操作步骤,而且无需卸载重装。 怎么恢复Chrome 之前版本&a…

前端实习第二个月小结

时间飞快,第一次实习已经过去两个多月,作一些简单的总结和分享。 注:文章整体会比较轻松,提及的经历、经验仅作参考。 一、关于实习/工作内容 1、工作内容 近期做的是管理后台方面的业务,技术栈:前端re…

阿里云 Serverless 助力盟主直播:高并发下的稳定性和成本优化

在直播场景中,阿里云 Serverless 应用引擎 SAE 提供的无缝弹性伸缩与极速部署能力,确保直播间高并发时的流畅体验,降低了我们的运营成本,简化了运维流程。结合阿里云云原生数据库 PolarDB 的 Serverless 能力,实现了数…

flutter的web页面

有几个服务器 有几个后台 直接通过web端进去虽然说很方便,但… 于是把web页面镶嵌到应用里面去, 这样就换了个方式打开web页面了 比如这里有有个列表 这里是写死了,活的列表可以通过io去获取 import package:flutter/material.dart; imp…

【Rust自学】13.1. 闭包 Pt.1:什么是闭包、如何使用闭包

13.1.0. 写在正文之前 Rust语言在设计过程中收到了很多语言的启发,而函数式编程对Rust产生了非常显著的影响。函数式编程通常包括通过将函数作为值传递给参数、从其他函数返回它们、将它们分配给变量以供以后执行等等。 在本章中,我们会讨论 Rust 的一…

安装 fairseq 失败

git clone https://github.com/pytorch/fairseq cd fairseq pip install --editable ./ 出现错误 解决方法: pip install pip24.0 参考:https://github.com/SociallyIneptWeeb/AICoverGen/issues/133 gcc 和 g 需要 9.0以上,怎么安装可以…

解决conda create速度过慢的问题

问题 构建了docker容器 想在容器中创建conda环境,但是conda create的时候速度一直很慢 解决办法 宿主机安装的是anaconda 能正常conda create,容器里安装的是miniforge conda create的时候速度一直很慢,因为容器和宿主机共享网络了,宿主机…

AI编程工具横向评测--Cloudstudio塑造完全态的jupyter notebook助力数据分析应用开发

AI编程工具横向评测–Cloudstudio塑造完全态的jupyter notebook助力数据分析应用开发 数据分析类应用的开发,指的是首先进行数据分析,比如统计学分析、机器学习模型的构建等,然后将分析的流程开发成数据分析类的工具,或者将数据分…

Web 浏览器轻松访问和管理 SSH 与 Telnet 服务

前几天也分享了一篇类似的文章,但是有朋友反馈不太安全,如果有个输入密码后访问最好,然后我就找了一下发现了这个更加优秀的项目, sshwifty是一个开源项目,它允许用户通过浏览器进行 SSH 和 Telnet 操作。这个项目提供…

Python制作简易PDF查看工具PDFViewerV1.0

PDFViewer PDF浏览工具,Python自制PDF查看工具,可实现基本翻页浏览功能,其它功能在进一步开发完善当中,如果有想一起开发的朋友,可以留言。本软件完全免费,自由使用。 软件界面简洁,有菜单栏、…

Python大数据可视化:基于Python的王者荣耀战队的数据分析系统设计与实现_flask+hadoop+spider

开发语言:Python框架:flaskPython版本:python3.7.7数据库:mysql 5.7数据库工具:Navicat11开发软件:PyCharm 系统展示 管理员登录 管理员功能界面 比赛信息管理 看板展示 系统管理 摘要 本文使用Python与…

【k8s面试题2025】3、练气中期

体内灵气的量和纯度在逐渐增加。 文章目录 在 Kubernetes 中自定义 Service端口报错常用控制器Kubernetes 中拉伸收缩副本失效设置节点容忍异常时间Deployment 控制器的升级和回滚日志收集资源监控监控 Docker将 Master 节点设置为可调度 在 Kubernetes 中自定义 Service端口报…