Allure:根据step动态设置description

2644 篇文章 26 订阅
2634 篇文章 14 订阅

背景

使用pytest+Allure进行自动化的时候,为了报告展示更明确会使用

with allure.step(xxx)

@allure.step(xxx)

测试结束后就可以看到

测试步骤

Allure还支持配置Description

之前直接在case中编写,例如

"""
[用例描述]: 专家问诊
[前置步骤]:
    1. 打开h5页面
    2. 完成登录
[测试步骤]:
    1. 点击问诊后搜索 测试医生数据
    2. 点击图文/电话/视频类型问诊
    3. 输入病情描述,选择患者
    4. 跳转至支付页面
    5. 取消订单
[编写人员]: zhongxin
"""

优点

  1. 内容清晰,由人工编写与确认

缺点

  1. 更新脚本后可能忘记同步更新

  2. 没有具体到每一步操作

新方案

新的方案采用读取执行过程中记录的step数据来展示Description

优点

  1. 根据脚本实时更新

  2. 具体到每一步的详细操作

缺点

  1. 具体程度需要根据allure.step的编写情况决定

  2. 执行失败后的步骤不会记录

  3. 不能记录后置操作

效果

 

效果

具体编码

在使用allure.step()的时候

使用的是

def __enter__(self):
    plugin_manager.hook.start_step(uuid=self.uuid, title=self.title, params=self.params)

其中start_step

    @allure_commons.hookimpl
    def start_step(self, uuid, title, params):
        parameters = [Parameter(name=name, value=value) for name, value in params.items()]
        step = TestStepResult(name=title, start=now(), parameters=parameters)
        self.allure_logger.start_step(None, uuid, step)
    def start_step(self, parent_uuid, uuid, step):
        parent_uuid = parent_uuid if parent_uuid else self._last_executable()
        if parent_uuid is None:
            self._orphan_items.append(uuid)
        else:
            self._items[parent_uuid].steps.append(step)
            self._items[uuid] = step

所以最终每个步骤都被存到了self._items里面

self._items = ThreadContextItems()

找到allure_commons.reporter.ThreadContextItems

conftest.py中编写一个函数来获取这个内容

import allure_commons

allure_commons.reporter.ThreadContextItems._thread_context.items()

然后将里面的内容解析出来

@pytest.fixture(autouse=True)
def case_end():
    yield

    for k, v in allure_commons.reporter.ThreadContextItems._thread_context.items():
        for k1, v1 in v.items():
            befores = hasattr(v1, 'befores') and getattr(v1, 'befores') or []
            steps = hasattr(v1, 'steps') and getattr(v1, 'steps') or []
            for i in befores:
                get_steps(i, base_name='前置', exclude=["_session_faker"])
            for i in steps:
                get_steps(i, base_name='\tcase')
  1. @pytest.fixture(autouse=True):每次case执行前后自动执行

  2. 第一行就是yield说明函数后面都是后置操作,在case执行结束之后才会去收集step信息

编写get_steps

因为step里面有嵌套,所以使用嵌套函数去逐步解析步骤内容

    global names
    description = []
    names = []

    def get_steps(data, base_name, exclude=None):
        if exclude is None:
            exclude = []
        global names
        name = getattr(data, 'name')
        steps = getattr(data, 'steps')
        if name and name not in exclude:
            names.append(name)
        if not steps and name:
            names_text = ""
            for index, j in enumerate(names):
                if index == 0:
                    names_text += f"<strong>{j}</strong>"
                else:
                    if index == 1:
                        names_text += "<ol>"
                    names_text += f"<li>{j}</li>"
                    if index == len(names) - 1:
                        names_text += "</ol>"
            if names_text:
                description.append(f"<p>「{base_name}」{names_text}</p>")
            names = []
            return
        if steps:
            if steps:
                for i in steps:
                    get_steps(i, base_name, exclude)

动态设置description

因为拿到的内容有很多重复,所以使用set进行去重,然后根据原列表的排序方式进行排序

    description_set = list(set(description))
    description_set.sort(key=description.index)
    description_text = "".join(description_set)
    description_text = f'<div style="line-height: 16px;font-size: 16px">{description_text}</div>'
    description = []
    allure.dynamic.description_html(description_text)

完整代码

@pytest.fixture(autouse=True)
def case_end():
    yield
    global names
    description = []
    names = []

    def get_steps(data, base_name, exclude=None):
        if exclude is None:
            exclude = []
        global names
        name = getattr(data, 'name')
        steps = getattr(data, 'steps')
        if name and name not in exclude:
            names.append(name)
        if not steps and name:
            names_text = ""
            for index, j in enumerate(names):
                if index == 0:
                    names_text += f"<strong>{j}</strong>"
                else:
                    if index == 1:
                        names_text += "<ol>"
                    names_text += f"<li>{j}</li>"
                    if index == len(names) - 1:
                        names_text += "</ol>"
            if names_text:
                description.append(f"<p>「{base_name}」{names_text}</p>")
            names = []
            return
        if steps:
            if steps:
                for i in steps:
                    get_steps(i, base_name, exclude)

    for k, v in allure_commons.reporter.ThreadContextItems._thread_context.items():
        for k1, v1 in v.items():
            befores = hasattr(v1, 'befores') and getattr(v1, 'befores') or []
            steps = hasattr(v1, 'steps') and getattr(v1, 'steps') or []
            for i in befores:
                get_steps(i, base_name='前置', exclude=["_session_faker"])
            for i in steps:
                get_steps(i, base_name='\tcase')

    description_set = list(set(description))
    description_set.sort(key=description.index)
    description_text = "".join(description_set)
    description_text = f'<div style="line-height: 16px;font-size: 16px">{description_text}</div>'
    description = []
    print(description_text)
    allure.dynamic.description_html(description_text)

资源分享

下方这份完整的软件测试视频学习教程已经上传CSDN官方认证的二维码,朋友们如果需要可以自行免费领取 【保证100%免费】

在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值