Jmeter——结合Allure展示测试报告 _

news2024/12/24 21:15:31

 

在平时用jmeter做测试时,生成报告的模板,不是特别好。大家应该也知道allure报告,页面美观。

先来看效果图,报告首页,如下所示:

​编辑

报告详情信息,如下所示:

​编辑

运行run.py文件,运行成功,如下所示:

​编辑

接下来来看下实现过程。

安装allure

allure是开源的,直接到github上下载即可。就不细说了。需要注意的是,环境变量的配置,allure的bin路径,需要配置到环境变量path中。

jmeter配置

找到bin目录下的 jmeter.properties 配置文件,将如下所示对应配置取消注释,jmeter.save.saveservice.output_format 修改为xml。

# This section helps determine how result data will be saved.
# The commented out values are the defaults.

# legitimate values: xml, csv, db.  Only xml and csv are currently supported.
jmeter.save.saveservice.output_format=xml

# The below properties are true when field should be saved; false otherwise
#
# assertion_results_failure_message only affects CSV output
#jmeter.save.saveservice.assertion_results_failure_message=true
#
# legitimate values: none, first, all
#jmeter.save.saveservice.assertion_results=none
#
jmeter.save.saveservice.data_type=true
jmeter.save.saveservice.label=true
jmeter.save.saveservice.response_code=true
# response_data is not currently supported for CSV output
jmeter.save.saveservice.response_data=true
# Save ResponseData for failed samples
jmeter.save.saveservice.response_data.on_error=true
jmeter.save.saveservice.response_message=true
jmeter.save.saveservice.successful=true
jmeter.save.saveservice.thread_name=true
jmeter.save.saveservice.time=true
jmeter.save.saveservice.subresults=true
jmeter.save.saveservice.assertions=true
jmeter.save.saveservice.latency=true
# Only available with HttpClient4
jmeter.save.saveservice.connect_time=true
jmeter.save.saveservice.samplerData=true
jmeter.save.saveservice.responseHeaders=true
jmeter.save.saveservice.requestHeaders=true
jmeter.save.saveservice.encoding=true
jmeter.save.saveservice.bytes=true
# Only available with HttpClient4
jmeter.save.saveservice.sent_bytes=true
jmeter.save.saveservice.url=true
jmeter.save.saveservice.filename=true
jmeter.save.saveservice.hostname=true
jmeter.save.saveservice.thread_counts=true
jmeter.save.saveservice.sample_count=true
jmeter.save.saveservice.idle_time=true

# Timestamp format - this only affects CSV output files
# legitimate values: none, ms, or a format suitable for SimpleDateFormat
jmeter.save.saveservice.timestamp_format=ms
jmeter.save.saveservice.timestamp_format=yyyy/MM/dd HH:mm:ss.SSS

生成jmeter结果文件

使用命令 jmeter -n -t C:\Users\Desktop\auth.jmx -l C:\Users\Desktop\result.xml 即可生成xml文件

安装依赖包

按项目中的 requirements.txt 文件,安装对应的依赖包即可。

文件解析生成allure报告

文件解析

xml文件内容如下:

​编辑

从上述的内容,我们可以分析得出如下内容:

t 从请求开始到响应结束的时间
ts 表示访问的时刻: date
s 运行的结果
lb 表示标题
rc 返回的响应码
rm 响应信息
tn 线程的名字
assertionResult: 断言信息
responseData/samplerData: 返回数据
queryString: 请求信息

代码实现

利用生成的结果文件生成pytest的参数化数据

    try:
        converte_data = xmltodict.parse(result_file, encoding='utf-8')
        sample_keys = list(converte_data['testResults'].keys())
        result = []
        ws_result = []
        sample_result = converte_data['testResults']['httpSample'] if isinstance(
            converte_data['testResults']['httpSample'],
            list) else [converte_data['testResults']['httpSample']]
        if 'sample' in sample_keys:
            ws_result = converte_data['testResults']['sample'] if isinstance(converte_data['testResults']['sample'],
                                                                             list) else [
                converte_data['testResults']['sample']]
        result_data = sample_result + ws_result
        for data in result_data:
            time = data['@t'] if '@t' in data else ''
            date = data['@ts'] if '@ts' in data else ''
            status = data['@s'] if '@s' in data else ''
            title = data['@lb'] if '@lb' in data else ''
            status_code = data['@rc'] if '@rc' in data else ''
            status_message = data['@rm'] if '@rm' in data else ''
            thread = data['@tn'] if '@tn' in data else ''
            assertion = data['assertionResult'] if 'assertionResult' in data else ''
            response_data = data['responseData']['#text'] if 'responseData' in data and '#text' in data['responseData'] \
                else ''
            sampler_data = data['samplerData']['#text'] if 'samplerData' in data and '#text' in data['samplerData'] \
                else ''
            request_data = data['queryString']['#text'] if 'queryString' in data and '#text' in data[
                'queryString'] else ''
            request_header = data['requestHeader']['#text'] if 'requestHeader' in data and '#text' in data[
                'requestHeader'] else ''
            request_url = data['java.net.URL'] if 'java.net.URL' in data else ''
            story = '未标记'
            assertion_name, assertion_result = None, None
            if status == 'false':
                assertion_name, assertion_result = get_assertion(assertion)

            meta_data = (
                time, date, status, story, title, status_code, status_message, thread, assertion_name, assertion_result,
                response_data
                , sampler_data, request_data, request_header, request_url)
            result.append(meta_data)
        return result
    except Exception as e:
        print(e)
        return [
            ('time', 'date', 'true', 'story', 'title', 'status_code', 'status_message', 'thread', 'assertion_name',
             'assertion_result',
             'response_data', 'sampler_data', 'request_data', 'request_header', 'request_url')]

用例详情字段

@allure.step('用例名称:{title}')
    def title_step(self, title):
        pass

    @allure.step('请求信息')
    def request_step(self, request_url, request_header, request_data, sampler_data):
        pass

    @allure.step('断言信息')
    def assert_step(self, assertion_name, assertion_result):
        assert False

    @allure.step('文件信息:{thread}')
    def file_step(self, thread):
        pass

    @allure.step('返回信息')
    def response_step(self, status_code, status_message, response_data):
        pass

    @allure.step('附件(全部信息)')
    def attach_all(self, data):
        allure.attach(str(data), name='attach_all_data',
                      attachment_type=allure.attachment_type.JSON)

    def base_step(self, time, date, status, title, status_code, status_message, thread, assertion_name,
                  assertion_result, response_data,
                  sampler_data, request_data, request_header,
                  request_url):
        data = {'title': title, 'thread': thread, 'request_url': request_url, 'request_header': request_header,
                'request_data': request_data, 'sampler_data': sampler_data, 'status_code': status_code,
                'response_data': response_data, 'assertion_name': assertion_name, 'assertion_resul': assertion_result}
        self.file_step(thread)
        self.title_step(title)
        self.request_step(request_url, request_header, request_data, sampler_data)
        self.response_step(status_code, status_message, response_data)
        self.attach_all(data)
        if status == 'false':
            self.assert_step(assertion_name, assertion_result)
            assert False
        else:
            assert True

    @allure.title("{title}")
    @allure.feature("失败信息")
    @pytest.mark.parametrize(
        "time,date,status,story,title,status_code,status_message,thread,assertion_name,assertion_result,response_data,sampler_data,request_data,request_header,"
        "request_url",
        xml_2_data(type=1))
    def test_gjw(self, time, date, status, story, title, status_code, status_message, thread, assertion_name,
                    assertion_result,
                    response_data, sampler_data, request_data, request_header,
                    request_url):
        # allure.dynamic.story(story)
        self.base_step(time, date, status, title, status_code, status_message, thread, assertion_name, assertion_result,
                       response_data,
                       sampler_data, request_data, request_header,
                       request_url)

处理报告转化时间一致

def report_edit(env):
    path = os.path.join(Path().get_report_path(), env, 'data')
    # 批量更新聚合文件
    for file in os.listdir(path):
        if '.json' in file and 'categories' not in file:
            try:
                with open(os.path.join(path, file), 'r') as f:
                    json_str = json.loads(f.read())
                    for data in json_str['children'][0]['children']:
                        name = data['name']
                        for meta in result:
                            if name == meta[3]:
                                data['time']['start'] = int(meta[1])
                                data['time']['stop'] = int(meta[1]) + int(meta[0])
                                data['time']['duration'] = int(meta[0])
                    with open(os.path.join(path, file), 'w') as w:
                        json.dump(json_str, w, indent=2, sort_keys=True, ensure_ascii=False)
            except Exception as e:
                print(e)
    # 批量更新case文件
    cases_path = os.path.join(path, 'test-cases')
    for file in os.listdir(cases_path):
        if '.json' in file and 'categories' not in file:
            try:
                with open(os.path.join(cases_path, file), 'r') as f:
                    json_str = json.loads(f.read())
                    name = json_str['name']
                    for meta in result:
                        if name == meta[3]:
                            json_str['time']['start'] = int(meta[1])
                            json_str['time']['stop'] = int(meta[1]) + int(meta[0])
                            json_str['time']['duration'] = int(meta[0])
                    with open(os.path.join(cases_path, file), 'w') as w:
                        json.dump(json_str, w, indent=2, sort_keys=True, ensure_ascii=False)
            except Exception as e:
                print(e)

上述只是部分代码,完整代码已上传 ,有兴趣的可以再完善。


最后我这里给你们分享一下我所积累和真理的文档和学习资料有需要是领取就可以了

以上内容,对于软件测试的朋友来说应该是最全面最完整的备战仓库了,为了更好地整理每个模块,我也参考了很多网上的优质博文和项目,力求不漏掉每一个知识点,很多朋友靠着这些内容进行复习,拿到了BATJ等大厂的offer,这个仓库也已经帮助了很多的软件测试的学习者,希望也能帮助到你。

关注下方我的微信公众号免费领取!↓ ↓ ↓ ↓ ↓

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

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

相关文章

van-list 下拉刷新 触底分页 触底分页事件只加载一次

我是 头部是筛选的条件,,更换不同的状态,显示不同的列表数据,比如 审批中数据是 对的,触底分页也是对的,如果我切换一个状态的话,总共是 15条数据,但是 切换了状态只显示第一页的数据…

Java“牵手”拼多多商品详情数据,拼多多商品详情接口,拼多多API接口申请指南

拼多多商品详情API接口的作用是获取拼多多平台上某个商品的详细信息,包括商品标题、价格、图片、规格、参数、店铺信息等。 开发者可以通过该接口获取到商品的原始数据,方便进行数据分析、价格比较、爬取等操作。通过该接口获取到的商品详情数据可以结合…

(2023|ICLR,)用于一般噪声反演问题的扩散后验采样

Diffusion posterior sampling for general noisy inverse problems 公众号:EDPJ(添加 VX:CV_EDPJ 进交流群获取资料) 目录 0. 摘要 1. 简介 2. 背景 2.1 基于分数的扩散模型 2.2 用扩散模型求解逆问题 3. 扩散后验采样…

接口优化1

接口优化 文章目录 接口优化1. 内容概述2. 集成RabbitMQ2.1 下载2.2 SpringBoot集成RabbitMQ 快速入门1.相关配置2.创建发送者者和接收者 2.3 rabbitmq四种交换模式2.4 秒杀接口优化 1. 内容概述 核心思路:减少对数据库的访问,利用Redis的高并发特性来实现。 系统初…

20.Xaml GroupBox控件 ---->带标题的内容控件

1.运行效果 2.运行源码 a.Xaml源码 <Window x:Class="testView.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.mic…

【excel加密】excel工作表保护和工作簿保护,有什么区别?

Excel不能编辑大家都知道时设置了工作表保护&#xff0c;在我们平时设置或取消工作表保护的时候也能够看到旁边的工作簿保护&#xff0c;那它的作用是什么呢&#xff1f;今天我们来看一下&#xff0c;工作表保护和工作簿保护的区别是什么吧&#xff01; 先统一讲一下如何设置保…

蓝色光标发布营销行业模型“Blue AI” 人机协同重构产业新格局

“Blue AI 行业模型的发布&#xff0c;标志着蓝色光标Al战略迈入新阶段”。蓝色光标集团CEO潘飞在发布会现场表示&#xff0c;把握好AI机会&#xff0c;会让蓝色光标更加接近于一家全球化的科技公司。今后&#xff0c;我们将继续沿着三个方面迭代与迈进&#xff1a;一是生产效率…

如何在多版本C#工程上添加程序集

给出工程配置文件添加程序集示例&#xff1a; <ItemGroup Condition"$(TargetFramework) net451"> <PackageReference Include"MySql.Data" Version"6.7.9" /> <Reference Include"System.Configuration" /&…

台式电脑组装爬坑之路

台式电脑十大部件 CPU 主板 内存 硬盘 机箱 电源 显卡 CPU散热器 显示器 鼠标 键盘 基本知识

Java面试笔试acm版输入

首先区分scanner.nextInt()//输入一个整数&#xff0c;只能读取一个数&#xff0c;空格就停止。 scanner.next()//输入字符串&#xff0c;只能读取一个字符串&#xff0c;空格就停止&#xff0c;但是逗号不停止。 scanner.nextLine() 读取一行&#xff0c;换行停止&#xff0c…

视频可以裁剪画面大小吗?教你几种简单裁切方法

视频可以裁剪画面大小吗&#xff1f;现在人们拍摄的视频越来越多&#xff0c;因此&#xff0c;视频编辑已成为一项必要的技能。视频裁剪是视频编辑中最基本的操作之一&#xff0c;它可以帮助你删除不需要的内容、调整画面大小和焦点&#xff0c;以及改善视频的视觉效果。那么视…

【uniapp】使用canvas组件编译到微信小程序兼容出错问题

使用uniapp编译跨平台项目会遇到不少兼容问题&#xff0c;这里主要讲canvas组件的&#xff0c;编译到微信小程序会有兼容出错问题&#xff0c;这里给讲一下解决方案&#xff0c;希望有帮助。 常见问题 draw无法绘制图形 如果使用CanvasContext绘制&#xff0c;以下代码&…

profinet是什么?

profinet是什么&#xff1f; 参考&#xff1a;一文读懂Profibus、Profinet、Ethernet的区别 PROFINETPROFIbusetherNET&#xff0c;把Profibus的主从结构移植到以太网上&#xff0c;所以profinet会有Controller和Device&#xff0c;他们的关系可以简单的对应于profibus的Maste…

动态 import

文章目录 动态 import1. 动态导入2. 语法3. 描述4. 模块命名空间对象5. 使用示例6. 动态导入的原理7. 兼容 动态 import import() 语法&#xff0c;通常称为动态导入&#xff0c;是一种类似函数的表达式&#xff0c;允许将 ECMAScript 模块异步和动态地加载到可能的非模块环境…

【python自动化应用】借助ChatGPT与Python轻松实现办公自动化 —— AIC松鼠活动第九期

背景&#xff1a;当今的工作环境中&#xff0c;高效和快速地完成日常任务对于个人和机构都至关重要。许多人正在利用Python自动化来提高他们的工作效率。Python自动化可以帮助您自动完成繁琐的、重复的、容易出错的任务&#xff0c;从而节省时间和精力。 Python自动化有很多应用…

《徐亦达机器学习:Kalman Filter 卡尔曼滤波笔记 (一)》

P ( x t P(x_t P(xt​| x t − 1 ) x_{t-1}) xt−1​) P ( y t P(y_t P(yt​| x t ) x_t) xt​) P ( x 1 ) P(x_1) P(x1​)Discrete State DM A X t − 1 , X t A_{X_{t-1},X_t} AXt−1​,Xt​​Any π \pi πLinear Gassian Kalman DM N ( A X t − 1 B , Q ) N(AX_{t-1}B,Q)…

Golang gin Cookie的使用

Cookie介绍 HTTP是无状态协议&#xff0c;服务器不能记录浏览器的访问状态&#xff0c;也就是说服务器不能区分两次请求是否由同一个客户端发出Cookie就是解决HTTP协议无状态的方案之一&#xff0c;中文是小甜饼的意思Cookie实际上就是服务器保存在浏览器上的一段信息。浏览器有…

AI绘画:StableDiffusion实操教程-斗破苍穹-云韵-婚服(附高清图下载)

大家好&#xff0c;我是小梦&#xff0c;最近一直研究AI绘画。 不久前&#xff0c;我与大家分享了StableDiffusion的全面教程&#xff1a;“AI绘画&#xff1a;Stable Diffusion 终极宝典&#xff1a;从入门到精通 ” 然而&#xff0c;仍有些读者提出&#xff0c;虽然他们已经…

nVisual光纤资源管理软件,亮相第24届光博会

第24届中国国际光电博览会&#xff08;CIOE&#xff09;于9月6日至8日在深圳国际会展中心盛大开幕。作为行业领先的网络基础设施管理软件供应商&#xff0c;耐威迪携nVisual光纤资源管理软件亮相9号馆C001、C002展位&#xff0c;全方位展示室外网络基础设施管理、光纤资源管理、…

【数据结构】堆的创建

文章目录 一、堆的概念及结构1、什么是堆2、堆的性质3、堆的结构及分类 二、堆的创建1、堆向下调整算法2、堆向上调整算法3、堆的创建 一、堆的概念及结构 1、什么是堆 堆就是以二叉树的顺序存储方式来存储元素&#xff0c;同时又要满足父亲结点存储数据都要大于儿子结点存储数…