一、pytest简介
pytest是Python中的一种单元测试的框架,同自带的unittest测试框架比较类似,相比于unittest框架pytes使用起来更加简洁,而且功能更加强大,效率更高效
特点:
- pytest是一个非常成熟的python的单元框架,比unittest更灵活,容易上手
- pytest可以和selenium,requests,appium结合实现web自动化,接口自动化,app自动化
- 可以结合插件(pytest.mark.parametrize)实现用例参数化
- pytest可以和allure生成非常美观的测试报告
- pytest可以和Jenkins持续集成
-
pytest有很多非常强大的插件,并且这些插件能够实现很多的实用的操作:
-
pytest ---------------------------->框架主包
-
pytest-html ---------------------> 用于生成html格式的自动化测试报告
-
pytest-xdist --------------------->测试用例分布式执行,多CPU分发
-
pytest-ordering ---------------->用于改变测试用例的执行顺序
-
pytest-rerunfailures ---------->用例失败后重跑
-
allure-pytest -------------------->用于生成美观的测试报告
-
【pytest依赖包】6个
pytest
pytest-html
pytest-xdist
pytest-ordering
pytest-rerunfailures
allure-pytest
批量导包:
新建文件“requirements.txt”
-
将所有依赖包导出
终端命令中输入命令 : pip freeze > requirements.txt
-
将所有依赖包导入
终端输入命令: 即可一键自动下载文件中的所包。 已存在的会覆盖下载
pip install -r ./requirements.txt
二、API接口框架-结构
- script(包文件) --------------------->存放开始调试的线性脚本
- common (包文件) ---------------->存放封装的公共方法
- testCase (包文件) ---------------->存放测试用例方法
- testData ----------------------------->存放测试数据的文件夹
- testLog ------------------------------>存在log日志的文件
- testReport -------------------------->测试报告
- config.ini ---------------------------->配置文件
- main.py ------------------------------->项目运行入口文件
三、Pytest测试用例编写规则
$使用pytest时,"默认"的用例编写规则$
- 模块名:必须以 test_ 开头或者 _test 结尾
- 测试类:必须以Test来头,并且不能有init方法
- 测试方法:必须以test开头
3.1、示例代码:
测试用例文件:test_login.py
import pytest
# 测试用例类
class TestCase:
# 测试用例方法
def test_case(self):
print("执行测试用例")
3.2、pytest.ini 配置文件中修改默认信息
[pytest]
# 修改测试文件,默认路径,“../testcase为上一层的testcase文件夹”
testpaths = ../testcase
# 配置测试搜索的模块文件名称
python_files = test*.py
# 配置测试搜索的测试类名
python_classes = Test*
# 配置测试搜索的测试函数名
python_functions = test
四、pytest测试用例的运行方式
4.1、主函数模式:
- 运行所有: pytest.main()
- 运行指定模块: pytest.main(['-vs','模块名.py'])
- 运行指定目录: pytest.mian(['-vs','目录路径'])
4.2、命令行模式:
- 运行所有: pytest
- 运行指定模块: pytest -vs 模块名.py
- 运行指定目录: pytest -vs 目录路径
除了在运行执行时,执行参数,也可以在“pytest.ini配置文件”中配置参数;执行时自动引用
4.3、pytest.ini 配置文件模式
-
pytest.ini是pytet单元测试框架的核心配置文件
-
位置:必须放在项目的根目录
-
编码格式:必须用ANSI格式,可用notepad++等工具修改
-
作用:改变pytest默认的行为
-
运行的规则:主函数模式和命令行模式都会读取这个配置文件
-
注意:配置文件中,尽量不要使用中文,如果使用中文,编码改成GBK
-
代码示例:
-
通过主函数传递参数
# 导包
import pytest
pytest.main(["-vs", '-n=2', '--reruns=2','--html=./testReport/reports.html'])
- 通过pytest.ini配置文件传递参数
[pytest]
# 多个参数,使用空格分割
addopts = -vs -n=2 --reruns=2
参数详解:
1 -s :输出调试信息,包括print打印的信息
2 -v :显示更详细的信息
3 -n :支持多线程或者分布式运行测试用例
- 主函数模式:
pytest.mian(['-vs','模块名.py','-n=2']) -->调用两个线程执行 -->'模块名.py'指定模块运行
- 命令行模式:
pytest -vs 模块名.py -n 2
如果有5条用例用2个线程执行:
线程一:1,3,5条
线程二:2,4条
4 --reruns :失败用例重试
-
主函数模式: pytest.mian(['-vs','模块名.py','-n=2','--reruns=2'])
-
命令行模式: pytest -vs 模块名.py -n=2 --reruns 2
失败后重跑2次,总共跑3次
5 --html :生成原生html的测试报告
# 示例代码
pytest.main(["-vs", '--html=./testReport/reports.html'])
- 主函数模式: pytest.mian(['-vs','模块名.py','--html=报告路径'])
- 命令行模式: pytest -vs 模块名.py --html '报告路径'
6 -x :遇到报错测试用例则立即停止测试
7 --maxfail :遇到指定个数用例失败就停止测试
- 主函数模式: pytest.mian(['-vs','模块名.py','--maxfail=2'])
- 命令行模式: pytest -vs 模块名.py --maxfail=2
8 -k :根据测试用例名称内的部分字符串指定执行测试用例
- 主函数模式: pytest.mian(['-vs','模块名.py','-k=xx'])
- 命令行模式: pytest -vs 模块名.py -k 'xx'
9 -vs :综合 -s , -v 的功能
五、pytest的测试执行顺序
unittest的执行顺序:默认按照ASCII表的顺序执行测试用例
pytest的执行顺序:默认按照从上到下的顺序执行测试用例
- 改变pytest的默认执行顺序:使用mark中的装饰器
-
@pytest.mark.run(order=3)
此功能需pytest-ordering插件支持
安装:pip install pytest-ordering
六、如何分组执行
使用场景:(冒烟,分模块执行,分接口或 UI执行)
smoke:冒烟用例,分布在各个模块里面
-
步骤一:在pytest.ini配置文件内添加配置信息:markers
[pytest]
addopts = -vs -m smoke
markers =
smoke:冒烟
g1:组一
g2:组二
[pytest]
# 同时执行多组用例
addopts = -vs -m "g1 or g2"
markers =
somke:冒烟用例
g1:
g2:
- 步骤二:给测试函数添加装饰器 @pytest.mark.smoke
class Testcase:
@pytest.mark.smoke
def testcase_Sign_in_lose(self):
"""测试用例方法"""
print("=======> smoke")
- 步骤三:执行测试用例:
主函数模式: pytest.mian(['-vs','模块名.py','-m=smoke'])
命令行模式: pytest -vs -m 'smoke'
注意:
此处的smoke不是固定的,可以自己定义标记名称
如果想执行多个标记的用例: pytest -vs -m '标记1 or 标记2'
总结:当主函数和配置文件都存在-运行参数时:
1. 默认是先执行配置文件参数
2. 如果参数不重复的情况下,都会执行参数
七、pytest跳过测试用例
-
无条件跳过:
-
添加装饰器: @pytest.mark.skip(reason = '跳过原因')
-
-
有条件跳过:
-
添加装饰器: @pytest.mark.skipif(表达式, reason = '跳过原因')
reason = '跳过原因':跳过提示
注意:此处的表达式得到的应该是一个布尔类型,表达式成立则跳过,否则执行用例
-
import pytest
class Testdemo:
@pytest.mark.skip(reason="版本原因,跳过用例")
def test_01(self):
print("我是用例a")
@pytest.mark.skipif(1 == 1, reason="条件成立,跳过用例")
def test_02(self):
print("我是用例b")
def test_03(self):
print("我是用例c")
if __name__ == '__main__':
pytest.main()
============================= test session starts ==============================
collecting ... collected 4 items
test_demo.py::Testdemo::test_01 SKIPPED (版本原因,跳过用例)
Skipped: 版本原因,跳过用例
test_demo.py::Testdemo::test_02 SKIPPED (条件成立,跳过用例)
Skipped: 条件成立,跳过用例
test_demo.py::Testdemo::test_03 我是用例c
PASSED
========================= 2 passed, 2 skipped in 0.01s =========================
进程已结束,退出代码为 0
八、mark标记-xfail用例失败
标记预期会出现异常的用例,出现异常,和未出现异常结果显示不一样
标记失败出现异常那么正常显示标记预期失败
- XFAIL
标记失败未出现异常那么显示标记成功通过
- XPASS
import pytest
class Testdemo:
@pytest.mark.xfail(reason="标记失败,原因描述")
def test_01(self):
print("我是用例a")
1/0
@pytest.mark.xfail
def test_02(self):
print("我是用例b")
def test_03(self):
print("我是用例c")
if __name__ == '__main__':
pytest.main()
test_demo.py:8: ZeroDivisionError
test_demo.py::Testdemo::test_02 我是用例b
XPASS
test_demo.py::Testdemo::test_03 我是用例c
PASSED
test_demo.py::Testdemo::test_04 我是用例d
PASSED
=================== 2 passed, 1 xfailed, 1 xpassed in 0.02s
进程已结束,退出代码为 0
九、前置后置处理
又名:夹具、固件、钩子函数
1、setup 和 teardown
class TestApi:
# 类级别前置处理
def setup_class(self):
print("创建日志对象(创建多个日志对象,那么日志会重复),创建数据库连接")
# 类级别后置处理
def teardown_class(self):
print("销毁日志对象,关闭数据库连接")
# 前置处理(用例级别)
def setup(self):
print("web自动化:打开浏览器,加载网页;接口自动化:日志开始")
# 后置处理(用例级别)
def teardown(self):
print("日志结束,关闭浏览器")
# 测试用例方法
@pytest.mark.skipif("1==1", resson="跳过")
def test_demo1(self):
print("我是测试用例---01")
2、@pytest.fixture():装饰器来实现部分用例的前后置
a- fixture定位顺序
- 先从当前用例执行模块定位fixture
- 其次从同级py模块中定位fixture
- 再从项目包中定位fixture
- 然后会从conftest.py模块中定位fixture
- 最后会从根目录定位fixture
- 如果再也没有找到对应的fixture程序就会报错
b- 语法
# 参数说明
@pytest.fixture(scope="作用域",
params=“数据驱动”,
autouser="自动执行",
ids=“自定义参数名称”,
anme=“别名;改变fixture标记的函数名”)
import pytest
# 添加此装饰器的函数可以实现初始化和清理工作
@pytest.fixture(autouse=True, scope="class")
def func(self):
print("我是初始化工作")
yield
print("我是清理工作")
class TestCase:
# 测试用例1
def test_case1(self):
print("执行测试用例1")
# 测试用例2:只有将初始化/清理函数作为参数传入用例,才会触发
def test_case2(self, func):
print("执行测试用例2")
if __name__ == '__main__':
pytest.main(["-vs"])
3、@pytest.fixture()装饰器:参数
@pytest.fixture();默认参数autose=False,scope="function"
可以通过传递函数来指定某个用例是否执行前置后置操作
import pytest
# 添加此装饰器的函数可以实现初始化和清理工作
@pytest.fixture()
def func():
print("我是初始化工作")
yield
print("我是清理工作")
class TestCase:
# 测试用例1
def test_case1(self,func):
print("执行测试用例1")
# 测试用例2:只有将初始化/清理函数作为参数传入用例,才会触发
def test_case2(self):
print("执行测试用例2")
if __name__ == '__main__':
pytest.main(["-vs"])
参数1: autouse
@pytest.fixture() 装饰器内autouse参数:
- 默认:为False,所有用例不会主动触发,需要在指定用例进行传参,来触发
- 修改:为True,则所有用例都会自动触发初始化清理方法
参数2: scope
表示被 @pytest.fixture 标记的方法的作用域
- function: 函数(默认),传递此参数或者不传则每条测试方法执行前后都会触发初始化清理方法
- class: 传递此参数则每个类执行前后会触发一次初始化清理方法
- module: 传递此参数则每个py模块执行前后会触发一次初始化清理方法
- package/session: 传递此参数则每个包执行前后会触发一次初始化清理方法(用例模块),一般和“connftest.py”文件一起使用
import pytest
# 添加此装饰器的函数可以实现初始化和清理工作
@pytest.fixture(autouse=True,scope='class')
def func():
print("我是初始化工作")
yield
print("\n我是清理工作")
class TestCase:
# 测试用例1
def test_case1(self, func):
print("执行测试用例1")
# 测试用例2:只有将初始化/清理函数作为参数传入用例,才会触发
def test_case2(self):
print("执行测试用例2")
if __name__ == '__main__':
pytest.main(["-vs"])
如果类级别的前置后置时,想要某个类执行 -->@pytest.maek.usefixtures
import pytest
@pytest.fixture(scope='class')
def func():
print("我是初始化工作")
yield
print("\n我是清理工作")
class TestCase:
def test_case1(self, func):
print("执行测试用例1")
# 使用装饰usefixtures()
@pytest.maek.usefixtures(func)
def test_case2(self):
print("执行测试用例2")
参数3: params (参数化)
注意:params接收的数据类型(列表、字典、元组)
用法如下:
import pytest
# 数据处理函数
def read_excel():
return [{"name1": "Tom"}, {"name2": "小明"}, {"name3": "小红"}]
@pytest.fixture(scope="function", params=read_excel())
def func(request): # request:固定写法
print("我是前置处理---连接数据库")
yield request.param # request.param:固定写法
print("我是后置处理-----断开数据库连接")
# 测试用例类
class TestApi:
def test_demo(self, func):
print("我是测试用例--demo", func)
if __name__ == '__main__':
pytest.main(["-vs"])
============================ test session starts ==============================
collecting ... collected 3 items
test_api_001.py::TestApi::test_demo[func0] 我是前置处理---连接数据库
我是测试用例--demo {'name1': 'Tom'}
PASSED我是后置处理-----断开数据库连接
test_api_001.py::TestApi::test_demo[func1] 我是前置处理---连接数据库
我是测试用例--demo {'name2': '小明'}
PASSED我是后置处理-----断开数据库连接
test_api_001.py::TestApi::test_demo[func2] 我是前置处理---连接数据库
我是测试用例--demo {'name3': '小红'}
PASSED我是后置处理-----断开数据库连接
============================== 3 passed in 0.00s ===============================
进程已结束,退出代码为 0
4、conftest.py 文件的使用
当fixture的级别为parkage/session时,那么一般和conftest.py文件一起使用
- 1. 名称固定为:conftest.py,主要用于单独的存放fixtrue固件;
- 2. 级别为package、session时,那么可以在多个包甚至多个文件里面共享前后置
- 3. conftest.py文件,可以有多个;(按层级从最外层,一级一级往里执行)
- 4. 单个conftest.py文件执行顺序:从最外面往最里面执行,从上到下,按照ASCII编码进行调用
- testcase
- goods_manage
- test_api.py
- conftest2.py
- user_manage
- tste_api2.py
- conftest3.py
- conftest1.py
# 注意:程序先执行最外层“conftest1.py”,再执行“conftest2.py”和“conftest3.py”
- 5 .注意:当同级别的 setup/teardown和contest.py 同时存在时, conftest.py 优先级更高一些
- 6. conftest文件可以夸py文件使用
十、参数化:@pytest.mark.parametrize()数据驱动基本用法
@pytest.mark.parametrize(args_name,args_value)
- args_name: 参数名称
- args_value: 参数值
有多少组值,就会执行多少次用例
args_value支持的数据类型:(list, tuple, 字典列表,字典元组)
示例代码:
第一种方式:[元素1,元素2...]:
# 导包
import pytest
class TestApi:
# 测试用例
@pytest.mark.parametrize("args", [1, 2, 3])
def test_case1(self, args):
print("执行测试用例", args)
# 断言:语法assert 表达式
assert args == 2, "这个数不是2"
if __name__ == '__main__':
pytest.main(["-vs"])
第二种方式:[[元素1, 元素2], [元素1, 元素2], [元素1, 元素2], ...]:
需要传递和元素一致的变量名接收,是一个拆包的过程
import pytest
data_value = [["python", 11], ["java", 22], ["php", 33]]
class TestApi_02:
@pytest.mark.parametrize("args1, args2", data_value)
def test_func2(self, args1, args2):
print(f"我是测试用例{args1}")
print(f"我是测试用例{args2}")
print('----------------------------\n')
if __name__ == '__main__':
pytest.main()
============================= test session starts ==============================
collecting ... collected 3 items
test_api2.py::TestApi_02::test_func2[python-11]
我是测试用例python
我是测试用例11
----------------------------
PASSED
test_api2.py::TestApi_02::test_func2[java-22]
我是测试用例java
我是测试用例22
----------------------------
PASSED
test_api2.py::TestApi_02::test_func2[php-33]
我是测试用例php
我是测试用例33
----------------------------
PASSED
============================== 3 passed in 0.01s ===============================
进程已结束,退出代码为 0
十一、断言
在pytest框架中使用assert进行断言
class TestCase:
# 测试用例
def test_case(self):
print("执行测试用例")
# 断言:语法assert 表达式
assert 1 == 2, "断言失败提示信息"
注意: assert后面的表达式需要返回布尔类型,True为测试用例通过,False为用例失败
十二、Pytest生成allure报告
1、allure环境配置
1、官网下载allure文件:
https://repo.maven.apache.org/maven2/io/qameta/allure/allure-commandline/
2、解压到非中文路径下,然后把bin目录配置到环境变量path中:E:\\allure-2.32\bin
3、验证 allure --version
4、安装 pip install allure-pytest
2、在report目录下生成测试报告
第一:report目录下生成temps目录,并且在temps目录下生成json格式临时报
import pytest, os, time
if __name__ == '__main__':
pytest.main(['--alluredir', 'testreport/temps', '--clean-alluredir'])
# --clean: 表示执行一次,要把原来的清楚一遍
写在pytest.ini文件中格式
addopts = -vs --alluredir=testReport/temps --clean-alluredir
第二:依据临时json报告生成allure报告
os.system("allure generate reports/temp -o report/allures --clean")
# --clean: 表示执行一次,要把原来的清楚一遍
3、allure报告-定制化
3.1、设置logo图标
第一:添加自定义logo插件
修改:将 /allure-2.9.0/config路径下的 allure.yml 文件 --> 添加到 /allure-2.9.0/plugins路径下 /custom-logo-plugin 文件夹(插件)中
(简单说:在allure.yml中添加custom-logo-plugin)
plugins文件目录:
- junit-xml-plugin
- xunit-xml-plugin
- trx-plugin
- behaviors-plugin
- packages-plugin
- screen-diff-plugin
- xctest-plugin
- jira-plugin
- xray-plugin
- custom-logo-plugin
第二:修改logo样式
文件路径:file:allure-2.9.0/plugins/custom-logo-plugin/static/styles.css(重新编写样式)
// 原始样式
/*
.side-nav__brand {
background: url('custom-logo.svg') no-repeat left center;
margin-left: 10px;
}
*/
//自定义样式
.side-nav__brand{
background: url('17house_logo.jpg') no-repeat left center !important;
margin-left: 70px;
height: 75px;
background-size: contain !important;
}
.side-nav__brand-text{
display: none;
}
注意:
1、指定 “logo图片” --图片存放在allure-2.9.0/plugins/custom-logo-plugin/static目录下
2、自定义边距
margin-left: 25px; // 调节左边像素
height: 80px; // 高
[功能:--->左边定制]
3.2、设置项目、模块、用例标题(别名)
1.史诗(项目名称):@allure.epic("项目名称:xxx公司-接口自动化测试")
2.特性(模块名称):@allure.feature("模块名称:用户管理模块")
3.分组(接口名称): @allure.title("接口名称:查询商品")
4.测试用例名称(2种):
(1)@allure.feature("测试用例别名:输入正确的条件-查询成功")
【注意】:适用于一个方法对应一个用例
(2)allure.dynamic.title("测试用例标题:输入错误的条件-查询失败")
【注意】:使用于一个方法对应多个用例,也就是使用数据驱动的情况
代码示例:
# 导包
import pytest, allure
@allure.epic("项目名称:xxx公司-接口自动化测试") # 添加装饰器,设置项目名称
@allure.feature("模块名称:用户管理模块") # 设置模块名称
class TestApi_demo:
@allure.title("接口名称:查询商品") # 设置接口名称
# 设置测试用例报告展示的名称
@allure.feature("测试用例别名:输入正确的条件-查询成功") # 方式一
def test_func_01(self):
print('我是测试用例函数----01')
def test_func_02(self):
allure.dynamic.title("测试用例标题:输入错误的条件-查询失败") # 方式二
print('我是测试用例函数-----02')
功能:-->右边定制
4、用例的严重程度
@allure.severity(allure.severity_level.BLOCKER):可以修饰方式,也可以修饰类
用例的严重程度解释:
- blocker:中断缺陷(内存泄漏、致命bug、用户数据丢失、系统崩溃)
- critical:临界缺陷,严重bug(功能为实现、功能错误、重复提交)
- normal:一般缺陷,一般bug(条件查询错误、无响应等)
- minor:次要级别(提示bug、颜色搭配不好、字体排列不整齐、错别字)
- Trivial:轻微缺陷,轻微bug(没有使用专业术语,必须项无提示,建议性问题)
代码示例:
# 导包
import pytest, allure
class TestApi_demo:
# 设置用例级别
@allure.severity(allure.severity_level.BLOCKER)
def test_func_01(self):
print('我是测试用例函数----01')
@allure.severity(allure.severity_level.CRITICAL)
def test_func_02(self):
print('我是测试用例函数-----02')
===如果将类下面的所有用例都设置一个界别=========================
# 导包
import pytest, allure
# 设置用例级别
@allure.severity(allure.severity_level.BLOCKER)
class TestApi_demo:
def test_func_01(self):
print('我是测试用例函数----01')
def test_func_02(self):
print('我是测试用例函数-----02')
5、用例的描述
添加用例描述有两种方式
- @allure.description("测试用例描述:方式一")
- allure.dynamic.description("测试用例描述:方式二")
第一种: 同一个方法多个接口,共用一个描述
import allure
class TestApi_002:
# 添加用例描述
@allure.description("测试用例描述:方式一")
def test_func1(self):
print(f"我是测试用例func1")
# 设置接口名称
@allure.title("接口名称:查询商品")
def test_func2(self):
allure.dynamic.description("测试用例描述:方式二")
print(f"我是测试用例func2")
第二种: 同一个方法多个接口,根据每个接口,自定义描述
import allure
class TestApi_002:
def test_func1(self):
print(f"我是测试用例func1")
def test_func2(self):
# 设置用例描述
allure.dynamic.description("测试用例描述:方式二")
print(f"我是测试用例func2")
6、用例链接,bug链接,接口地址
-
设置用例接口地址
@allure.link(name="接口地址", url='百度一下,你就知道')
-
设置bug链接
@allure.issue(name='bug地址', url='xxxx')
-
设置用例地址
@allure.testcase(name='测试用例地址', url='xxxx')
import pytest, allure
class TestApi_demo1:
# 设置接口名称
@allure.title("接口名称:查询商品-成功")
# 设置用例级别
@allure.severity(allure.severity_level.BLOCKER)
# 设置用例的链接
# 设置用例接口地址
@allure.link(name="接口地址", url='https://www.baidu.com/')
# 设置bug链接
@allure.issue(name='bug地址', url='xxxx')
# 设置用例地址
@allure.testcase(name='测试用例地址', url='xxxx')
def test_func_01(self):
allure.dynamic.title("测试用例别名:输入正确的条件-查询成功")
print('我是测试用例函数----01')
7、测试步骤的定制
方式一:
@allure.step('xxx')
# 导包
import pytest, allure
class TestApi_demo1:
# 添加用例步骤
@allure.step("步骤一:1、登陆 2、输入商品信息 3、点击【搜索】")
def test_func_02(self):
allure.dynamic.title("测试用例标题:输入错误的条件-查询失败")
print('我是测试用例函数-----02')
方式二:
with allure.step("测试用例步骤"):
print('测试步骤下执行的代码')
# 导包
import pytest, allure
class TestApi_demo1:
def test_func_01(self):
with allure.step("测试用例步骤"):
print('测试步骤下执行的代码')
8、附件的定制
1、web-自动化执行过程中的截图展示在allure报告中
参数:body:附件内容, name:文件别名, attachment_type:文件拓展名
allure.attach(body=f.read(), name='错误截图', attachment_type=allure.attachment_type.JPG
import allure
class TestApi_allure:
def test_func2(self):
allure.dynamic.description("测试用例描述:方式二")
print(f"我是测试用例func2")
# 定制附件:
with open(r"/Users/xiangzp/Desktop/Python_pytest_xuexi/17house.jpg", mode='rb') as f:
allure.attach(body=f.read(), name='错误截图', attachment_type=allure.attachment_type.JPG)
2、接口-自动化,执行过程数据展示在allure报告中
可以将接口的响应信息展示在报告
import pytest, allure, requests
class TestApi_allure:
def test_func1(self):
print(f"我是测试用例func1")
# 接口自动化测试-附件展示
# 请求地址
allure.attach(body='https://www.wanandroid.com/user/login', name='请求地址', attachment_type=allure.attachment_type.TEXT)
# 请求方式
allure.attach(body='GET', name='请求方式', attachment_type=allure.attachment_type.TEXT)
# 响应结果
data = {
"username": "xiangzp01",
"password": "123455@xzp"
}
res = requests.post(url="https://www.wanandroid.com/user/login", json=data)
allure.attach(body=res.json(), name='响应结果', attachment_type=allure.attachment_type.TEXT)
9、前置、后置、日志
allure会自动化将代码中使用的fixture()的用例,展示出来
日志也会自动展示在报告中
import pytest
@pytest.fixture(scope="function")
def login():
print("用户登陆-----登陆成功")
yield
print('退出登陆------')
@pytest.fixture(scope="function")
def func11():
print('-----------')
4、allure报告如何在本地访问
pycharm自带容器:(tomcat、Nginx、web logic )
- 1、在本地搭建服务器
- 2、通过启动服务,打开allure报告
在当前目录下输入命令:
allure open ./testReport/allures
./testReport/allures:allure报告路径
(Python_pytest_xuexi) xiangzp@bogon Python_pytest_xuexi %: allure open ./testReport/allures
Starting web server...
2023-11-26 13:12:52.392:INFO::main: Logging initialized @418ms to org.eclipse.jetty.util.log.StdErrLog
Server started at <http://192.168.0.101:57913/>. Press <Ctrl+C> to exit
常用的:allure报告结构定制
- @allure.epic:敏捷里面的概念,定义史诗,相当于module级的标签
- @allure.feature:功能点的描述,可以理解成模块,相当于class级的标签
- @allure.story:故事,可以理解为场景,相当于method级的标签
左边:
(1)项目名称(史诗):@allure.epic("码尚教育自动化测试报告")
(2)模块名称(特性):@allure.feature("用户管理模块")
(3)接口名称(分组):@allure.story("增加用户接口")
(4)用例标题:有两种方式,一般用第二种。allure.dynamic.title("验证成功增加商品")
右边:
(1)测试用例步骤+附件:一般用于错误截图(一般用于web自动化测试)
(2)文本内容的定制:一般应用于接口自动化
pytest中钩子函数
钩子函数详解:
参考博客: