pytest学习和使用23-通俗易懂的聊聊allure常用特性集合及使用方法说明
Posted 虫无涯
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了pytest学习和使用23-通俗易懂的聊聊allure常用特性集合及使用方法说明相关的知识,希望对你有一定的参考价值。
23-allure常用特性集合及使用方法说明
- 1 @allure.step()
- 2 allure.attach
- 3 @allure.description()
- 4 @allure.title()
- 5 @allure.link()、@allure.issue()、allure.testcase()
- 6 @allure.epic()、@allure.feature()、@allure.story()
- 7 @allure.severity
1 @allure.step()
@allure.step()
装饰器,可以让测试用例在allure
报告中显示详细的测试过程;step()
只有一个参数title
,传什么就在allure
上就显示什么;- 举例:
# -*- coding:utf-8 -*-
# 作者:虫无涯
# 日期:2023/3/28
# 文件名称:test_allure_step.py
# 作用:@allure.step特性
# 联系:VX(NoamaNelson)
# 博客:https://blog.csdn.net/NoamaNelson
import pytest
import allure
@allure.step("步骤1:用户登陆")
def test_login():
pass
@allure.step("步骤2:用户数据检查")
def test_check():
test_login()
if __name__ == '__main__':
pytest.main(["-s", "test_allure_step.py"])
- 运行命令再回顾下:
pytest -n auto --alluredir=allure test_allure_step.py
allure serve allure
- 运行后如下:
- 还有一种场景就是用例之间的嵌套,
step()
支持支持位置参数和关键字参数; - 如下:
# -*- coding:utf-8 -*-
# 作者:虫无涯
# 日期:2023/3/28
# 文件名称:test_allure_step1.py
# 作用:@allure.step特性
# 联系:VX(NoamaNelson)
# 博客:https://blog.csdn.net/NoamaNelson
import pytest
import allure
@allure.step("步骤1:用户登陆0, passwd")
def login(name, passwd):
pass
@allure.step("步骤2:数据检查")
def check():
login("zhang", "123456")
@allure.step("步骤3:登陆")
def test_case():
check()
if __name__ == '__main__':
pytest.main(["-s", "test_allure_step1.py"])
2 allure.attach
allure
报告支持显示许多不同类型的附件;- 使用方法是:
allure.attach(body, name, attachment_type, extension)
- 参数说明:
body:附件内容
name:附件名称
attachment_type:附件类型,是 allure.attachment_type 里面的其中一种
extension:附件扩展名
- 而
allure.attachment_type
的类型如下,可以查看源码:
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")
- 举例:
# -*- coding:utf-8 -*-
# 作者:虫无涯
# 日期:2023/3/28
# 文件名称:test_allure_attach.py
# 作用:allure.attach特性
# 联系:VX(NoamaNelson)
# 博客:https://blog.csdn.net/NoamaNelson
import allure
import pytest
def test_login():
allure.attach("user01,user02,user03", "用户信息", allure.attachment_type.TEXT)
pass
allure.attach()
的另一种使用方法为:
allure.attach.file(source, name, attachment_type, extension)
- 参数说明:
source:文件路径
body:附件内容
name:附件名称
attachment_type:附件类型,是 allure.attachment_type 里面的其中一种
extension:附件扩展名
- 举例:
# -*- coding:utf-8 -*-
# 作者:虫无涯
# 日期:2023/3/28
# 文件名称:test_allure_attach.py
# 作用:allure.attach特性
# 联系:VX(NoamaNelson)
# 博客:https://blog.csdn.net/NoamaNelson
import allure
import pytest
def test_login():
allure.attach("user01,user02,user03", "用户信息", allure.attachment_type.TEXT)
pass
def test_login_info():
allure.attach.file("./user_info.csv", attachment_type=allure.attachment_type.CSV)
pass
3 @allure.description()
- 添加更详细的测试用例描述;
- 格式为:
@allure.description(str)
,类似于函数声明下方添加""" """
; - 举例:
# -*- coding:utf-8 -*-
# 作者:虫无涯
# 日期:2023/3/28
# 文件名称:test_allure_description.py
# 作用:@allure.description特性
# 联系:VX(NoamaNelson)
# 博客:https://blog.csdn.net/NoamaNelson
import allure
import pytest
# 使用方法一
@allure.description("""
这个用例的主要所用是验证?
哦,对了,我也不知道干啥的!!!
""")
def test_case01():
num = 100 * (1 + 9)
assert num == 1000
# 使用方法二
def test_case02():
"""
这是一个用例!
这个用例什么也没做!
这个用例只是简单做个验证而已~
"""
pass
4 @allure.title()
- 描述测试用例的标题,可为中文;
- 格式为:
@allure.title(str)
- 如下:
# -*- coding:utf-8 -*-
# 作者:虫无涯
# 日期:2023/3/28
# 文件名称:test_allure_title.py
# 作用:@allure.title特性
# 联系:VX(NoamaNelson)
# 博客:https://blog.csdn.net/NoamaNelson
import allure
@allure.title("用户正常登陆")
def test_login01():
pass
@allure.title("用户名错误")
def test_login02():
pass
- 另外,
allure.title()
支持占位符传递关键字参数; - 如下:
# -*- coding:utf-8 -*-
# 作者:虫无涯
# 日期:2023/3/28
# 文件名称:test_allure_title1.py
# 作用:@allure.title特性
# 联系:VX(NoamaNelson)
# 博客:https://blog.csdn.net/NoamaNelson
import allure
import pytest
@allure.title("用户登陆")
@pytest.fixture
def test_login(request):
args = request.param
user = args["name"]
pwd = args["password"]
print(user, pwd, args)
yield user, pwd
@allure.title("正常登陆,用户信息为:test_login")
@pytest.mark.parametrize("test_login", [
"name": "xiaoli", "password": "123456",
"name": "laoli", "password": "123456"], indirect=True)
def test_login_info(test_login):
user, pwd = test_login
allure.attach(f"用户名:user, 密码:pwd")
5 @allure.link()、@allure.issue()、allure.testcase()
- 为了将
allure
报告和一些系统集成,可以更快速的跳转到指定地址; - 源码为:
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))
- 参数说明:
issue()和testcase()其实调用的也是link(),只是link_type不一样
url:跳转的链接;
name:可选参数,显示在allure报告的名字,不传则显示完整的链接;
link_type:跳转的type类型;LINK、ISSUE、TEST_CASE,即访问链接、Bug链接、测试用例链接;
总结:三个方法是一样的,只是link_type不一样,allure报告显示的样式不一样。
- 举例:
# -*- coding:utf-8 -*-
# 作者:虫无涯
# 日期:2023/3/28
# 文件名称:test_link_issue_testcase.py
# 作用:@allure.link()、@allure.issue()、@allure.testcase()的特性
# 联系:VX(NoamaNelson)
# 博客:https://blog.csdn.net/NoamaNelson
import allure
@allure.link("https://blog.csdn.net/NoamaNelson")
def test_blog_link():
pass
@allure.link("https://blog.csdn.net/NoamaNelson", name="点击查看博客主页")
def test_blog_link1():
pass
@allure.issue('https://bbs.csdn.net/forums/NoamaNelson', '全栈测试技术社区')
def test_blog_issue():
pass
@allure.testcase("https://bbs.csdn.net/forums/NoamaNelson?category=10003&typeId=1566629", "测试用例地址")
def test_blog_testcase():
pass
6 @allure.epic()、@allure.feature()、@allure.story()
allure
的三种标记装饰器,可以显示在allure报告上;@pytest.mark
不会显示在allure
报告上;- 作用:
@allure.epic:往下是 feature
@allure.feature:功能点的描述,模块往下是 story
@allure.story:故事,往下是 title
注意:
story 是 feature 的子集。
- 举例:
# -*- coding:utf-8 -*-
# 作者:虫无涯
# 日期:2023/3/28
# 文件名称:test_epic_feature_story.py
# 作用:@allure.epic()、@allure.feature()、@allure.story()特性
# 联系:VX(NoamaNelson)
# 博客:https://blog.csdn.net/NoamaNelson
import allure
def test_case01():
pass
@allure.story('epic01')
def test_case02():
pass
@allure.story('story01')
def test_case03():
pass
@allure.story('story02')
def test_case04():
pass
@allure.feature('feature02')
@allure.story('story02')
def test_case05():
pass
7 @allure.severity
- 在
allure
报告可以看到不同级别用例的缺陷数量,即标记用例级别 ; - 使用方法:
@allure.severity(allure.severity_level.xxx)
# xxx为级别
- 比如
@allure.severity(allure.severity_level.TRIVIAL)
,可以看下源码:
class Severity(str, Enum):
BLOCKER = 'blocker'
CRITICAL = 'critical'
NORMAL = 'normal'
MINOR = 'minor'
TRIVIAL = 'trivial'
- 从以上可以看出有5个等级,分别是:
blocker:阻塞缺陷
critical:严重缺陷
normal: 一般缺陷
minor:次要缺陷
trivial: 轻微缺陷
- 举例:
# -*- coding:utf-8 -*-
# 作者:虫无涯
# 日期:2023/3/28
# 文件名称:test_severity.py
# 作用:@allure.severity标记用例级别
# 联系:VX(NoamaNelson)
# 博客:https://blog.csdn.net/NoamaNelson
import allure
# @allure.severity(allure.severity_level.NORMAL)
@allure.severity("normal")
@allure.description("""normal级别用例""")
def test_case01():
print("用例01")
# @allure.severity(allure.severity_level.CRITICAL)
@allure.severity("critical")
@allure.description("""critical级别用例""")
def test_case02():
print("用例02")
# @allure.severity(allure.severity_level.BLOCKER)
@allure.severity("blocker")
@allure.description("""blocker级别用例""")
def test_case03():
print("用例03")
# @allure.severity(allure.severity_level.MINOR)
@allure.severity("minor")
@allure.description("""minor级别用例""")
def test_case04():
print("用例04")
# @allure.severity(allure.severity_level.TRIVIAL)
@allure.severity("trivial")
@allure.description("""trivial级别用例""")
def test_case05():
print("用例05")
@allure.description("""没标记,默认为 normal""")
def test_case06():
print("用例06")
- 没标记的默认
normal
:
- 图表样式:
- 也可以使用命令行参数
allure-severities
根据优先级选择需要运行的测试用例,比如:
pytest test_severity.py -sq --alluredir=./allure --allure-severities=blocker,critical
用例02
.用例03
.
2 passed in 0.10s
pytest学习和使用20-pytest如何进行分布式测试?(pytest-xdist)
(20-pytest如何进行分布式测试?(pytest-xdist))
1 什么是分布式测试?
- 在进行本文之前,先了解些基础知识,什么是分布式测试?
- 分布式测试:是指通过局域网和Internet,把分布于不同地点、独立完成特定功能的测试计算机连接起来,以达到测试资源共享、分散操作、集中管理、协同工作、负载均衡、测试过程监控等目的的计算机网络测试。
- 通俗的讲:分布式测试 就是活太多,一个人干费时间,那就让多个人一起干,节省了资源和时间。
2 为什么要进行分布式测试?
2.1 场景1:自动化测试场景
- 自动化测试时,我们有很多用例,比如2000条用例,按照顺序执行,每条用例执行1分钟,那需要2000分钟;
- 什么概念?2000分钟就30多个小时,如果是冒烟测试,估计还没人工跑的快;
- 还有,如果是线上发布,跑完2000条用例就太浪费时间了;
- 那如果我们让我们让用例分布式执行,是不是可以节省很多时间?
2.2 场景2:性能测试场景
- 如果数据量很大,我们使用1台压测机,可能并发压力过大;
- 那就需要选择使用多台压测机(比如Jmeter的 Agent/负载机);
- 这样也是一种分布式压测或者分布式性能测试场景。
3 分布式测试有什么特点?
特点 | 说明 |
---|---|
网格化 | 多节点互联互通,可资源共享 |
分布性 | 地域和计算机上,协同工作、负载均衡、可扩展性、高可用性 |
开放性 | 可移植性、可互操作性、可伸缩性、易获得性 |
实时性 | 各种信息都必须是实时的 |
动态性 | 测试过程对象和活动动态映射 |
处理不确定性 | 具有处理不确定性的能力 |
容错及安全性 | 容错能力强,可靠性高、安全性好 |
4 分布式测试关键技术是什么?
技术点 | 要求 |
---|---|
分布式环境 | 获取全局状态,能够方便地监视和操纵测试过程;集中式的分布式策略。 |
分布式环境下的节点通信 | 稳定的通信环境;适合用基于消息通信的方式来实现。 |
测试任务调度 | 静态调度、动态调度和混合调度。 |
5 分布式执行用例的前置条件是什么?
- 用例之间是独立且没有依赖关系,完全独立运行;
- 用例执行没有顺序,随机顺序都能正常执行;
- 每个用例都能重复运行,运行结果不会影响其他用例。
6 pytest-xdist安装
pytest-xdist
让自动化测试用例分布式执行,节省测试时间,属于进程级别的并发;- 使用以下方法安装:
pip3 install pytest-xdist
C:\\Users\\Administrator>pip3 install pytest-xdist
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple
Requirement already satisfied: pytest-xdist in d:\\python37\\lib\\site-packages (1.31.0)
Requirement already satisfied: six in d:\\python37\\lib\\site-packages (from pytest-xdist) (1.15.0)
Requirement already satisfied: execnet>=1.1 in d:\\python37\\lib\\site-packages (from pytest-xdist) (1.8.0)
Requirement already satisfied: pytest>=4.4.0 in d:\\python37\\lib\\site-packages (from pytest-xdist) (6.2.4)
Requirement already satisfied: pytest-forked in d:\\python37\\lib\\site-packages (from pytest-xdist) (1.1.3)
Requirement already satisfied: apipkg>=1.4 in d:\\python37\\lib\\site-packages (from execnet>=1.1->pytest-xdist) (1.5)
Requirement already satisfied: toml in d:\\python37\\lib\\site-packages (from pytest>=4.4.0->pytest-xdist) (0.10.2)
Requirement already satisfied: attrs>=19.2.0 in d:\\python37\\lib\\site-packages (from pytest>=4.4.0->pytest-xdist) (20.3.0)
Requirement already satisfied: colorama in d:\\python37\\lib\\site-packages (from pytest>=4.4.0->pytest-xdist) (0.4.4)
Requirement already satisfied: atomicwrites>=1.0 in d:\\python37\\lib\\site-packages (from pytest>=4.4.0->pytest-xdist) (1.4.0)
Requirement already satisfied: pluggy<1.0.0a1,>=0.12 in d:\\python37\\lib\\site-packages (from pytest>=4.4.0->pytest-xdist) (0.13.1)
Requirement already satisfied: py>=1.8.2 in d:\\python37\\lib\\site-packages (from pytest>=4.4.0->pytest-xdist) (1.10.0)
Requirement already satisfied: importlib-metadata>=0.12 in d:\\python37\\lib\\site-packages (from pytest>=4.4.0->pytest-xdist) (2.1.1)
Requirement already satisfied: packaging in d:\\python37\\lib\\site-packages (from pytest>=4.4.0->pytest-xdist) (20.8)
Requirement already satisfied: iniconfig in d:\\python37\\lib\\site-packages (from pytest>=4.4.0->pytest-xdist) (1.1.1)
Requirement already satisfied: zipp>=0.5 in d:\\python37\\lib\\site-packages (from importlib-metadata>=0.12->pytest>=4.4.0->pytest-xdist) (1.2.0)
Requirement already satisfied: pyparsing>=2.0.2 in d:\\python37\\lib\\site-packages (from packaging->pytest>=4.4.0->pytest-xdist) (2.4.7)
7 pytest-xdist的优势
- 测试运行并行化;
- 在子进程中重复运行测试;
- 可指定不同的Python解释程序或不同的平台,并行运行测试。
8 pytest-xdist的使用
8.1 普通执行
# -*- coding:utf-8 -*-
# 作者:虫无涯
# 日期:2023/3/16
# 文件名称:test_xdist.py
# 作用:pytest-xdist分布式测试
import pytest
import time
class TestCase01():
def test_case_01(self):
time.sleep(1)
print("case01$$$$$$$$$$$$$$$$$$$$$")
def test_case_02(self):
time.sleep(1)
print("case02$$$$$$$$$$$$$$$$$$$$$")
def test_case_03(self):
time.sleep(1)
print("case03$$$$$$$$$$$$$$$$$$$$$")
def test_case_04(self):
time.sleep(1)
print("case04$$$$$$$$$$$$$$$$$$$$$")
def test_case_05(self):
time.sleep(1)
print("case05$$$$$$$$$$$$$$$$$$$$$")
def test_case_06(self):
time.sleep(1)
print("case06$$$$$$$$$$$$$$$$$$$$$")
class TestCase02():
def test_case_07(self):
time.sleep(1)
print("case07$$$$$$$$$$$$$$$$$$$$$")
def test_case_08(self):
time.sleep(1)
print("case08$$$$$$$$$$$$$$$$$$$$$")
def test_case_09(self):
time.sleep(1)
print("case08$$$$$$$$$$$$$$$$$$$$$")
if __name__ == __main__:
pytest.main(["-s", "test_xdist.py"])
- 执行结果如下,使用了9.14s:
test_xdist.py::TestCase01::test_case_01
test_xdist.py::TestCase01::test_case_02
test_xdist.py::TestCase01::test_case_03
test_xdist.py::TestCase01::test_case_04
test_xdist.py::TestCase01::test_case_05
test_xdist.py::TestCase01::test_case_06
test_xdist.py::TestCase02::test_case_07 PASSED [ 11%]case01$$$$$$$$$$$$$$$$$$$$$
PASSED [ 22%]case02$$$$$$$$$$$$$$$$$$$$$
PASSED [ 33%]case03$$$$$$$$$$$$$$$$$$$$$
PASSED [ 44%]case04$$$$$$$$$$$$$$$$$$$$$
PASSED [ 55%]case05$$$$$$$$$$$$$$$$$$$$$
PASSED [ 66%]case06$$$$$$$$$$$$$$$$$$$$$
PASSED [ 77%]case07$$$$$$$$$$$$$$$$$$$$$
test_xdist.py::TestCase02::test_case_08 PASSED [ 88%]case08$$$$$$$$$$$$$$$$$$$$$
test_xdist.py::TestCase02::test_case_09 PASSED [100%]case08$$$$$$$$$$$$$$$$$$$$$
============================== 9 passed in 9.14s ==============================
8.2 上述代码分布式执行:
- 执行命令:
pytest -s -n auto test_xdist.py
- 结果如下,用时4.51s,可见分布式执行后大大缩短了测试时间:
(venv) F:\\pytest_study\\test_case\\test_j>pytest -s -n auto test_xdist.py
============================================ test session starts =============================================
platform win32 -- Python 3.7.0, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
rootdir: F:\\pytest_study, configfile: pytest.ini
plugins: allure-pytest-2.8.12, assume-2.4.3, cov-2.8.1, forked-1.1.3, html-2.0.1, metadata-1.8.0, ordering-0.6,
repeat-0.9.1, rerunfailures-10.3, xdist-1.31.0
gw0 [9] / gw1 [9] / gw2 [9] / gw3 [9] / gw4 [9] / gw5 [9] / gw6 [9] / gw7 [9]
.........
============================================= 9 passed in 4.51s ==============================================
8.3 指定CPU运行数量
-n auto
:可以自动检测到系统的CPU
核数;- 使用
auto
利用了所有CPU
来跑用例; - 也可以指定使用几个
CPU
来跑用例:
# x为cpu个数
pytest -s -n x
- 如下可以看到使用两个
CPU
来跑用例时长为6.27s:
(venv) F:\\pytest_study\\test_case\\test_j>pytest -s -n 2 test_xdist.py
============================================ test session starts =============================================
platform win32 -- Python 3.7.0, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
rootdir: F:\\pytest_study, configfile: pytest.ini
plugins: allure-pytest-2.8.12, assume-2.4.3, cov-2.8.1, forked-1.1.3, html-2.0.1, metadata-1.8.0, ordering-0.6,
repeat-0.9.1, rerunfailures-10.3, xdist-1.31.0
gw0 [9] / gw1 [9]
.........
============================================= 9 passed in 6.27s ==============================================
8.4 与pytest-html一起使用
- 命令如下:
pytest -s -n auto --html=report.html --self-contained-html
- 运行结果:
pytest -s -n auto test_xdist.py --html=report.thml --self-contained-htm
l
gw0 [9] / gw1 [9] / gw2 [9] / gw3 [9] / gw4 [9] / gw5 [9] / gw6 [9] / gw7 [9]
.........
------------------ generated html file: file://F:\\pytest_study\\test_case\\test_j\\report.thml ------------------
============================================= 9 passed in 4.68s ==============================================
8.5 让pytest-xdist按照指定顺序执行
pytest-xdist
执行默认是无须的;- 可通过
--dist
参数来控制顺序;
参数 | 说明 |
---|---|
--dist=loadscope |
同一个模块module 下的函数和同一个测试类class 下的方法来分组 |
--dist=loadfile |
同一个文件名来分组 |
8.6 pytest-xdist如何保持session执行一次
pytest-xdist
没有内置的支持来确保会话范围的夹具仅执行一次;- 可使用
FileLock
方法仅仅产生一次fixture
数据:
import pytest
from filelock import FileLock
@pytest.fixture(scope="session")
def login():
print("====登录===")
with FileLock("session.lock"):
name = "zhang"
password= "123456"
# web ui自动化
# 声明一个driver,再返回
# 接口自动化
# 发起一个登录请求,将token返回都可以这样写
yield name, password
print("====退出====")
以上是关于pytest学习和使用23-通俗易懂的聊聊allure常用特性集合及使用方法说明的主要内容,如果未能解决你的问题,请参考以下文章