初识pytest
pytest单元测试框架
(1)什么是单元测试框架?
单元测试是指在软件开发过程当中,针对软件的最小单位(函数、方法)进行正确性的检查测试。
(2)单元测试框架主要做什么?
1. 测试发现:从多个文件里面找到我们的测试用例
2. 测试执行:按照一定的规则和顺序去执行,并生成结果
3. 测试判断:通过断言判断预期结果和实际结果的差异
4. 测试报告:统计测试进度,耗时,通过率,生成测试报告
单元测试框架和自动化测试框架有什么关系?
(1)什么是自动化测试框架
(2)作用?
1. 提高测试效率,降低维护成本
2. 减少人工干预,提高测试准确性,增加代码的重用性
3. 核心思想是让不懂代码的人也能通过框架去实现自动化测试
(3)pytest单元测试框架和自动化测试框架的关系?
1. 单元测试框架:只是自动化测试框架的组成部分之一
2. pom设计模式:只是自动化测试框架的组成部分之一
数据驱动。。。
关键字驱动文件的封装
日志监控
requests二次封装
断言
报告邮件
.....
pytest简介
1. pytest是一个非常成熟的python单元测试框架,比unittest更灵活,更容易上手
2. pytest可以和selenium,requests,appium结合实现web、接口、app自动化
3. pytest可以实现测试用例的跳过以及reruns失败用例重试
4. pytest可以和allure生成测试报告
5. pytest可以和jenkins持续集成
6. pytest有很多强大的插件,并且这些插件能够实现很多使用的操作
pytest插件:
插件名 | 作用 |
---|---|
pytest-html | 生成html格式的自动化测试报告 |
pytest-xdist | 测试用例分布式执行,cpu分发 |
pytest-ordering | 用于改变测试用例的执行顺序 |
pytest-rerunfailures | 测试用例失败后重跑 |
allure-pytest | 用于生成测试报告 |
pytest规则以及基础应用
1. 模块名必须以test_开头或者_test结尾
2. 测试类必须以Test开头,并且不能init方法
3. 测试方法必须以test开头
pytest测试用例的运行方式
pytest 参数 | 详解 |
---|---|
-s | 表示输出调试信息,包括print打印的信息 |
-v | 显示更详细的信息 |
-n | 指定分布式运行测试用例(指定线程数即可) |
- -reruns | 失败用例重跑(指定重跑数量) |
-x | 只要有一个测试用例报错就停止 |
- -maxfail=2 | 出现两个测试用例失败就停止 |
-k | 根据测试用例部分字符串指定测试用例 |
-q | 安静标志在此处和以下示例中保持输出简短。 |
1. 主函数模式
(1)运行所有:pytest.main()
(2)指定模块:pytest.main(['-vs','test_login.py'])
(3)指定目录:pytest.main(['-vs','./interface_testcase'])
(4)通过nodeid指定用例运行:nodeid由模块名、分隔符、类名、方法名、函数名组成。
pytest.main('-vs','./interface_testcase/test_interface.py::test_04_func') # 执行函数
pytest.main('-vs','./interface_testcase/test_interface.py::TestInterface::test_03_test') # 执行方法
**2. 命令行模式**
(1)运行所有: pytest
(2)指定模块:pytest -vs test_login.py
(3)指定目录:pytest -vs ./interface_testcase
(4)指定函数:pytest -vs ./interface_testcase/test_interface.py::test_04_func
(5)执行方法:pytest -vs ./interface_testcase/test_interface.py::TestInterface::test_03_test
**3. 通过读取pytest.ini配置文件运行**
(1)pytest.ini 文件时pytest单元测试框架的核心配置文件。
(2)位置:一般存放与项目的根目录
(3)编码:必须是ANSI,可以使用notpad++修改编码格式
(4)作用:改变pytest默认的行为规则
(5)运行规则:不管是主函数的模式运行或者命令行的模式运行,都回去读取这个文件
[pytest]
addopts = -vs # 命令行的参数用空格分隔
testpaths = ./testcase #测试用例的路径
python_file = test_*.py #模块名的规则
python_classes = Test* #类名的规则
python_functions = test #方法名的规则
pytest测试用例运行顺序
pytest测试运力从上至下以此执行,可用通过@pytest.mark.run(order=3)
装饰器设置测试用例执行的顺序,该装饰器依赖于pytest-ordering插件 使用时需提前安装
测试用例分组执行(冒烟,分模块执行,分接口和web执行)
somke:冒烟用例,分布在各个模块里面
pytest固件代码
setup_class()在每个测试类之前会执行一次
teardown_class() 在每个测试类执行完成后会执行一次
setup()每个测试用例之前会执行一次
teardown()每个测试用例执行之后会执行一次
# -*-coding:utf-8 -*-
# @Author : Lwd_charles
# @File : test_tfsec.py
# @ Version : 1.0
class TestLwd:
#在所有用例前只执行一次
def setup_class(self):
print('\n在每个类之前执行的初始化工作...# 创建日志对象,创建数据库连接,创建接口请求对象')
# 固件
def setup(self):
print('\n在执行测试用例之前执行的代码...')
def test_001(self):
print('这是001')
def test_002(self):
print('这是002')
def teardown(self):
print('\n在测试用例执行之后执行的代码')
def teardown_class(self):
print('在每个类之后执行一次 进行扫尾工作')
使用@pytest.fixture()装饰器实现部分用例的前后置
# -*-coding:utf-8 -*-
# @Author : Lwd_charles
# @File : test_tfsec.py
# @ Version : 1.0
import pytest
# @pytest.fixture(scope="",params="",autouse="False",ids="",name="")
'''
(1) scope 表示的被@pytest.fixture标记的方法的作用域,function(默认),class,module
(2) params 参数化 (列表[],元组(),字典列表[{},{}],字典元组{},{},{})
(3)autouse = True 自动使用,默认False
(4) id 当使用params参数化时,给每一个值设置一个变量名
(5)name 给表示的 是被@pytest.fixture标记的方法取一个别名
'''
# 函数 yield实现后置条件
#@pytest.fixture(scope='class,module,function',autouse=True)
@pytest.fixture(scope='module',autouse=True)
def test_fixture():
print('前置条件')
yield
print('后置条件')
class TestLwd:
def test_001(self):
print('\n这是001')
def test_002(self):
print('\n这是002')
通过conftest.py 和@pytest.fixture()结合使用,实现 全局 前置应用(比如:项目的全局登录,模块的全局处理)
1.conftest.py文件是一个单独存放的夹具配置文件,名称是不可更改的,需要在测试用例层级新建 conftest.py文件
2.用处,可在不同文件的py文件中使用同一个fixture函数
3.conftest.py 需要和运行的用例放到同一层,并且不需要任何的import导入操作
conftest.py夹具文件需要和用例放在同一个目录,也可以为每个单独的模块测试用例文件夹内放置一个,也可在项目的根目录放置一个全局的夹具供全局使用。
代码如下:
conftest.py 文件示例
# -*-coding:utf-8 -*-
# @Author : Lwd_charles
# @File : conftest.py
# @ Version : 1.0
import pytest
@pytest.fixture(scope="function")
def test_user_manager():
print("\r用户管理前置条件")
yield
print("\r用户管理后置条件")
test_user_manager.py 文件示例
# -*-coding:utf-8 -*-
# @Author : Lwd_charles
# @File : test_user_manager.py
# @ Version : 1.0
class TestUserManager:
def test_del_user(self,test_user_manager):
print("删除用户成功")
def test_ins_user(self,test_user_manager):
print("添加用户成功")
全局夹具代码:
# -*-coding:utf-8 -*-
# @Author : Lwd_charles
# @File : conftest.py.py
# @ Version : 1.0
import pytest
@pytest.fixture(scope='module')
def all_tianhui():
print('全局项目前置条件')
yield
print('全局项目后置条件')
测试用例可以同时引用多个夹具,夹具优先级按照引用顺序为准
断言
assert 1 == 2
pytest结合allure-pytest插件生成allure测试报告
步骤 下载-解压-配置path路径
下载路径:
https://github.com/allure-framework/allure2/releases
验证: allure --version
1、 --alluredir ./temp 加入生成allure json临时文件
2、 生成allure报告
os.system('allure generate ./temp -o ./report --clean') #生成allure报告
allure | 作用 |
---|---|
allure generate | # 固定命令 |
./temp | #临时的json格式报告的路径 |
-o | # 输出output |
./report | #生成allure报告的路径 |
–clean | #清空原有的报告 |
pytest数据驱动
# -*-coding:utf-8 -*-
# @Author : Lwd_charles
# @File : run.py
# @ Version : 1.0
import pytest
from utils.requestsutil import RequestSend
class TestDemo:
@pytest.mark.parametrize('args',['lwd','cd','wzg'])
def test_user(self,args):
print(args)
@pytest.mark.parametrize('args,age',[['lwd',20],['cd',21],['wzg',22]])
def test_user2(self,args,age):
print(age,args)
if __name__ == '__main__':
pytest.main(['-vs'])