当前位置: 首页 > news >正文

【pytest、playwright】allure报告生成视频和图片

目录

1、修改插件pytest_playwright

2、conftest.py配置

3、修改pytest.ini文件

4、运行case

5、注意事项


1、修改插件pytest_playwright

 pytest_playwright.py内容如下:

# Copyright (c) Microsoft Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.import shutil
import os
import sys
import warnings
from typing import Any, Callable, Dict, Generator, List, Optionalimport pytest
from playwright.sync_api import (Browser,BrowserContext,BrowserType,Error,Page,Playwright,sync_playwright,
)
from slugify import slugify
import tempfile
import allureartifacts_folder = tempfile.TemporaryDirectory(prefix="playwright-pytest-")@pytest.fixture(scope="session", autouse=True)
def delete_output_dir(pytestconfig: Any) -> None:output_dir = pytestconfig.getoption("--output")if os.path.exists(output_dir):try:shutil.rmtree(output_dir)except FileNotFoundError:# When running in parallel, another thread may have already deleted the filespassdef pytest_generate_tests(metafunc: Any) -> None:if "browser_name" in metafunc.fixturenames:browsers = metafunc.config.option.browser or ["chromium"]metafunc.parametrize("browser_name", browsers, scope="session")def pytest_configure(config: Any) -> None:config.addinivalue_line("markers", "skip_browser(name): mark test to be skipped a specific browser")config.addinivalue_line("markers", "only_browser(name): mark test to run only on a specific browser")# Making test result information available in plugins
# https://docs.pytest.org/en/latest/example/simple.html#making-test-result-information-available-in-fixtures
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item: Any) -> Generator[None, Any, None]:# execute all other hooks to obtain the report objectoutcome = yieldrep = outcome.get_result()# set a report attribute for each phase of a call, which can# be "setup", "call", "teardown"setattr(item, "rep_" + rep.when, rep)def _get_skiplist(item: Any, values: List[str], value_name: str) -> List[str]:skipped_values: List[str] = []# Allowlistonly_marker = item.get_closest_marker(f"only_{value_name}")if only_marker:skipped_values = valuesskipped_values.remove(only_marker.args[0])# Denylistskip_marker = item.get_closest_marker(f"skip_{value_name}")if skip_marker:skipped_values.append(skip_marker.args[0])return skipped_valuesdef pytest_runtest_setup(item: Any) -> None:if not hasattr(item, "callspec"):returnbrowser_name = item.callspec.params.get("browser_name")if not browser_name:returnskip_browsers_names = _get_skiplist(item, ["chromium", "firefox", "webkit"], "browser")if browser_name in skip_browsers_names:pytest.skip("skipped for this browser: {}".format(browser_name))VSCODE_PYTHON_EXTENSION_ID = "ms-python.python"@pytest.fixture(scope="session")
def browser_type_launch_args(pytestconfig: Any) -> Dict:launch_options = {}headed_option = pytestconfig.getoption("--headed")if headed_option:launch_options["headless"] = Falseelif VSCODE_PYTHON_EXTENSION_ID in sys.argv[0] and _is_debugger_attached():# When the VSCode debugger is attached, then launch the browser headed by defaultlaunch_options["headless"] = Falsebrowser_channel_option = pytestconfig.getoption("--browser-channel")if browser_channel_option:launch_options["channel"] = browser_channel_optionslowmo_option = pytestconfig.getoption("--slowmo")if slowmo_option:launch_options["slow_mo"] = slowmo_optionreturn launch_optionsdef _is_debugger_attached() -> bool:pydevd = sys.modules.get("pydevd")if not pydevd or not hasattr(pydevd, "get_global_debugger"):return Falsedebugger = pydevd.get_global_debugger()if not debugger or not hasattr(debugger, "is_attached"):return Falsereturn debugger.is_attached()def _build_artifact_test_folder(pytestconfig: Any, request: pytest.FixtureRequest, folder_or_file_name: str
) -> str:output_dir = pytestconfig.getoption("--output")return os.path.join(output_dir, slugify(request.node.nodeid), folder_or_file_name)@pytest.fixture(scope="session")
def browser_context_args(pytestconfig: Any,playwright: Playwright,device: Optional[str],
) -> Dict:context_args = {}if device:context_args.update(playwright.devices[device])base_url = pytestconfig.getoption("--base-url")if base_url:context_args["base_url"] = base_urlvideo_option = pytestconfig.getoption("--video")capture_video = video_option in ["on", "retain-on-failure"]if capture_video:context_args["record_video_dir"] = artifacts_folder.namereturn context_args@pytest.fixture(scope="session")
def playwright() -> Generator[Playwright, None, None]:pw = sync_playwright().start()yield pwpw.stop()@pytest.fixture(scope="session")
def browser_type(playwright: Playwright, browser_name: str) -> BrowserType:return getattr(playwright, browser_name)@pytest.fixture(scope="session")
def launch_browser(browser_type_launch_args: Dict,browser_type: BrowserType,
) -> Callable[..., Browser]:def launch(**kwargs: Dict) -> Browser:launch_options = {**browser_type_launch_args, **kwargs}browser = browser_type.launch(**launch_options)return browserreturn launch@pytest.fixture(scope="session")
def browser(launch_browser: Callable[[], Browser]) -> Generator[Browser, None, None]:browser = launch_browser()yield browserbrowser.close()artifacts_folder.cleanup()@pytest.fixture()
def context(browser: Browser,browser_context_args: Dict,pytestconfig: Any,request: pytest.FixtureRequest,
) -> Generator[BrowserContext, None, None]:pages: List[Page] = []context = browser.new_context(**browser_context_args)context.on("page", lambda page: pages.append(page))tracing_option = pytestconfig.getoption("--tracing")capture_trace = tracing_option in ["on", "retain-on-failure"]if capture_trace:context.tracing.start(name=slugify(request.node.nodeid),screenshots=True,snapshots=True,sources=True,)yield context# If requst.node is missing rep_call, then some error happened during execution# that prevented teardown, but should still be counted as a failurefailed = request.node.rep_call.failed if hasattr(request.node, "rep_call") else Trueif capture_trace:retain_trace = tracing_option == "on" or (failed and tracing_option == "retain-on-failure")if retain_trace:trace_path = _build_artifact_test_folder(pytestconfig, request, "trace.zip")context.tracing.stop(path=trace_path)else:context.tracing.stop()screenshot_option = pytestconfig.getoption("--screenshot")capture_screenshot = screenshot_option == "on" or (failed and screenshot_option == "only-on-failure")if capture_screenshot:print("--------------------------111")for index, page in enumerate(pages):human_readable_status = "failed" if failed else "finished"screenshot_path = _build_artifact_test_folder(pytestconfig, request, f"test-{human_readable_status}-{index + 1}.png")print(f'-----------------{screenshot_path}')try:page.screenshot(timeout=5000, path=screenshot_path)allure.attach.file(screenshot_path,name=f"{request.node.name}-{human_readable_status}-{index + 1}",attachment_type=allure.attachment_type.PNG)except Error:passcontext.close()video_option = pytestconfig.getoption("--video")preserve_video = video_option == "on" or (failed and video_option == "retain-on-failure")if preserve_video:for page in pages:video = page.videoif not video:continuetry:video_path = video.path()file_name = os.path.basename(video_path)file_path = _build_artifact_test_folder(pytestconfig, request, file_name)video.save_as(path=file_path)# 放入视频allure.attach.file(file_path, name=f"{request.node.name}-{human_readable_status}-{index + 1}",attachment_type=allure.attachment_type.WEBM)except Error:# Silent catch empty videos.pass@pytest.fixture
def page(context: BrowserContext) -> Generator[Page, None, None]:page = context.new_page()yield page@pytest.fixture(scope="session")
def is_webkit(browser_name: str) -> bool:return browser_name == "webkit"@pytest.fixture(scope="session")
def is_firefox(browser_name: str) -> bool:return browser_name == "firefox"@pytest.fixture(scope="session")
def is_chromium(browser_name: str) -> bool:return browser_name == "chromium"@pytest.fixture(scope="session")
def browser_name(pytestconfig: Any) -> Optional[str]:# When using unittest.TestCase it won't use pytest_generate_tests# For that we still try to give the user a slightly less feature-rich experiencebrowser_names = pytestconfig.getoption("--browser")if len(browser_names) == 0:return "chromium"if len(browser_names) == 1:return browser_names[0]warnings.warn("When using unittest.TestCase specifying multiple browsers is not supported")return browser_names[0]@pytest.fixture(scope="session")
def browser_channel(pytestconfig: Any) -> Optional[str]:return pytestconfig.getoption("--browser-channel")@pytest.fixture(scope="session")
def device(pytestconfig: Any) -> Optional[str]:return pytestconfig.getoption("--device")def pytest_addoption(parser: Any) -> None:group = parser.getgroup("playwright", "Playwright")group.addoption("--browser",action="append",default=[],help="Browser engine which should be used",choices=["chromium", "firefox", "webkit"],)group.addoption("--headed",action="store_true",default=False,help="Run tests in headed mode.",)group.addoption("--browser-channel",action="store",default=None,help="Browser channel to be used.",)group.addoption("--slowmo",default=0,type=int,help="Run tests with slow mo",)group.addoption("--device", default=None, action="store", help="Device to be emulated.")group.addoption("--output",default="test-results",help="Directory for artifacts produced by tests, defaults to test-results.",)group.addoption("--tracing",default="off",choices=["on", "off", "retain-on-failure"],help="Whether to record a trace for each test.",)group.addoption("--video",default="off",choices=["on", "off", "retain-on-failure"],help="Whether to record video for each test.",)group.addoption("--screenshot",default="off",choices=["on", "off", "only-on-failure"],help="Whether to automatically capture a screenshot after each test.",)

主要修改了原插件的哪些内容:

你们搜索这个文件内容,关于allure的内容,都是我们做了修改的~

2、conftest.py配置

删除原本安装的pytest_playwright插件:

在settiings中找到pytest_playwright,点击减号就可以删除了~

3、修改pytest.ini文件

 --tracing=retain-on-failure--screenshot=only-on-failure--video=retain-on-failure

4、运行case

此时运行case,当case失败时,我们可以看到这个目录:

里面就是截图,录屏,以及路由追踪~

5、注意事项

如果conftest.py中配置了如下内容:

 

要保证json文件中有值,否则会报错~

相关文章:

【pytest、playwright】allure报告生成视频和图片

目录 1、修改插件pytest_playwright 2、conftest.py配置 3、修改pytest.ini文件 4、运行case 5、注意事项 1、修改插件pytest_playwright pytest_playwright.py内容如下: # Copyright (c) Microsoft Corporation. # # Licensed under the Apache License, Ver…...

浅谈iOS开发中的自动引用计数ARC

1.ARC是什么 我们知道,在C语言中,创建对象时必须手动分配和释放适量的内存。然而,在 Swift 中,当不再需要类实例时,ARC 会自动释放这些实例的内存。 Swift 使用 ARC 来跟踪和管理应用程序的内存,其主要是由…...

Spring IoCDI(2)

IoC详解 通过上面的案例, 我们已经知道了IoC和DI的基本操作, 接下来我们来系统地学习Spring IoC和DI的操作. 前面我们提到的IoC控制反转, 就是将对象的控制权交给Spring的IoC容器, 由IoC容器创建及管理对象. (也就是Bean的存储). Bean的存储 我们之前只讲到了Component注解…...

30. UE5 RPG GamplayAbility的配置项

在上一篇文章,我们介绍了如何将GA应用到角色身上的,接下来这篇文章,将主要介绍一下GA的相关配置项。 在这之前,再多一嘴,你要能激活技能,首先要先应用到ASC上面,才能够被激活。 标签 之前介绍…...

提升自己最快的方式是什么?

提升自己最快的方式通常涉及到个人成长的各个方面,包括心理、情感、技能和知识等。根据查阅到的资料,以下是一些具体的方法和步骤,帮助你快速提升自己: 1. 培养屏蔽力 荷兰畅销书作家罗伊马丁纳提到,屏蔽力是个人成长…...

题目:一个5位数,判断它是不是回文数。即12321是回文数,个位与万位相同,十位与千位相同。

题目:一个5位数,判断它是不是回文数。即12321是回文数,个位与万位相同,十位与千位相同。    There is no nutrition in the blog content. After reading it, you will not only suffer from malnutrition, but also impotence…...

《HelloGitHub》第 96 期

兴趣是最好的老师,HelloGitHub 让你对编程感兴趣! 简介 HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。 https://github.com/521xueweihan/HelloGitHub 这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等,涵盖多种编程语言 …...

C++tuple类型

tuple 类型 tuple是类似pair的模板。 每个pair的成员类型都不相同,但每个pair都恰好有两个成员。不同tuple类型的成员类型也不相同,但一个tuple可以有任意数量的成员。 每个确定的tuple类型的成员数目是固定的,但一个tuple类型的成员数目可…...

亚远景科技-浅谈ASPICE标准和ASPICE认证/评估

ASPICE(Automotive SPICE)是一种针对汽车行业的软件开发过程的评估模型,它旨在帮助汽车制造商和供应商提高软件开发过程的能力和质量,从而提升产品的质量、安全性和效率。 ASPICE标准涵盖了软件开发的各个阶段和活动,…...

PHP性能提升方案

一、背景与介绍 PHP语言开发效率高,特别应用于适合中小型项目,对于创业初期敏捷开发验证项目可行性或者Demo演示绝对占据优势。 但是随着现在Web应用的复杂性,针对项目要适应高并发、高流量的访问特性,PHP确实在性能方面相对Go、J…...

关系(二)利用python绘制热图

关系(二)利用python绘制热图 热图 (Heatmap)简介 热图适用于显示多个变量之间的差异,通过颜色判断彼此之间是否存在相关性。 快速绘制 基于seaborn import seaborn as sns import pandas as pd import numpy as np i…...

P8597 [蓝桥杯 2013 省 B] 翻硬币

# [蓝桥杯 2013 省 B] 翻硬币 ## 题目背景 小明正在玩一个“翻硬币”的游戏。 ## 题目描述 桌上放着排成一排的若干硬币。我们用 * 表示正面,用 o 表示反面(是小写字母,不是零),比如可能情形是 **oo***oooo&#x…...

主流公链 - Fantom

Fantom:高性能的区块链协议 Fantom是一种开创性的区块链协议,旨在革新去中心化应用和数字金融领域 技术特点 共识机制 Lachesis协议:Fantom使用了Lachesis协议作为其共识算法。Lachesis是一种 异步拜占庭容错(ABFT)共…...

vue-quill-editor 富文本编辑器(可上传视频图片),组件挂载的方式实现

1.安装 npm install vue-quill-editor --save npm install quill-image-drop-module --save npm install quill-image-resize-module --save2.在组件下面新增组件 QlEditor (1)index.vue <template><div><div idquillEditorQiniu><!-- 基于element…...

入门编程第一步,从记住这些单词开始

** 入门编程第一步&#xff0c;从记住这些单词开始 ** 2023-10-18 一、交互式环境与 print 输出 1、print : 打印/输出 2、coding : 编码 3、syntax : 语法 4、error : 错误 5、invalid : 无效 6、idenfifier : 名称/标识符 7、character : 字符 二、字符串的操作&#x…...

[C++]使用OpenCV去除面积较小的连通域

这是后期补充的部分&#xff0c;和前期的代码不太一样 效果图 源代码 //测试 void CCutImageVS2013Dlg::OnBnClickedTestButton1() {vector<vector<Point> > contours; //轮廓数组vector<Point2d> centers; //轮廓质心坐标 vector<vector<Point&…...

vscode连接不上,终端ssh正常,一直输入密码正确但是无法登录

若是之前链结果突然等不上&#xff0c;使用第一个链接 若是第一次链接连不上&#xff0c;先使用第二个链接&#xff0c;在使用第一个链接 原因&#xff1a;原因是服务器端的wget命令不能使用&#xff0c;vscode需要服务器端下载个文件&#xff0c;无法下载就导致了如上的错误…...

Hive on Spark 配置

目录 1 Hive 引擎简介2 Hive on Spark 配置2.1 在 Hive 所在节点部署 Spark2.2 在hive中创建spark配置文件2.3 向 HDFS上传Spark纯净版 jar 包2.4 修改hive-site.xml文件2.5 Hive on Spark测试2.6 报错 1 Hive 引擎简介 Hive引擎包括&#xff1a;MR&#xff08;默认&#xff09…...

ROS 基本

ROS创建自己的功能包 ROS中工作空间(workspace)是一个存放工程开发相关文件的文件夹&#xff0c;其中有四个文件夹。 src:代码空间(Source Space)build:编译空间(Build Space)devel:开发空间(Development Space)install:安装空间(Install Space) OK接下来创作工作空间&#…...

Pygame基础9-射击

简介 玩家用鼠标控制飞机&#xff08;白色方块&#xff09;移动&#xff0c;按下鼠标后&#xff0c;玩家所在位置出现子弹&#xff0c;子弹匀速向右飞行。 代码 没有什么新的东西&#xff0c;使用两个精灵类表示玩家和子弹。 有一个细节需要注意&#xff0c;当子弹飞出屏幕…...

自治性、反应性、学习能力:AI Agent的关键特性

自治性、反应性、学习能力:AI Agent的关键特性——从蚂蚁觅食到通用智能体的进化之路 关键词 AI Agent, 自治性, 反应性, 强化学习, 记忆机制, 环境交互, 通用人工智能萌芽 摘要 想象一下:你有一个能自己帮你规划周末露营路线(自治性)、中途遇到暴雨自动切换到附近民宿…...

Alph:一键统一配置AI编程助手MCP服务器的命令行工具

1. 项目概述&#xff1a;告别手动配置的混乱时代 如果你和我一样&#xff0c;日常开发中同时用着 Cursor、Claude Code、Gemini CLI 这些 AI 编程助手&#xff0c;那你一定对下面这个场景深恶痛绝&#xff1a;每次想给它们接入一个新的 MCP 服务器&#xff0c;都得像个考古学家…...

Dify数据库查询插件:让AI应用轻松连接业务数据的实战指南

1. 项目概述与核心价值 如果你正在使用 Dify 构建企业级 AI 应用&#xff0c;并且经常需要让 AI 助手去查询数据库里的数据——比如让 LLM 帮你分析销售报表、查找用户信息或者生成业务洞察——那么你很可能遇到过这样的痛点&#xff1a;Dify 本身并不直接支持数据库连接。你需…...

如何解决Funannotate数据库安装失败:从403错误到完整部署的实战指南

如何解决Funannotate数据库安装失败&#xff1a;从403错误到完整部署的实战指南 【免费下载链接】funannotate Eukaryotic Genome Annotation Pipeline 项目地址: https://gitcode.com/gh_mirrors/fu/funannotate Funannotate是真核基因组注释的强大工具&#xff0c;但在…...

京城汤泉夜宿体验:寻找最舒适的放松之地

引言在快节奏的城市生活中&#xff0c;越来越多的人开始追求一种能够彻底放松身心的方式。洗浴汤泉作为其中的一种选择&#xff0c;以其独特的魅力吸引了众多都市人。本文将带您走进京城的洗浴汤泉世界&#xff0c;特别介绍合韵汤泉&#xff0c;帮助您找到最适合自己的放松之地…...

YOLO26改进 | MSHC多尺度异构卷积:用方形核与条带核捕获复杂空间纹理,以清晰动机打造超强创新!

# YOLO26改进最新创新改进系列 | MSHC多尺度异构卷积&#xff1a;用方形核与条带核捕获复杂空间纹理&#xff0c;以清晰动机打造超强创新&#xff01; 购买相关资料后畅享一对一答疑&#xff01; 畅享超多免费持续更新且可大幅度提升文章档次的纯干货工具&#xff01; 这篇采用…...

轴承剩余寿命预测 | 基于BP神经网络的轴承剩余寿命预测MATLAB实现!

研究背景 该代码基于IEEE PHM 2012数据挑战赛的轴承全寿命加速退化实验数据&#xff0c;旨在利用数据驱动方法预测滚动轴承的剩余使用寿命&#xff08;RUL&#xff09;。实验中轴承在恒定负载下持续运行至失效&#xff0c;期间通过水平/竖直加速度传感器以25.6 kHz采样频率每隔…...

北京AGG聚砂吸声板哪家性价比高

在选择AGG聚砂吸声板时&#xff0c;“性价比”往往不只是看价格&#xff0c;而是综合考量声学性能、施工服务、材料稳定性和后期维护的平衡。北京市场上的供应商不少&#xff0c;但真正能长期稳定输出成熟产品的&#xff0c;需要从几个实际角度去判断。首先&#xff0c;要优先看…...

如何快速恢复加密压缩包密码:ArchivePasswordTestTool完整指南

如何快速恢复加密压缩包密码&#xff1a;ArchivePasswordTestTool完整指南 【免费下载链接】ArchivePasswordTestTool 利用7zip测试压缩包的功能 对加密压缩包进行自动化测试密码 项目地址: https://gitcode.com/gh_mirrors/ar/ArchivePasswordTestTool 你是否曾经遇到过…...

LVGL图片资源全解析:从C数组到图标字体的高效集成方案

1. LVGL图片资源方案概述 在嵌入式GUI开发中&#xff0c;图片资源的管理直接影响产品性能和开发效率。LVGL作为轻量级图形库&#xff0c;提供了三种主流的图片集成方案&#xff1a;内部C数组、外部文件系统图片和图标字体。每种方案都有其独特的适用场景和实现方式&#xff0c;…...