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


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

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

    在这里插入图片描述

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

    在这里插入图片描述

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

    在这里插入图片描述

    接下来来看下实现过程。

    安装allure

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

    jmeter配置

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

    1. # This section helps determine how result data will be saved.
    2. # The commented out values are the defaults.
    3. # legitimate values: xml, csv, db. Only xml and csv are currently supported.
    4. jmeter.save.saveservice.output_format=xml
    5. # The below properties are true when field should be saved; false otherwise
    6. #
    7. # assertion_results_failure_message only affects CSV output
    8. #jmeter.save.saveservice.assertion_results_failure_message=true
    9. #
    10. # legitimate values: none, first, all
    11. #jmeter.save.saveservice.assertion_results=none
    12. #
    13. jmeter.save.saveservice.data_type=true
    14. jmeter.save.saveservice.label=true
    15. jmeter.save.saveservice.response_code=true
    16. # response_data is not currently supported for CSV output
    17. jmeter.save.saveservice.response_data=true
    18. # Save ResponseData for failed samples
    19. jmeter.save.saveservice.response_data.on_error=true
    20. jmeter.save.saveservice.response_message=true
    21. jmeter.save.saveservice.successful=true
    22. jmeter.save.saveservice.thread_name=true
    23. jmeter.save.saveservice.time=true
    24. jmeter.save.saveservice.subresults=true
    25. jmeter.save.saveservice.assertions=true
    26. jmeter.save.saveservice.latency=true
    27. # Only available with HttpClient4
    28. jmeter.save.saveservice.connect_time=true
    29. jmeter.save.saveservice.samplerData=true
    30. jmeter.save.saveservice.responseHeaders=true
    31. jmeter.save.saveservice.requestHeaders=true
    32. jmeter.save.saveservice.encoding=true
    33. jmeter.save.saveservice.bytes=true
    34. # Only available with HttpClient4
    35. jmeter.save.saveservice.sent_bytes=true
    36. jmeter.save.saveservice.url=true
    37. jmeter.save.saveservice.filename=true
    38. jmeter.save.saveservice.hostname=true
    39. jmeter.save.saveservice.thread_counts=true
    40. jmeter.save.saveservice.sample_count=true
    41. jmeter.save.saveservice.idle_time=true
    42. # Timestamp format - this only affects CSV output files
    43. # legitimate values: none, ms, or a format suitable for SimpleDateFormat
    44. jmeter.save.saveservice.timestamp_format=ms
    45. 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文件内容如下:

    在这里插入图片描述

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

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

    代码实现

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

    1. try:
    2. converte_data = xmltodict.parse(result_file, encoding='utf-8')
    3. sample_keys = list(converte_data['testResults'].keys())
    4. result = []
    5. ws_result = []
    6. sample_result = converte_data['testResults']['httpSample'] if isinstance(
    7. converte_data['testResults']['httpSample'],
    8. list) else [converte_data['testResults']['httpSample']]
    9. if 'sample' in sample_keys:
    10. ws_result = converte_data['testResults']['sample'] if isinstance(converte_data['testResults']['sample'],
    11. list) else [
    12. converte_data['testResults']['sample']]
    13. result_data = sample_result + ws_result
    14. for data in result_data:
    15. time = data['@t'] if '@t' in data else ''
    16. date = data['@ts'] if '@ts' in data else ''
    17. status = data['@s'] if '@s' in data else ''
    18. title = data['@lb'] if '@lb' in data else ''
    19. status_code = data['@rc'] if '@rc' in data else ''
    20. status_message = data['@rm'] if '@rm' in data else ''
    21. thread = data['@tn'] if '@tn' in data else ''
    22. assertion = data['assertionResult'] if 'assertionResult' in data else ''
    23. response_data = data['responseData']['#text'] if 'responseData' in data and '#text' in data['responseData'] \
    24. else ''
    25. sampler_data = data['samplerData']['#text'] if 'samplerData' in data and '#text' in data['samplerData'] \
    26. else ''
    27. request_data = data['queryString']['#text'] if 'queryString' in data and '#text' in data[
    28. 'queryString'] else ''
    29. request_header = data['requestHeader']['#text'] if 'requestHeader' in data and '#text' in data[
    30. 'requestHeader'] else ''
    31. request_url = data['java.net.URL'] if 'java.net.URL' in data else ''
    32. story = '未标记'
    33. assertion_name, assertion_result = None, None
    34. if status == 'false':
    35. assertion_name, assertion_result = get_assertion(assertion)
    36. meta_data = (
    37. time, date, status, story, title, status_code, status_message, thread, assertion_name, assertion_result,
    38. response_data
    39. , sampler_data, request_data, request_header, request_url)
    40. result.append(meta_data)
    41. return result
    42. except Exception as e:
    43. print(e)
    44. return [
    45. ('time', 'date', 'true', 'story', 'title', 'status_code', 'status_message', 'thread', 'assertion_name',
    46. 'assertion_result',
    47. 'response_data', 'sampler_data', 'request_data', 'request_header', 'request_url')]

    用例详情字段

    1. @allure.step('用例名称:{title}')
    2. def title_step(self, title):
    3. pass
    4. @allure.step('请求信息')
    5. def request_step(self, request_url, request_header, request_data, sampler_data):
    6. pass
    7. @allure.step('断言信息')
    8. def assert_step(self, assertion_name, assertion_result):
    9. assert False
    10. @allure.step('文件信息:{thread}')
    11. def file_step(self, thread):
    12. pass
    13. @allure.step('返回信息')
    14. def response_step(self, status_code, status_message, response_data):
    15. pass
    16. @allure.step('附件(全部信息)')
    17. def attach_all(self, data):
    18. allure.attach(str(data), name='attach_all_data',
    19. attachment_type=allure.attachment_type.JSON)
    20. def base_step(self, time, date, status, title, status_code, status_message, thread, assertion_name,
    21. assertion_result, response_data,
    22. sampler_data, request_data, request_header,
    23. request_url):
    24. data = {'title': title, 'thread': thread, 'request_url': request_url, 'request_header': request_header,
    25. 'request_data': request_data, 'sampler_data': sampler_data, 'status_code': status_code,
    26. 'response_data': response_data, 'assertion_name': assertion_name, 'assertion_resul': assertion_result}
    27. self.file_step(thread)
    28. self.title_step(title)
    29. self.request_step(request_url, request_header, request_data, sampler_data)
    30. self.response_step(status_code, status_message, response_data)
    31. self.attach_all(data)
    32. if status == 'false':
    33. self.assert_step(assertion_name, assertion_result)
    34. assert False
    35. else:
    36. assert True
    37. @allure.title("{title}")
    38. @allure.feature("失败信息")
    39. @pytest.mark.parametrize(
    40. "time,date,status,story,title,status_code,status_message,thread,assertion_name,assertion_result,response_data,sampler_data,request_data,request_header,"
    41. "request_url",
    42. xml_2_data(type=1))
    43. def test_gjw(self, time, date, status, story, title, status_code, status_message, thread, assertion_name,
    44. assertion_result,
    45. response_data, sampler_data, request_data, request_header,
    46. request_url):
    47. # allure.dynamic.story(story)
    48. self.base_step(time, date, status, title, status_code, status_message, thread, assertion_name, assertion_result,
    49. response_data,
    50. sampler_data, request_data, request_header,
    51. request_url)

    处理报告转化时间一致

    1. def report_edit(env):
    2. path = os.path.join(Path().get_report_path(), env, 'data')
    3. # 批量更新聚合文件
    4. for file in os.listdir(path):
    5. if '.json' in file and 'categories' not in file:
    6. try:
    7. with open(os.path.join(path, file), 'r') as f:
    8. json_str = json.loads(f.read())
    9. for data in json_str['children'][0]['children']:
    10. name = data['name']
    11. for meta in result:
    12. if name == meta[3]:
    13. data['time']['start'] = int(meta[1])
    14. data['time']['stop'] = int(meta[1]) + int(meta[0])
    15. data['time']['duration'] = int(meta[0])
    16. with open(os.path.join(path, file), 'w') as w:
    17. json.dump(json_str, w, indent=2, sort_keys=True, ensure_ascii=False)
    18. except Exception as e:
    19. print(e)
    20. # 批量更新case文件
    21. cases_path = os.path.join(path, 'test-cases')
    22. for file in os.listdir(cases_path):
    23. if '.json' in file and 'categories' not in file:
    24. try:
    25. with open(os.path.join(cases_path, file), 'r') as f:
    26. json_str = json.loads(f.read())
    27. name = json_str['name']
    28. for meta in result:
    29. if name == meta[3]:
    30. json_str['time']['start'] = int(meta[1])
    31. json_str['time']['stop'] = int(meta[1]) + int(meta[0])
    32. json_str['time']['duration'] = int(meta[0])
    33. with open(os.path.join(cases_path, file), 'w') as w:
    34. json.dump(json_str, w, indent=2, sort_keys=True, ensure_ascii=False)
    35. except Exception as e:
    36. print(e)

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

    最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

    在这里插入图片描述

    这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!   

  • 相关阅读:
    Java项目:JSP高校新生报到迎新管理系统
    使用正则表达式分割字符串
    [LINUX]linux基本指令大总结
    十三、Mysql的存储引擎
    H5页面如何实现图片懒加载?
    蓝桥杯每日一题2023.11.6
    Spring Security(五)--管理用户
    原生微信小程序实现手写签名功能
    B3614 【模板】栈
    LIO-SAM框架:点云配准之角点面点的残差及梯度构建
  • 原文地址:https://blog.csdn.net/qq_48811377/article/details/132901754