pytest简易教程汇总,详见

简介

上一篇我们已经生成了allure报告,但是可读性不是很强,

所以我们还需要对报告优化,也就是通过allure提供的装饰器添或者代码方式加一些描述信息。

官方示例:https://github.com/allure-examples/allure-examples

 

常用装饰器

pytest简易教程(36):pytest + allure最佳实践_sed

 

说明:

  • feature和story类似于父子关系
  • 如果不加 @allure.feature、@allure.story,在Behaviors下测试用例就不会分类显示
  • 如果没有添加 @allure.title() ,测试用例的标题默认就是函数名

 

添加方式及常用格式

方式一:装饰器

放在测试用例上,也就是测试方法上

@allure.epic("项目")
@allure.feature("模块")
@allure.story("子模块")
@allure.title("标题")
@allure.severity(allure.severity_level.CRITICAL)
@allure.description("描述")

 

优点:可以指定feature、story、severity运行,--allure-features="xxx" --alure-stories="xxx","yyy" --allure-severities blocker,critical,normal

pytest简易教程(36):pytest + allure最佳实践_优先级_02

 

不足:每个用例分别添加描述信息比较繁琐

 

补充:severity_level的值是枚举

pytest简易教程(36):pytest + allure最佳实践_sed_03

 

方式二:代码(推荐)

放在测试用例下,也就是测试方法下

allure.dynamic.epic("项目")
allure.dynamic.feature("模块")
allure.dynamic.story("子模块")
allure.dynamic.title("标题")
allure.dynamic.severity("优先级")
allure.dynamic.description("描述")

 

优点:描述信息实现参数化

不足:不能指定feature、story、severity运行

 

实际工作中,如果用到参数化,描述信息可以放到参数化数据中,这样就可以用方式二读取测试数据动态生成描述信息。

报告添加severity(装饰器方式)

应用场景:想要根据优先级执行用例,可以通过allure.severity来添加标记

示例代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : 韧

import allure


# 没有指定,默认是normal
@allure.feature("模块1")
@allure.story("m1子模块1")
def test_no_severity():
    pass


@allure.feature("模块2")
@allure.story("m2子模块1")
@allure.severity(allure.severity_level.TRIVIAL)
def test_trivial_severity():
    pass

@allure.feature("模块3")
@allure.story("m3子模块1")
@allure.severity(allure.severity_level.NORMAL)
def test_normal_severity():
    pass

@allure.feature("模块4")
@allure.story("m4子模块1")
@allure.severity(allure.severity_level.NORMAL)
class TestCase:
    def test_inclass_normal_severity(self):
        pass

    # 优先级就近原则
    @allure.severity(allure.severity_level.CRITICAL)
    def test_inclass_critical_severity(self):
        pass

  

指定单个优先级执行

pytest简易教程(36):pytest + allure最佳实践_优先级_04

 

指定多个优先级执行

pytest简易教程(36):pytest + allure最佳实践_测试用例_05

 

指定单个模块执行

pytest简易教程(36):pytest + allure最佳实践_测试用例_06

 

指定模块和优先级执行,结果是并集,不是交集

pytest简易教程(36):pytest + allure最佳实践_sed_07

 

同时指定模块和子模块执行,结果是并集,不是交集

pytest case\test_qzcsbj6.py -vs --alluredir=./result --clean-alluredir --allure-features=模块4 --allure-stories=m3子模块1

pytest简易教程(36):pytest + allure最佳实践_sed_08

 

报告添加epic、feature、story、title、severity、description(代码方式)

应用场景:在Behaviors下测试用例分类显示,在用例详情中显示severity和description

比如接口自动化中

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : 韧

import allure
import pytest

data = [
    {
        "epic":"全栈测试笔记",
        "feature":"用户模块",
        "story":"用户注册",
        "title":"用户注册成功",
        "description":"desc - 用户注册成功",
        "severity":"critical",
        "request":{
            "url":"/qzcsbj/user/register",
            "method":"post",
            "headers": {'Content-Type': 'application/json'},
            "params":{"uname":"qzcsbj","pwd":"123456"}
        }
    },
    {
        "epic": "全栈测试笔记",
        "feature": "用户模块",
        "story": "用户注册",
        "title": "用户注册失败",
        "description": "desc - 用户注册失败",
        "severity":"critical",
        "request": {
            "url": "/qzcsbj/user/register",
            "method": "post",
            "headers": {'Content-Type': 'application/json'},
            "params": {"uname": "ren", "pwd": "666666"}
        }
    },
    {
        "epic": "全栈测试笔记",
        "feature": "订单模块",
        "story": "查询订单",
        "title": "查询订单成功",
        "description": "desc - 查询订单成功",
        "severity":"normal",
        "request": {
            "url": "/qzcsbj/order/search",
            "method": "post",
            "headers": {'Content-Type': 'application/json'},
            "params": {"product": "thinkpad"}
        }
    }
]
@pytest.mark.parametrize('casedata',data)
class TestCase:
    def test_case(self, casedata):
        allure.dynamic.epic(casedata["epic"])
        allure.dynamic.feature(casedata["feature"])
        allure.dynamic.story(casedata["story"])
        allure.dynamic.title(casedata["title"])
        allure.dynamic.severity(casedata["severity"])
        allure.dynamic.description(casedata["description"])        
        print(f"---测试数据是:{casedata['request']}")
        assert 1==1

  

运行结果:

pytest简易教程(36):pytest + allure最佳实践_sed_09

 

生成测试报告

pytest简易教程(36):pytest + allure最佳实践_优先级_10

 

打开报告

pytest简易教程(36):pytest + allure最佳实践_优先级_11

 

pytest简易教程(36):pytest + allure最佳实践_优先级_12

 

pytest简易教程(36):pytest + allure最佳实践_优先级_13

 

 

报告添加step

应用场景:ui自动化测试中,测试过程中的每个步骤可以通过step来描述,通过with allure.step():放在测试用例方法里面,测试步骤的代码需要被该语句包含

如果中间某个步骤失败,后面步骤不会执行

示例代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : 韧

import allure

@allure.epic("全栈测试笔记")
@allure.feature("用户模块")
@allure.story("注册")
class TestRigister:
    @allure.title("注册成功")
    @allure.severity("critical")
    @allure.description("desc - 注册成功")
    def test_reg_success(self):
        with allure.step("步骤1:打开注册页面"):
            print("打开注册页面")
        with allure.step("步骤2:输入注册信息"):
            print("输入注册信息")
        with allure.step("步骤3:提交注册,注册成功"):
            print("提交注册,注册成功")
            assert 1==1
    @allure.title("注册失败")
    @allure.severity("critical")
    @allure.description("desc - 注册失败")
    def test_reg_fail(self):
        with allure.step("步骤1:打开注册页面"):
            print("打开注册页面")
        with allure.step("步骤2:输入注册信息"):
            print("输入注册信息")
        with allure.step("步骤3:提交注册,注册失败"):
            print("提交注册,注册失败")
            assert 1==2

  

执行:

pytest简易教程(36):pytest + allure最佳实践_测试用例_14

 

生成最终报告:

pytest简易教程(36):pytest + allure最佳实践_sed_15

 

打开报告:

pytest简易教程(36):pytest + allure最佳实践_sed_16

 

pytest简易教程(36):pytest + allure最佳实践_测试用例_17

 

pytest简易教程(36):pytest + allure最佳实践_测试用例_18

 

pytest简易教程(36):pytest + allure最佳实践_优先级_19

 

pytest简易教程(36):pytest + allure最佳实践_sed_20

 

pytest简易教程(36):pytest + allure最佳实践_测试用例_21

 

右侧多了Test body

pytest简易教程(36):pytest + allure最佳实践_测试用例_22

 

pytest简易教程(36):pytest + allure最佳实践_优先级_23

 

pytest简易教程(36):pytest + allure最佳实践_测试用例_24

 

报告添加link、issue、testcase

应用场景:

allure报告中想快速跳转到公司其它测试系统(比如:bug管理系统、用例管理系统),可以将allure报告和测试系统集成,在测试报告中添加bug、用例等相关链接即可

 

源码:本质上,调用的都是link

def link(url, link_type=LinkType.LINK, name=None):
    return safely(plugin_manager.hook.decorate_as_link(url=url, link_type=link_type, name=name))


def issue(url, name=None):
    return link(url, link_type=LinkType.ISSUE, name=name)


def testcase(url, name=None):
    return link(url, link_type=LinkType.TEST_CASE, name=name)

 

指定link的参数

pytest简易教程(36):pytest + allure最佳实践_测试用例_25

Link_Type对应源码LinkType,是枚举

pytest简易教程(36):pytest + allure最佳实践_测试用例_26

 

演示代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : 韧

import allure


TEST_CASE_LINK = ''
@allure.link("")
def test_link():
    pass

@allure.link("", name="全栈测试笔记")
def test_named_link():
    pass

@allure.issue("16", "bug地址")
def test_testcase_link():
    pass
@allure.testcase(TEST_CASE_LINK, "测试用例管理平台地址")
def test_issue_link():
    pass

 

运行:这里LinkType的值是issue,表示bug地址

pytest case\test_qzcsbj6.py -s -q --alluredir=./result --clean-alluredir --allure-link
-pattern=issue:{}

pytest简易教程(36):pytest + allure最佳实践_sed_27

 

pytest简易教程(36):pytest + allure最佳实践_优先级_28

 

pytest简易教程(36):pytest + allure最佳实践_测试用例_29

 

pytest简易教程(36):pytest + allure最佳实践_优先级_30

 

pytest简易教程(36):pytest + allure最佳实践_测试用例_31

 

pytest简易教程(36):pytest + allure最佳实践_sed_32

 

pytest简易教程(36):pytest + allure最佳实践_sed_33

 

pytest简易教程(36):pytest + allure最佳实践_优先级_34

 

跳转的地址

pytest简易教程(36):pytest + allure最佳实践_sed_35

 

pytest简易教程(36):pytest + allure最佳实践_sed_36

 

pytest简易教程(36):pytest + allure最佳实践_sed_37

 

pytest简易教程(36):pytest + allure最佳实践_sed_38

 

 

pytest简易教程(36):pytest + allure最佳实践_优先级_39

 

优先级默认是normal

pytest简易教程(36):pytest + allure最佳实践_sed_40

 

pytest简易教程(36):pytest + allure最佳实践_优先级_41

 

报告添加attach

应用场景:如果想在报告中看到测试用例的详细内容展示,可以在用例中添加附件(ui自动化测试中常用),可以是图片、视频、网页、文本等。

源码:

pytest简易教程(36):pytest + allure最佳实践_优先级_42

 

allure.attach(),用于传文本

  • body:文本内容
  • name:展示名称
  • attachment_type:类型
  • extension:扩展名

allure.attach.file(),用于传附件

  • source:附件源路径
  • name:展示名称
  • attachment_type:类型
  • extension:扩展名

支持的类型

class AttachmentType(Enum):

    def __init__(self, mime_type, extension):
        self.mime_type = mime_type
        self.extension = extension

    TEXT = ("text/plain", "txt")
    CSV = ("text/csv", "csv")
    TSV = ("text/tab-separated-values", "tsv")
    URI_LIST = ("text/uri-list", "uri")

    HTML = ("text/html", "html")
    XML = ("application/xml", "xml")
    JSON = ("application/json", "json")
    YAML = ("application/yaml", "yaml")
    PCAP = ("application/vnd.tcpdump.pcap", "pcap")

    PNG = ("image/png", "png")
    JPG = ("image/jpg", "jpg")
    SVG = ("image/svg-xml", "svg")
    GIF = ("image/gif", "gif")
    BMP = ("image/bmp", "bmp")
    TIFF = ("image/tiff", "tiff")

    MP4 = ("video/mp4", "mp4")
    OGG = ("video/ogg", "ogg")
    WEBM = ("video/webm", "webm")

    PDF = ("application/pdf", "pdf")

  

示例代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : 韧

import allure


@allure.epic("全栈测试笔记")
@allure.feature("用户模块")
@allure.story("注册")
class TestRigister:
    # @allure.title("注册成功")
    # @allure.severity("critical")
    # @allure.description("desc - 注册成功")
    # def test_reg_success(self):
    #     with allure.step("步骤1:打开注册页面"):
    #         print("打开注册页面")
    #     with allure.step("步骤2:输入注册信息"):
    #         print("输入注册信息")
    #     with allure.step("步骤3:提交注册,注册成功"):
    #         print("提交注册,注册成功")
    #         assert 1 == 1

    @allure.title("注册失败")
    @allure.severity("critical")
    @allure.description("desc - 注册失败")
    def test_reg_fail(self):
        with allure.step("步骤1:打开注册页面"):
            print("打开注册页面")
            allure.attach("文本信息",
                          name="文本",
                          attachment_type=allure.attachment_type.TEXT)
        with allure.step("步骤2:输入注册信息"):
            print("输入注册信息")
            allure.attach('<div class="wx"><img src="https://s2.51cto.com/images/blog/202403/02021924_65e21c2c6abfa46241.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=" alt="微信:ren168632201"></div>',
                          name="html",
                          attachment_type=allure.attachment_type.HTML)
        with allure.step("步骤3:提交注册,注册失败"):
            print("提交注册,注册失败")
            allure.attach.file("D:\wx.png",
                               name="这是图片",
                               attachment_type=allure.attachment_type.JPG,
                               extension="jpg")
            assert 1 == 1

 

图片在D盘

pytest简易教程(36):pytest + allure最佳实践_sed_43

 

运行

pytest简易教程(36):pytest + allure最佳实践_测试用例_44

 

生成并打开报告

pytest简易教程(36):pytest + allure最佳实践_测试用例_45

 

结果:右侧步骤可以看到添加的文本、html、图片

pytest简易教程(36):pytest + allure最佳实践_测试用例_46

 

思考题

动态添加描述信息,比如feature、story等,

allure.dynamic.feature("模块")
allure.dynamic.story("子模块")

如果实现指定feature、story运行测试用例?

比如:

  pytest  -s -q --alluredir=./result --clean-alluredir --allure-features=用户模块 --allure-stories=登录

  pytest  -s -q --alluredir=./result --clean-alluredir --allure-stories=登录

  pytest  -s -q --alluredir=./result --clean-alluredir --allure-severities=normal,critical

 

【bak】

 

> > > > > > 下一系列自动化测试框架开发(python + pytest + requests + allure + jsonpath + pyyaml)

 

__EOF__

本文作者:持之以恒(韧)