pytest&allure分析redis的数据并动态生成testCase报告

1.pytest.mark.parametrize

pytest.mark.parametrize 是一个pytest的装饰器,它可以用于将参数传递给测试函数。使用 pytest.mark.parametrize 装饰器时,需要在装饰器中指定参数名称和参数值。对于多个参数,可以使用多个装饰器。

下面是一些使用 pytest.mark.parametrize 的示例:

第一个示例中,test_addition 测试函数将三个参数(x、y 和 expected)作为输入。参数值列表包含三个元组,每个元组都包含一组参数值。pytest将运行每个元组的所有参数值组合,并对每组参数值调用测试函数一次。

第二个示例中,test_uppercase 函数将两个参数(string 和 expected)作为输入。参数值列表包含两个元组,每个元组都包含一组参数值。pytest将运行每个元组的所有参数值组合,并对每组参数值调用测试函数一次。

python 复制代码
import pytest
 
@pytest.mark.parametrize('x, y, expected', [(1, 2, 3), (2, 3, 5), (3, 4, 7)])
def test_addition(x, y, expected):
    assert x + y == expected
 
@pytest.mark.parametrize('string, expected', [('hello world', 'HELLO WORLD'), ('goodbye', 'GOODBYE')])
def test_uppercase(string, expected):
    assert string.upper() == expected

按照上面的例子,那么读取redis的list数据赋值给变量detail,装饰器 parametrize('detail_one',detail) 这样就可以把redis的list每条数据传到case里面了。但实际调试发现,allure.title 会显示 parametrize 的参数化,把case标题挤得很不好看:

2.要考虑另一种写法,在 allure.title 不显示 parametrize 的参数化的具体长数据

python 复制代码
@allure.epic("Org-文档中心")
@allure.feature("页面跳转死链接巡检")
@pytest.mark.parametrize("index", list(range(len(detail))))
def test_read_list(index):
    detail_dict_one = ast.literal_eval(detail[index])

parametrize 的参数化不传具体的值,而是传list的元素的数量len,在case里面 detail_dict_one = ast.literal_eval(detailindex) 获取redis的list的每条数据。报告 allure.title 显示 parametrize 参数化的具体长数据的索引:

3.ast.literal_eval

ast.literal_eval() 方法将该字符串转换为字典格式,ast.literal_eval() 方法是将字符串作为 Python 表达式进行评估,如果字符串可以安全地转换为字典、列表或原始类型,则返回转换后的对象。

python代码从redis的list读取的数据是字符串,如:

python 复制代码
"{'url': 'http://**-ui.iot4-qa-group.orgapp.com/login?next=%2Frecipe', 'title': None, 'referer_url': None, 'referer_url_text': None}"

需要将这个字符串转成字典格式,以下是示例代码:

python 复制代码
import ast
 
data = "{'url': 'http://**-ui.iot4-qa-group.orgapp.com/login?next=%2Frecipe', 'title': None, 'referer_url': None, 'referer_url_text': None}"
converted_data = ast.literal_eval(data)
print(converted_data) # {'url': 'http://**-ui.iot4-qa-group.orgapp.com/login?next=%2Frecipe', 'title': None, 'referer_url': None, 'referer_url_text': None}

4.allure.dynamic

默认 allure 报告上的测试用例标题不设置就是用例名称,现在需要的是,当 pytest.mark.parametrize 使用每个参数值作为入参去调用一次测试函数就生成一条case。

allure 提供了在测试用例执行过程中动态指定标题和描述等标签的方法 ,allure.dynamic 是 Allure 测试报告框架中的一个装饰器,用于将动态生成的测试步骤和附件添加到测试报告中,例子:

python 复制代码
import allure
 
def test_devloper_docs():
    """
    测试用例1
    """
    allure.dynamic.title("动态title")
    allure.dynamic.description_html("动态description_html")
    allure.dynamic.severity("blocker")
    allure.dynamic.feature("动态feature")
    allure.dynamic.story("动态story")
    allure.dynamic.tag("动态tag")
    allure.dynamic.link("https://www.baidu.com/?wd=1", "动态link")
    allure.dynamic.issue("https://www.baidu.com/?wd=2", "动态issue")
    allure.dynamic.testcase("https://www.baidu.com/?wd=3", "动态testcase")
 
def test_demo():
    """
    测试用例2
    """
    allure.dynamic.description("动态description")

实际代码:

python 复制代码
@pytest.mark.parametrize("index", list(range(len(detail))))
def test_read_list(index):
    """
    动态设置描述
    """
    # 获取redis的list的每条数据,并把字符串"{}"的数据转成字典格式
    detail_dict_one = ast.literal_eval(detail[index])
    # 从字典获取对应字典的数据
    url = detail_dict_one.get('url')
    title = detail_dict_one.get('title').strip() if detail_dict_one.get('title') else detail_dict_one.get('title')
    referer_url = detail_dict_one.get('referer_url')
    referer_url_text = detail_dict_one.get('referer_url_text').strip() if detail_dict_one.get('referer_url_text') else detail_dict_one.get('referer_url_text')
    crawled = detail_dict_one.get('crawled')
    spider = detail_dict_one.get('spider')
    # 把url转成在allure可以直接点击访问的链接
    url_link = f"<a href={url}>{url}</a>"
    referer_url_link = f"<a href={referer_url}>{referer_url}</a>"
    # 定义一个函数html的表格,在用例描述那里展示redis的数据
    description_html = format_table(url_link, title, referer_url_link, referer_url_text, crawled, spider)
    allure.dynamic.description_html(description_html)
 
    # 把case.title进行分类,归类到不同的story下面,方便查看
    if "swagger" in url:
        allure.dynamic.story("不需校验的链接")
        allure.dynamic.title(url)
        pytest.skip("该链接为swagger-json文档,不属于校验范围")
    elif title == "该页面不存在":
        allure.dynamic.story("链接跳转后该页面不存在")
        allure.dynamic.title(url)
        assert title != "该页面不存在"
    elif referer_url_text is not None and title is None:
        allure.dynamic.story("链接跳转后该页面标题为None")
        allure.dynamic.title(url)
        assert title is not None
    else:
        allure.dynamic.story("巡检通过的链接")
        allure.dynamic.title(url)

5.description_html

在allure报告case的描述通过一个html表格展示redis读取的数据,定义一个函数 format_table,代码如下:

python 复制代码
def format_table(link, title, referer_url, referer_url_text, crawled, spider):
    # 定义HTML样式
    style = """
        <style>
            table {
                border-collapse: collapse;
                width: 100%;
            }
            td, th {
                border: 1px solid black;
                text-align: left;
                padding: 8px;
            }
            th {
                background-color: #dddddd;
            }
        </style>
    """
    # 定义表格内容
    table_content = f"""
        <table>
            <tr>
                <td>url</td>
                <td>{link}</td>
            </tr>
            <tr>
                <td>title</td>
                <td>{title}</td>
            </tr>
            <tr>
                <td>referer_url</td>
                <td>{referer_url}</td>
            </tr>
            <tr>
                <td>referer_url_text</td>
                <td>{referer_url_text}</td>
            </tr>
            <tr>
                <td>crawled</td>
                <td>{crawled}</td>
            </tr>
            <tr>
                <td>spider</td>
                <td>{spider}</td>
            </tr>
        </table>
    """
    # 将样式和表格内容拼接起来
    html = f"{style}{table_content}"
 
    # 返回HTML代码
    return html
 
# 定义一个函数html的表格,在用例描述那里展示redis的数据
description_html = format_table(url_link, title, referer_url_link, referer_url_text, crawled, spider)
allure.dynamic.description_html(description_html)

Description 表格样式:

6.完整代码

python 复制代码
# coding=utf-8
import pytest
import allure
import os
import ast
from _redis import operate_redis
 
# 使用lrange()方法从左到右检索整个列表并将其存储在名为detail的变量中
detail = operate_redis().find_redis_list("lrange","developer-docs:items")
 
@allure.epic("org-文档中心")
@allure.feature("页面跳转死链接巡检")
@pytest.mark.parametrize("index", list(range(len(detail))))
def test_read_list(index):
    """
    动态设置描述
    """
    # 获取redis的list的每条数据,并把字符串"{}"的数据转成字典格式
    detail_dict_one = ast.literal_eval(detail[index])
    # 从字典获取对应字典的数据
    url = detail_dict_one.get('url')
    title = detail_dict_one.get('title').strip() if detail_dict_one.get('title') else detail_dict_one.get('title')
    referer_url = detail_dict_one.get('referer_url')
    referer_url_text = detail_dict_one.get('referer_url_text').strip() if detail_dict_one.get('referer_url_text') else detail_dict_one.get('referer_url_text')
    crawled = detail_dict_one.get('crawled')
    spider = detail_dict_one.get('spider')
    # 把url转成在allure可以直接点击访问的链接
    url_link = f"<a href={url}>{url}</a>"
    referer_url_link = f"<a href={referer_url}>{referer_url}</a>"
    # 定义一个函数html的表格,在用例描述那里展示redis的数据
    description_html = format_table(url_link, title, referer_url_link, referer_url_text, crawled, spider)
    allure.dynamic.description_html(description_html)
 
    # 把case.title进行分类,归类到不同的story下面,方便查看
    if "swagger" in url:
        allure.dynamic.story("不需校验的链接")
        allure.dynamic.title(url)
        pytest.skip("该链接为swagger-json文档,不属于校验范围")
    elif title == "该页面不存在":
        allure.dynamic.story("链接跳转后该页面不存在")
        allure.dynamic.title(url)
        assert title != "该页面不存在"
    elif referer_url_text is not None and title is None:
        allure.dynamic.story("链接跳转后该页面标题为None")
        allure.dynamic.title(url)
        assert title is not None
    else:
        allure.dynamic.story("巡检通过的链接")
        allure.dynamic.title(url)
 
 
def format_table(link, title, referer_url, referer_url_text, crawled, spider):
    # 定义HTML样式
    style = """
        <style>
            table {
                border-collapse: collapse;
                width: 100%;
            }
            td, th {
                border: 1px solid black;
                text-align: left;
                padding: 8px;
            }
            th {
                background-color: #dddddd;
            }
        </style>
    """
    # 定义表格内容
    table_content = f"""
        <table>
            <tr>
                <td>url</td>
                <td>{link}</td>
            </tr>
            <tr>
                <td>title</td>
                <td>{title}</td>
            </tr>
            <tr>
                <td>referer_url</td>
                <td>{referer_url}</td>
            </tr>
            <tr>
                <td>referer_url_text</td>
                <td>{referer_url_text}</td>
            </tr>
            <tr>
                <td>crawled</td>
                <td>{crawled}</td>
            </tr>
            <tr>
                <td>spider</td>
                <td>{spider}</td>
            </tr>
        </table>
    """
    # 将样式和表格内容拼接起来
    html = f"{style}{table_content}"
 
    # 返回HTML代码
    return html
 
 
if __name__ == '__main__':
    # pytest.main(["-s","allure-test.py"])
    '''
    -q: 安静模式, 不输出环境信息
    -v: 丰富信息模式, 输出更详细的用例执行信息
    -s: 显示程序中的print/logging输出
    '''
    pytest.main(['-s', '-q', '--clean-alluredir', '--alluredir=docs_report/report/allure-results'])
    os.system(r"allure generate docs_report/report/allure-results/ -o docs_report/report/allure-report --clean")

7.allure装饰器方法介绍

相关推荐
阿童木写作31 分钟前
跨境电商图片翻译工具推荐:批量图片翻译+视频字幕翻译+智能抠图
python·macos·音视频·xcode
cui_ruicheng1 小时前
LangChain 应用开发(十四):Agent 上下文与记忆机制
服务器·人工智能·python·langchain
circuitsosk2 小时前
任务规划器的三种范式对比:ReAct、Plan-and-Execute 与 Tree-of-Thought 在真实业务中的取舍
前端·javascript·python·react.js·llm·ai agent
shehuiyuelaiyuehao2 小时前
算法31,前缀和,可被k整除的子数组
数据结构·python·算法
宸津-代码粉碎机2 小时前
AI攻防战升级!基于Spring AI构建Java应用自动免疫安全体系
java·大数据·开发语言·人工智能·python·安全·spring
测试19982 小时前
如何用appium搭建Android自动化测试框架?
自动化测试·软件测试·python·测试工具·职场和发展·appium·测试用例
程序员大雄学编程2 小时前
微积分46. 无穷级数四大核心性质:从理论到实践的全方位解析
python·学习·微积分·学习工具
数字化转型分享点滴3 小时前
## 工厂数字化管理系统的价值体现:构建制造全流程数据闭环
python
2301_800074214 小时前
map,list简单方法
windows·python·list
DeepVisionary5 小时前
30B 参数打平 1 万亿参数:Meta 开源 Muse Glimmer,跑分 35 对 36
python·自动化