当前位置: 首页 > 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;当子弹飞出屏幕…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?

在建筑行业&#xff0c;项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升&#xff0c;传统的管理模式已经难以满足现代工程的需求。过去&#xff0c;许多企业依赖手工记录、口头沟通和分散的信息管理&#xff0c;导致效率低下、成本失控、风险频发。例如&#…...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted&#xff08;&#xff09;是OpenCV库中用于图像处理的函数&#xff0c;主要功能是将两个输入图像&#xff08;尺寸和类型相同&#xff09;按照指定的权重进行加权叠加&#xff08;图像融合&#xff09;&#xff0c;并添加一个标量值&#x…...

蓝桥杯 2024 15届国赛 A组 儿童节快乐

P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡&#xff0c;轻快的音乐在耳边持续回荡&#xff0c;小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下&#xff0c;六一来了。 今天是六一儿童节&#xff0c;小蓝老师为了让大家在节…...

C++ 基础特性深度解析

目录 引言 一、命名空间&#xff08;namespace&#xff09; C 中的命名空间​ 与 C 语言的对比​ 二、缺省参数​ C 中的缺省参数​ 与 C 语言的对比​ 三、引用&#xff08;reference&#xff09;​ C 中的引用​ 与 C 语言的对比​ 四、inline&#xff08;内联函数…...

图表类系列各种样式PPT模版分享

图标图表系列PPT模版&#xff0c;柱状图PPT模版&#xff0c;线状图PPT模版&#xff0c;折线图PPT模版&#xff0c;饼状图PPT模版&#xff0c;雷达图PPT模版&#xff0c;树状图PPT模版 图表类系列各种样式PPT模版分享&#xff1a;图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...

Linux离线(zip方式)安装docker

目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1&#xff1a;修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本&#xff1a;CentOS 7 64位 内核版本&#xff1a;3.10.0 相关命令&#xff1a; uname -rcat /etc/os-rele…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行

项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战&#xff0c;克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...