全栈自动化第一期—Pytest+Allure实现用例与报告管理

简介: 本文主要介绍了详解Pytest+Allure搭建方法以及生成报告常用操作,实现自动化过程中对测试用例的管理以及最终生成自定义测试报告,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

Pytest+Allure实现用例管理与自定义测试报告

(一)快捷安装所需依赖

1、创建requirements.txt文件,里面填写我们项目所需的依赖

2、在Pycharm下方的Terminal栏中,输入命令pip install -r <文件名>

在这里插入图片描述

3、按回车键执行命令,即可自动下载我们项目所需要的依赖

4、然后输入pip list,即可查看我们下载的依赖是否存在,存在则说明下载成功,如果失败的话,需要重新执行命令,有可能是网络波动导致下载依赖失败。

(二)Pytest测试用例规则

1、模块名必须要以test_开头或者_test结尾

2、测试类必须以Test开头,并且不能有__init__方法

3、测试用例必须要以test_开头

(三)Pytest的运行方式


  • -n <数值>: 支持多线程或者分布试运行测试用例,大大提升运行时速度(前提是安装了pytest -xdist依赖
  • --reruns <数值>:任何用例失败后会进行重跑2次(前提是安装了pytest -rerunfailures依赖
  • -x:表示只要一个用例报错,那么测试停止
  • --maxfail=<数值> :表示出现两个用例失败就停止
  • -k: 根据测试用例的部分字符串指定测试用例,多个名称使用关键字“or”,“and”分隔
  • --html=<存放目录>: 运行完测试用例后生成测试报告(前提是安装了pytset -html

    1、主函数方式

    一般会在目录的根目录下创建一个run.py文件,用来运行所有的测试用例,这个时候符合pytest测试用例规则的就会被发现并且运行,控制台输出一个.表示运行通过。

    2、命令行方式

    在pycharm下方的terminal中,输入pytest即可运行所有的符合测试用例规则的测试用例方法[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8RRZXlYn-1661627743675)(http://colablog.top/imagepytest-9.png)]。
    (1)输入pytest运行所有测试用例

    (2)输入pytest -vs <文件名>,运行指定模块的测试用例

    (3)输入pytest -vs <目录名>,运行指定目录下的测试用例
    (4)输入pytest -vs <具体用例方法>,根据node id运行指定位置的测试用例
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IHduJ6ts-1661627743676)(http://colablog.top/imagepytest-9.png)]

    3、Pytest.ini配置文件运行

    (1)在项目根目录下创建pytest.ini文件
    (2)[pytest]用于标记该文件为pytest配置文件
    (3)addopts表示命令行参数,多个参数使用空格分隔
    (4)testpaths表示测试用例搜索范围
    (5)python_files表示修改测试用例文件命名规则
    (6)python_classes表示修改测试用例类名命名规则
    (7)python_functions表示修改测试用例方法名命名规则
    (8)markers表示对用例进行分组,可按照不同的组来执行,此操作需要给测试用例方法添加装饰器,如模块名为“smoke”,测试用例需要添加@pytest.mark.smoke来表示此用例属于该分组,addopts需要添加-m <分组名>,多个分组使用 '<分组名1> or <分组名2>',类似于-k参数
    📢ps:该文本不能存在中文字符!!!如果需要中文注释的话,需要使用Nodepad++打开,将编码格式修改为“GB2312”,在工具栏中的“编码-编码字符集-中文-GB2312”。
    示例图:


(四)常用装饰器

@pytest.mark.run(order=1)

改变测试用例执行顺序,需要安装 pytest-ordering插件。pytest默认执行顺序是从上到下,该装饰器可以修改测试用例的执行顺序,数值越小,优先级越高,有装饰器的比没有装饰器的优先级高。

@pytest.mark.skip(reason="")

@pytest.mark.skipif(<判断式>, reason="")

跳过不需要执行的测试用例,skip和skipif,skipif需要添加判断条件,如果成立则跳过该条测试用例,不成立则执行用例,skif只需要添加原因,直接不执行该条用例。

@pytest.fixture(scope="作用域",params="数据驱动",autouse="自动执行",ids="自定义参数名",name="别名")

scope参数 作用域
function 每条测试用例前后执行一次
class 每个测试类前后执行一次
module 在每个测试.py文件前后执行一次
package/session 所有包前后执行一次

1、scope

function级别:

@pytest.fixture(scope="function")
def execute_sql():
    print("········夹具前置")
    yield
    print("夹具后置········")

def test_baidu03(self, execute_sql):
    print("这是一条测试用例")
    assert 1 == 1
yield可以返回数值,并且可以在返回后继续执行后面的代码,而使用return则不可以

class级别:

@pytest.fixture(scope="class", autouse=True)
def execute_sql():
    print("········夹具前置")
    yield
    print("夹具后置········")


pytest.mark.usefixtures("execute_sql")
class TestApi:
    def test_baidu01(self):
        print("这是一条测试用例")
        assert 1 == 1
在测试类用需要添加夹具方法

module级别:

@pytest.fixture(scope="module", autouse=True)
def execute_sql():
    print("········夹具前置")
    yield
    print("夹具后置········")
每个模块(.py文件)执行前后运行一次,效果类似于setup_module,teardown_module方法

2、autouser

代码示例:

@pytest.fixture(scope="function", autouse=True)
使用autouse,会自动给所有测试用例添加夹具

3、params

def read_data():
    return ['1', '2', '3', '4']


@pytest.fixture(scope="function", params=read_data(), autouse=True)
def execute_sql(request):
    print("········夹具前置")
    yield request.param
    print("夹具后置········")

@pytest.mark.newModel
def test_baidu04(self, execute_sql):
    print(execute_sql)
    print("这是一条测试用例04")
    assert 1 == 1
定义一个返回值方法,然后传入params参数中,通过给夹具方法加上形参request(固定写法),然后通过yield返回request.param(固定写法)返回给测试用例,达到数据驱动的目的

4、ids

def read_data():
    return ['1', '2', '3', '4']

@pytest.fixture(scope="function", params=read_data(), ids=['test1', 'test2', 'test3', 'test4'], autouse=True)
def execute_sql(request):
    print("········夹具前置")
    yield request.param
    print("夹具后置········")

@pytest.mark.newModel
def test_baidu04(self, execute_sql):
    print(execute_sql)
    print("这是一条测试用例04")
    assert 1 == 1
ids需要和params参数一起使用,ids是给params参数命名,ids参数的长度需要和params参数长度一致,一一对应,此作用是在执行用例时,能清晰看到每一条参数的名字,如下图所示。

5、name

@pytest.fixture(scope="function", params=read_data(), ids=['test1', 'test2', 'test3', 'test4'], autouse=True, name="fixture")
def execute_sql(request):
    print("········夹具前置")
    yield request.param
    print("夹具后置········")

def test_baidu04(self, fixture):
    print(fixture)
    print("这是一条测试用例04")
    assert 1 == 1
⚠️name用于给夹具起别名,测试用例的参数需要使用此别名,否则报错。

@pytest.mark.parametrize(参数名, 数据)

用于修饰测试用例方法,参数名表示数据的别名,数据参数可放数组、字典、列表、元组等,使用此装饰器的测试用例方法形参中,必须添加此装饰器的参数名且一致,才能实现数据驱动。
@pytest.mark.parametrize("name, test_id", [["哈哈哈", 1], ["呵呵呵", 2], ["嘻嘻嘻", 3]])
    def test_baidu(self, name, test_id)
结合Yaml,实现数据驱动,接口自动化
def read_yaml(path):
    with open(path, mode="r", encoding="utf-8") as file:
        data = yaml.load(file, Loader=yaml.FullLoader)
        return data


@allure.epic("项目名称:若依管理系统")
@allure.feature("模块名称:登录模块")
class TestApi:
    @allure.story("登录模块")
    @allure.severity(allure.severity_level.BLOCKER)
    @pytest.mark.run(order=2)
    @pytest.mark.smoke
    @pytest.mark.parametrize("data", read_yaml("./testcases/API/data.yaml"))
    def test_baidu01(self, data):
        allure.dynamic.title(data["name"])
        allure.dynamic.description(data["description"])
        res = requests.request(method=data["request"]["method"], url=data["request"]["url"], json=data["request"]["data"])
        assert res.json()["msg"] == "操作成功"

📢PS:读取Yaml文件的路径哪个文件调用就相对于哪个文件的相对路径,因此,建议使用一个工具类进行绝对路径拼接。

(五)Pytest前后置器

1、测试用例执行之前运行

def setup(self)

2、测试用例执行之后运行

def teardown(self)

3、测试类执行之前运行

def setup_class(self)
📢ps:常用于创建数据库连接、日志对象等只需要执行一次的操作

4、测试类执行之后运行

def teardown_class(self)

5、模块执行之前运行

def setup_module()

6、模块执行之后运行

def teardown_module()
📢PS:前后置器只能作用于全局,不能指定测试用例,所以出现了更强大的装饰器—@pytest.fixture


(六)conftest共享夹具

📢:配合@pytest.fixture(scope="package/session")一起使用。在每一个模块文件里创建夹具,只能内部使用,无法达到共享,于是产生了conftest.py

import pytest

def read_data():
    return ['1', '2', '3', '4']

@pytest.fixture(scope="package", params=read_data(), ids=['test1', 'test2', 'test3', 'test4'], autouse=True, name="fixture")
def execute_sql(request):
    print("········夹具前置")
    yield request.param
    print("夹具后置········")
在测试用例包下创建conftest(固定名称),在其中添加夹具方法,在所有测试用例文件中,都能使用到此夹具,目录级别越高的conftest会优先执行,目录级别比较低的conftest会后面执行。当conftest的scope级别和用例文件内setup、teardown方法级别一致时,conftest会优先执行。

(七)Assert断言

  • assert xx:判断 xx 为真
  • assert not xx :判断 xx 不为真
  • assert a in b:判断 b 包含 a
  • assert a == b :判断 a 等于 b
  • assert a != b :判断 a 不等于 b

(八)Allure报告

1、Allure下载

官网下载Allure,官网地址: Allure2.18.1下载

2、配置

解压文件后,将bin目录添加到系统变量path中

3、验证

命令行窗口中验证Allure是否安装成功
allure --version

4、安装allure-pytest

检验Pycharm中是否安装allure-pytest
pip list

5、配置pytest.ini

在pytest.ini中添加运行参数
[pytest]
addopts = -vs -m 'smoke or newModel' --alluredir=reports/temps --clean-alluredir
--alluredir=DIR:指定allure报告所需json数据的文件夹;
--clean-alluredir:如果已经存在报告,那就先清空,然后再生成新的测试报告;

6、定制Logo

  • 进入E:\Allure\allure-2.18.1\config目录下
  • 修改allure.yml,末尾添加 - custom-logo-plugin
  • 进入E:\Allure\allure-2.18.1\plugins\custom-logo-plugin\static,将定制logo图标复制至此
  • 修改style.css,将内容修改为以下代码

    .side-nav__brand {
    background: url('logo.png') no-repeat left center !important;
    margin-left: 40px;
    height: 90px;
    background-size: contain !important;
    }
    .side-nav__brand-text{
      display: none;
    }
  • 最终展示效果

7、生成报告

在run.py中生成测试报告
    pytest.main()
    os.system("allure generate reports/temps -o reports/allures --clean")
使用os.system()调用cmd命令行模式,allure generate <allure-result中间文件> -o 输出目录(默认路径:allure report)- -clean 清缓存。

8、报告优化

@allure.epic()

项目名称,修饰类

@allure.feature()

模块名称,修饰类

@allure.story()

子功能名称,修饰方法

@allure.title()

测试用例名称,修饰方法,适用于单个用例单个名称

allure.dynamic.title()

测试用例名称,方法体内使用,适用于动态参数的测试用例,可结合 @pytest.mark.parametrize 一起使用,当@allure.title()和此方法一同使用时,此方法会覆盖掉@allure.title()
@allure.epic("项目名称:若依管理系统")
@allure.feature("模块名称:登录模块")
class TestApi:
    @allure.story("登录模块")
    @allure.severity(allure.severity_level.BLOCKER)
    @pytest.mark.run(order=2)
    @pytest.mark.smoke
    @pytest.mark.parametrize("data", read_yaml("./testcases/API/data.yaml"))
    def test_baidu01(self, data):
        allure.dynamic.title(data["name"])
        allure.dynamic.description(data["description"])
        res = requests.request(method=data["request"]["method"], url=data["request"]["url"], json=data["request"]["data"])
        assert res.json()["msg"] == "操作成功"

@allure.severity()

参数名 参数级别 对标测试用例级别
allure.severity_level.BLOCKER 最高,阻塞级 致命:系统崩溃,内存泄漏等
allure.severity_level.CRITICAL 次高,严重级 严重:功能未实现,服务器错误等
allure.severity_level.NORMAL 一般,正常级 一般:逻辑错误,功能报错等
allure.severity_level.MINOR 较低,轻微级 轻微:条件查询错误,界面UI错误
allure.severity_level.TRIVIAL 最低,建议级 建议:错别字,样式优化等
此装饰器,可以修饰测试方法,也可以修饰测试类,都是用于表现不同程度的级别

@allure.description()

修改测试用例描述信息,用于装饰测试方法,适用于单个用例

allure.dynamic.description()

修改用例描述信息,用于测试方法内部,适用于动态参数的测试用例,可结合 @pytest.mark.parametrize 一起使用,当allure.description()和此方法一同使用时,此方法会覆盖掉allure.description()
@allure.epic("项目名称:若依管理系统")
@allure.feature("模块名称:登录模块")
class TestApi:
    @allure.story("登录模块")
    @allure.severity(allure.severity_level.BLOCKER)
    @pytest.mark.run(order=2)
    @pytest.mark.smoke
    @pytest.mark.parametrize("data", read_yaml("./testcases/API/data.yaml"))
    def test_baidu01(self, data):
        allure.dynamic.title(data["name"])
        allure.dynamic.description(data["description"])
        res = requests.request(method=data["request"]["method"], url=data["request"]["url"], json=data["request"]["data"])
        assert res.json()["msg"] == "操作成功"

@allure.link(name="", url="")

接口地址,name表示接口地址名称,URL表示链接地址

@allure.issue(name="", url="")

BUG地址,name表示BUG地址名称,URL表示BUG链接地址

@allure.testcase(name="", url="")

测试用例地址,name表示测试用例名称,URL表示测试用例链接地址

@allure.step(title="")

测试步骤,用于修饰方法,当该方法被测试用例调用时,会显示为测试步骤,该方法可传参


with allure.step

测试步骤,用于方法内部,会显示为测试步骤,该方法用于方法内部,无法传参
@allure.epic("测试项目:百度")
@allure.feature("模块名称:百度搜索")
class TestApi:
    @allure.story("百度搜索框")
    @allure.title("能否根据关键词搜索正确结果")
    @allure.description("验证百度模块")
    @pytest.mark.smoke
    @allure.link(name="接口地址", url="https://www.colablog.top")
    @allure.issue(name="BUG地址", url="https://www.colablog.top")
    @allure.testcase(name="测试用例地址", url="https://www.colablog.top")
    def test_baidu(self):
        with allure.step("打开浏览器"):
            print("打开谷歌浏览器")
        with allure.step("输入关键词"):
            print("输入搜索的关键词")
        with allure.step("搜索查看结果"):
            print("搜索结果并查看是否正确")
        allure.dynamic.title("覆盖-能否根据关键词搜索正确结果")
        allure.dynamic.description("覆盖-验证百度模块")
        print("这是第二条测试用例")
        assert 1 == 1

allure.attach

🔊附件,用法方法内部,测试报告会显示附件,需要配合with open使用
with open("D:\\壁纸.jpg", mode="rb") as f:
    allure.attach(body=f.read(), name="错误截图", attachment_type=allure.attachment_type.JPG)
目录
相关文章
|
5月前
|
存储 设计模式 测试技术
怎么基于Pytest+Requests+Allure实现接口自动化测试?
该文介绍了一个基于Python的自动化测试框架,主要由pytest、requests和allure构成,采用关键字驱动模式。项目结构分为六层:工具层(api_keyword)封装了如get、post的请求;参数层(params)存储公共参数;用例层(case)包含测试用例;数据驱动层(data_driver)处理数据;数据层(data)提供数据;逻辑层(logic)实现用例逻辑。代码示例展示了如何使用allure装饰器增强测试报告,以及如何使用yaml文件进行数据驱动。
188 0
|
1月前
|
测试技术
自动化测试项目学习笔记(五):Pytest结合allure生成测试报告以及重构项目
本文介绍了如何使用Pytest和Allure生成自动化测试报告。通过安装allure-pytest和配置环境,可以生成包含用例描述、步骤、等级等详细信息的美观报告。文章还提供了代码示例和运行指南,以及重构项目时的注意事项。
204 1
自动化测试项目学习笔记(五):Pytest结合allure生成测试报告以及重构项目
|
1月前
|
测试技术 Python
自动化测试项目学习笔记(四):Pytest介绍和使用
本文是关于自动化测试框架Pytest的介绍和使用。Pytest是一个功能丰富的Python测试工具,支持参数化、多种测试类型,并拥有众多第三方插件。文章讲解了Pytest的编写规则、命令行参数、执行测试、参数化处理以及如何使用fixture实现测试用例间的调用。此外,还提供了pytest.ini配置文件示例。
34 2
|
2月前
|
人工智能 测试技术 Python
基于 LangChain 的自动化测试用例的生成与执行
本章节详细介绍了如何利用人工智能技术自动化完成Web、App及接口测试用例的生成与执行过程,避免了手动粘贴和调整测试用例的繁琐操作。通过封装工具包与Agent,不仅提升了测试效率,还实现了从生成到执行的一体化流程。应用价值在于显著节省时间并提高测试自动化水平。
|
3月前
|
前端开发 关系型数据库 测试技术
django集成pytest进行自动化单元测试实战
在Django项目中集成Pytest进行单元测试可以提高测试的灵活性和效率,相比于Django自带的测试框架,Pytest提供了更为丰富和强大的测试功能。本文通过一个实际项目ishareblog介绍django集成pytest进行自动化单元测试实战。
55 3
django集成pytest进行自动化单元测试实战
|
4月前
|
监控 数据挖掘 BI
ERP系统中的工作流管理与自动化
【7月更文挑战第25天】 ERP系统中的工作流管理与自动化
198 2
ERP系统中的工作流管理与自动化
|
3月前
|
小程序 前端开发 持续交付
小程序全栈开发中的CI/CD流程与自动化部署是一种高效的开发模式。
本文探讨小程序全栈开发中的CI/CD流程与自动化部署,介绍持续集成与部署的概念,包括自动化构建、测试、代码审查及部署实践。通过提高代码质量、迭代速度及团队协作效率,确保小程序稳定运行与良好用户体验。
87 2
|
3月前
|
Web App开发 安全 测试技术
自动化测试中的Python魔法:使用Selenium和pytest框架
【8月更文挑战第31天】 在软件开发的海洋中,自动化测试是确保航行安全的灯塔。本文将带你探索如何利用Python语言结合Selenium和pytest框架,搭建一套高效的自动化测试体系。我们将从基础设置讲起,逐步深入到编写测试用例,最后通过一个实战案例来展示如何在实际项目中运用这些工具。文章旨在为读者提供一套清晰的自动化测试解决方案,让你的开发之旅更加顺畅。
|
3月前
|
存储 测试技术 API
apifox实例应用-自动化测试用例for循环的使用
总结来说,通过在Apifox自动化测试用例中结合for循环的使用,我们可以有效地对接口进行批量测试,提升测试效率和覆盖率。同时,通过参数化测试数据的灵活应用,能够确保我们的接口在不同的输入条件下都能保持正确的行为。这种方法能够显著减少手动测试工作量,同时通过标准化的流程确保测试的一致性。
287 0
|
4月前
|
机器学习/深度学习 人工智能 运维
智能化运维的崛起:自动化与人工智能在IT管理中的融合
本文深入探讨了智能化运维在现代企业中的重要性,并分析了自动化技术和人工智能(AI)如何共同推动IT运维管理的革新。文章首先概述了传统运维面临的挑战,然后详细介绍了智能化运维的核心概念和实施步骤,最后通过具体案例展示了智能化运维在实际工作中的应用效果和潜在价值。
132 0
下一篇
无影云桌面