pytest简介——深入分析
一.pytest单元测试框架
1.什么是单元测试框架
单元测试是指在软件开发当中,针对软件的最小单位(函数,方法)进行正确性的检查测试。
2.单元测试框架
java:junit和esting
python:unitest和pytest
3.单元测试框架主要做什么?
(1). 测试发现:从多个文件里面去找到我们的测试用例
(2). 测试执行:按照一定的顺序和规则去执行,并生成结果
(3). 测试判断:通过断言判断预期结果和实际结果的差异
(4). 测试报告:统计测试进度,耗时,通过率,生成测试报告
二.单元测试框架和自动化测试框架有什么关系?
1.什么是自动化测试框架
2.作用
(1). 提高测试效率,降低维护成本
(2). 减少人工干预,提高测试的准确性,增加代码的重用性
(3). 核心思想是让不懂代码的人也能够通过这个框架去实现自动化测试
3.pytest单元测试框架和自动化测试框架的关系
单元测试框架:只是自动化测试框架中的组成部分之一。
pom设计模式:只是自动化测试框架中的组成部分之一。
数据驱动:只是自动化测试框架中的组成部分之一。
关键字驱动:只是自动化测试框架中的组成部分之一。
全局配置文件的封装:只是自动化测试框架中的组成部分之一。
日志监控:只是自动化测试框架中的组成部分之一。
selenium,request二次封装:只是自动化测试框架中的组成部分之一。
断言:只是自动化测试框架中的组成部分之一。
报告邮件:只是自动化测试框架中的组成部分之一。
更多....................。
三.pytest简介
1.pytest是一个非常成熟的python的单元框架。比unittest更灵活,容易上手
2.pytest可以和selenium,requests,appium结合实现web自动化,接口自动化,app自动化
3.pytest 可以实现测试用例的跳过以及reruns失败用例重试
4.pytest可以和allure生成非常美观的测试报告
5.pytest可以和jenkins持续集成
6.pytest有很多非常强大的插件,并且这些插件能够实现很多实用的操作
插件:
(1). pytest-html 生成html格式的自动化测试报告
(2). pytest-xdist 测试用例分布式执行,多cpu分发
(3). pytest-ordering 用于改变测试用例的执行顺序
(4). pytest-rerunfailures 用例失败后重跑
(5). allure-pytest 用于生成美观的测试报告
安装:
在项目目录中新建一个文件,一般叫做requirements.txt ,将插件名称放到txt中,
在terminal中输入pip install -r requirements.txt
requirements.txt中的内容如下:
pytest
pytest-html
pytest-xdist
pytest-ordering
pytest-rerunfailures
allure-pytest
注意:这个安装是局部的,仅仅是我们的项目中,如果想要安装全局的,需要在dos中进行执行。
四.pytest使用,默认的测试用例的规则以及基础应用
1.模块名必须以test_ 开头或者_test 结尾
2.测试类必须以Test开头,并且不能有init方法
3.测试方法必须以test开头
例如:
五.pytest测试用例的运行方式
1.主函数模式
上面的方式是打印不出来print中的内容的
我们需要在main中加参数,例如:
(1). 运行所有
if __name__ == '__main__':
pytest.main(['-s'])
这样就能打印出来了。
2.命令行模式
在这个终端中输入pytest,即可执行用例。
(1). 运行所有 pytest
(2). 指定模块 pytest -vs test_login.py
(3). 指定目录 pytest -vs ./interface_testcase
(4). 指定目录 pytest -vs ./interface_testcase/test_interface.py::TestInterface::test_03_zhiliao
参数详解:
-s:表示输出调试信息,包括print打印的信息
-v:打印更详细的信息
-vs:这两个参数可以一起用
-n:支持多线程或者分布式运行测试用例
例如:
import pytest
if __name__ == '__main__':
pytest.main(['-vs','./testcase','-n=2'])
--reruns NUM:失败用例重跑
import pytest
if __name__ == '__main__':
pytest.main(['-vs','./testcase','--reruns=2'])
-x :表示有一个用例报错,那么测试停止
--maxfail=2:出现两个用例失败就停止
-k: 根据测试用例的部分字符串指定用例
--html ./report/report.html:生成html的测试报告
(2). 指定模块
如果想在all.py中指定模块
import pytest
if __name__ == '__main__':
pytest.main(['-sv','test_login.py'])
这样指定即可
(3). 指定目录
将all.py放在最外面,又创建了一个interface_testcase这个包,包里面是一个test_interface.py模块,模块下,创建了类和方法。
那么执行在all文件下指定包名也可以执行里面的用例。
(4).通过nodeid指定用例运行:nodeid由模块名,分隔符,类名,方法名,函数名组成。
if __name__ == '__main__':
pytest.main(['-vs','./interface_testcase/test_interface.py::test_04_func'])
注意:模块和函数之间使用::这个符号隔开,然后如果想执行“测试知了”,需要带上类名。
if __name__ == '__main__':
pytest.main(['-vs','./interface_testcase/test_interface.py::TestInterface::test_03_zhiliao'])
3.通过读取pytest.ini全局配置文件运行
pytest.ini这个文件是pytest单元测试的配置文件。
1.位置:一般放在项目的根目录
2.编码:必须是ANSI,可以使用notpad++修改编码格式。
3.作用:改变pytest默认的行为
4.运行的规则:不管是主函数的模式运行,命令行模式运行,都会去读这个配置文件。
[pytest]
addopts= -vs #命令行的参数,用空格分隔
testpaths = ./testcase #测试用例的路径
python_files=test*.py #模块名的规则
python_classes = Test* #类名的规则
python_functions = test #方法名的规则
六.pytest执行用例的顺序是怎么样的?
unittest:ascll的大小来绝对的执行的顺序
pytest:默认从上到下
@pytest.mark.run(order=),这个可以改变用例的执行顺序。
七.如何分组执行(冒烟,分模块执行,分接口和web执行)
smoke:冒烟用例,分布在各个模块里面
命令行执行:pytest -m "smoke or usermanage"
[pytest]
addopts= -vs --html ./report/report.html
testpaths = ./testcase
python_files=test*.py
python_classes = Test*
python_functions = test
markers =
smoke:冒烟用例
usermanage:用户管理模块
productmange:商品管理模块
八.pytest跳过测试用例
(1).无条件跳过
@pytest.mark.skip(reason="百里不老实")
(2).有条件跳过
@pytest.mark.skipif(age>=18,reason="已成年")
九.pytest框架实现一些前后置(固件,夹具)的处理,常用三种
1. setup/teardown,setup_class/teardown_class
为什么需要这些功能?
比如:web自动化执行用例之前,请问需要打开浏览器
import time
import pytest
class TestLogin:
def setup_class(self):
print("在每个类执行前的初始化的工作:比如:创建日志对象,创建数据库链接,创建接口的请求对象")
def setup(self):
print('\n在执行测试用例之前初始化的代码:打开浏览器,加载网页')
@pytest.mark.run(order=5)
def test_01_baili(self):
print("测试百里")
@pytest.mark.run(order=4)
def test_02_xiaohai(self):
print("测试小海")
@pytest.mark.run(order=3)
def test_03_xiaoze(self):
print("测试小泽")
@pytest.mark.run(order=2)
def test_05_xiaohao(self):
print("测试小号")
@pytest.mark.run(order=1)
def test_04_xiaotao(self):
print("\n测试小涛")
def teardown(self):
print('\n在执行测试用例之后的扫尾的代码:关闭浏览器')
def teardown_class(self):
print("在每个类执行后的扫尾工作:比如:销毁日志对象,销毁数据库连接,销毁接口的请求对象")
注意:和Unitest不一样,全是小写
2.使用@pytest.fixture()装饰器来实现部分用例的前后置
@pytest.fixture(scope="",params="",autouse="",ids="",name="")
结构如此:
scope表示的是被@pytest.fixture标记的方法的作用域。function(默认),class,module,package/session.
params:参数化(支持,列表,元组,字典列表,字典元组)
autouse=True:自动执行,默认False
ids:当使用params参数化时,给每个值设置一个变量名。意义不大。
name:表示的是被@pytest.fixture标记的方法取一个别名。
@pytest.fixture(scope='function',params=['成龙','甄子丹'])
def my_fixture(request):
"这个位置可以加个前置,例如放一个print('这是前置的方法')"
"yield是用来加后置的,一般在yield下面放输出的内容即可"
return request.param
class TestLogin:
def test_01_baili(self):
print("测试百里")
def test_02_xiaohai(self):
print("测试小海")
def test_03_xiaoze(self):
print("测试小泽")
def test_05_xiaohao(self):
print("测试小号")
def test_04_xiaotao(self,my_fixture):
print("\n测试小涛")
print('.............'+str(my_fixture))
注:return和yield都表示返回的意思,但是return的后面不能有代码,,yield返回后,后面可以加代码。
@pytest.fixture(scope='function',params=['成龙','甄子丹'])
def my_fixture(request):
# "这个位置可以加个前置,例如放一个print('这是前置的方法')"
#"yield是用来加后置的,一般在yield下面放输出的内容即可"
#return request.param
print('前置')
yield request.param
print('后置')
class TestLogin:
def test_01_baili(self):
print("测试百里")
def test_02_xiaohai(self):
print("测试小海")
def test_03_xiaoze(self):
print("测试小泽")
def test_05_xiaohao(self):
print("测试小号")
def test_04_xiaotao(self,my_fixture):
print("\n测试小涛")
print('.............'+str(my_fixture))
注:上面的代码实现了前后置和参数化一起用。
import time
import pytest
@pytest.fixture(scope='function',params=['成龙','甄子丹'],ids=('cl','zzd'))
def my_fixture(request):
# "这个位置可以加个前置,例如放一个print('这是前置的方法')"
#"yield是用来加后置的,一般在yield下面放输出的内容即可"
#return request.param
print('前置')
yield request.param
print('后置')
class TestLogin:
def test_01_baili(self):
print("测试百里")
def test_02_xiaohai(self):
print("测试小海")
def test_03_xiaoze(self):
print("测试小泽")
def test_05_xiaohao(self):
print("测试小号")
def test_04_xiaotao(self,my_fixture):
print("\n测试小涛")
print('.............'+str(my_fixture))
注:上面代码演示了ids的使用。下面展示变化内容。给每一个值设置了一个变量名
给这个unicode这个值改成自己想要的。
import time
import pytest
@pytest.fixture(scope='function',params=['成龙','甄子丹'],ids=('cl','zzd'),name='aaa')
def my_fixture(request):
# "这个位置可以加个前置,例如放一个print('这是前置的方法')"
#"yield是用来加后置的,一般在yield下面放输出的内容即可"
#return request.param
print('前置')
yield request.param
print('后置')
class TestLogin:
def test_01_baili(self):
print("测试百里")
def test_02_xiaohai(self):
print("测试小海")
def test_03_xiaoze(self):
print("测试小泽")
def test_05_xiaohao(self):
print("测试小号")
def test_04_xiaotao(self,aaa):
print("\n测试小涛")
print('.............'+str(aaa))
注:上面的内容展示的是通过name给标记起了一个别名。
3.通过conftest.py和@pytest.fixture()结合使用实现全局前置应用(比如:项目的全局登录,模块的全局处理)
(1). conftest.py文件是单独存放的一个夹具配置文件,名称不能更改。
(2). 用处可以在不同的py文件中使用同一个fixture函数。
(3). 原则上conftest.py需要和运行的用例放到同一层,并且不需要做任何的import导入的操作
总结:setup/teardown,setup_class/teardown_class,他是作用于所有用例或者所有的类
@pytest.fixture(),他的作用是既可以部分也可以全部前后置
conftest.py和@pytest.fixture()结合使用,作用于全局的前后置
4.断言
assert
5.pytest结合allure-pytest插件生成allure测试报告
(1).下载,解压,配置path路径
(2). 加入命令生成json格式临时报告
[pytest]
addopts= -vs --alluredir ./temp
testpaths = ./testcase
python_files=test*.py
python_classes = Test*
python_functions = test
markers =
smoke:冒烟用例
usermanage:用户管理模块
productmange:商品管理模块
(3).生成allure报告
os.system('allure generate ./temp -o ./report --clean')
allure generate 命令,固定的
./trmp 临时的json格式报告的路径
-o 输出output
/report 生成的allure报告的路径
-clean 清空./report 路径原来的报告
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!