Pytest学习笔记

未编辑完毕,有时间再把格式搞好
要分p,细化,加代码细节以及项目细节--参考极客时间的文章

简述

支持简单的单元测试和复杂的功能测试
可以结合 Requests 实现接口测试; 结合 Selenium、Appium 实现自动化功能测试
结合 Allure 集成到 Jenkins 中可以实现持续集成
支持参数化
支持测试用例的skip和xfail,自动失败重试等处理

支持 315 种以上的插件

报告:Allure
多线程:distributed testing plugin)
用例执行顺序控制:pytest-ordering
多CPU分发:pytest-xdist

插件举例
	pytest-xdist  分布式并发执行测试用例(重点)
	pytest-ordering 控制用例的执行顺序(重点)
	pip install pytest-dependency   控制用例的依赖关系 (了解)
	pytest-rerunfailures  失败重跑(了解)
	pytest-assume  多重较验(了解)
	pytest-random-order  用例随机执行(了解)
	pytest-html  测试报告(了解)

格式规范

Python风格规范-Google开源项目风格指南
https://zh-google-styleguide.readthedocs.io/en/latest/google-python-styleguide/python_style_rules/

测试用例编写规则

文件 -- test_开头 或者 _test 结尾
类 -- Test 开头
方法/函数 -- test_ 开头

ps: 函数(function):在类外部 / 方法(method):在类内部
测试类中不可以添加__init__构造函数

pycharm 配置与界面化运行
安装 Pytest: Project -> python Interpreter -> + -> 添加pytest
默认测试执行器为Pytest
进入 Tools->Python Intergrated Tools
选择 Default test runner 为 pytest

pytest测试装置
模块级 -- setup_module/teardown_module
模块始末,全局的(优先最高)
类级 -- setup_class/teardown_class
只在类中前后运行一次(类中)(重点)
函数级 -- setup_function/teardown_function
只对函数用例生效 (类外)
方法级 -- setup_method/teardown_methond
开始于方法始末(类中)
类中 -- setup/teardown
运行在调用方法的前后(重点)

用例运行
terminal运行(python解释器)
执行包下所有的用例:pytest/py.test [包名]
执行单独一个pytest模块:pytest 文件名.py
运行某个模块里面某个类:pytest 文件名.py::类名
运行某个模块里面某个类里面的方法:
pytest 文件名.py::类名::方法名
pytest.main函数(python解释器)
if name == 'main':
pytest.main(['test_mark.py::test_case2', '-vs'])
pytest.main(['test_search.py', '-vs', '-m', 'str'])

运行方式
python test_.py
使用 python -m pytest test_
.py 调用pytest(jenkins持续集成用到)
运行结果
常用的:fail/error/pass
特殊的结果:warning(警告)/deselect(未选中)
常用命令行参数
pytest --help
pytest -v 打印详细日志
pytest -s 打印输入日志(一般-vs使用)
pytest -x 文件名 一旦运行到报错,就停止 运行
pytest --maxfail=[num] 当运行错误达到num时停止运行
pytest -k "关键字” 执行某个关键字的测试用例
pytest -m [标记名]
@pytest.mark.[标记名] 将运行有这个标记的测试用例
场景:只执行符合要求的某一部分用例 可以把一个web项目划分多个模块,然后指定模块名称执行。
解决: 在测试用例方法上加 @pytest.mark.标签名
执行: -m 执行自定义标记的相关用例
pytest -s test_mark_zi_09.py -m=webtest
pytest -s test_mark_zi_09.py -m apptest
pytest -s test_mark_zi_09.py -m "not ios"
pytest无法识别自定义的标签,解决方法:创建pytest.ini文件,列举自定义的标签
[pytest]
markers = str
int
Mark:跳过(skip) 预期失败(xFail)
pytest的内置标签,可以处理一些特殊测试用例
skip -- 始终跳过该用例
添加装饰器 @pytest.mark.skip
在代码中跳过 pytest.skip(reason)
skipif -- 遇到特定情况跳过该测试用例
xfail -- 遇到特定情况,产生一个“期望失败”输出
预期结果为fail ,标记用例为fail
用法:添加装饰器@pytest.mark.xfail
pytest --lf, --last-failed 只运行上一次执行失败的用例
pytest --ff, --failed-first
先执行上一次失败的用例,后执行上一次成功的用例
pytest --collect-only
(测试平台,pytest 自动导入功能 )
pytest - - junitxml=./result.xml
生成执行结果文件
pytest --setup-show 回溯fixture的执行过程
pytest.ini 配置
[pytest]
markers 自定义mark 标签名
addopts 运行时参数(可添加多个命令行参数,空格分隔,所有参数与命令行一致)
python_files 自定义测试文件命名规则
python_classes = Test_* 自定义测试类命名规则
python_functions= test_* check_* 自定义测试方法命名规则
testpaths = bilibili baidu
norecursedirs = result logs datas test_demo* 运行时忽略某些文件夹

参数化
将模型中的定量信息变量化,使之成为任意调整的参数;
对于变量化参数赋予不同数值,就可得到不同大小和形状的零件模型
参数化测试函数使用
单参数
@pytest.mark.parametrize('a',a_list)
多参数
@pytest.mark.parametrize('a,b', [ (1,1), (2,3)])
用例重命名
ids参数增加可读性
@pytest.mark.parametrize('a', [1,2],
ids = ['name1','name2'])
ids与传递数据个数相等
笛卡尔积
@pytest.mark.parametrize('wd', ["appium", "selenium", "pytest"])
@pytest.mark.parametrize('code', [1, 2, 3])
def test_cast(wd, code):
print(f"wd:{wd}, code:{code}")
数据驱动--yaml文件导入数据
@pytest.mark.parametrize(['a','b'],
yaml.safe_load(open('./data.yml')))
yaml用法

异常处理
try…except
pytest.raises()
可以捕获特定的异常
获取捕获的异常的细节(异常类型,异常信息)
发生异常,后面的代码将不会被执行

fixture
提供一个测试的基线,在此基线基础上,可以更可靠的进行重复测试
简述
测试fixture有明确的名称,通过在函数/模块/类或者整个项目中激活来使用 。
测试fixture是模块化的实现,使用fixture名即可触发特定的fixture,fixture可以在其他fixture中 进行使用 。
测试fixture不仅可以进行简单的单元测试,也可以进行复杂的功能测试。可以根据配置和组件的 选项进行参数化定制测试,或者跨函数/类/模块或者整个测试过程进行测试。
用法
函数通过装饰器标志@pytest.fixture注册
@pytest.mark.usefixtures('fixture1','fixture2') -- 适合测试类
两者区别
使用usefixtures和在测试方法中添加fixture参数,区别之一在于只有后者才能够使用fixture的返回值
conftest.py:共享fixture函数
pytest自动检索
fixture函数的检索顺序是从测试类开始,然后测试的模块,然后就是conftest.py文件,最后是内置的插件和第三方插件
scope:在类/模块/整个测试中共享fixture实例
用于控制fixture执行配置和销毁逻辑的频率
@pytest.fixture(scope="module")
scope值 -- function, class, module, package, session
scope='function':函数级别的fixture每个测试函数只需要运行一次。配置代码在测试用例运行之前运行,销毁代码在测试用例运行之后运行。
scope='class':类级别的fixture每个测试类只需要运行一次。无论测试类里有多少类方法都可以共享这个fixture。
scope='module':模块级别的fixture每个模块只需要运行一次。无论模块里有多少类方法都可以共享这个fixture。
scope='session':会话级别的fixture每个会话只需要运行一次。一次pytest会话中的所有测试函数、方法都可以共享这个fixture。
ps: Pytest对于每个fixture只会缓存一个实例,这意味着如果使用参数化的fixture,pytest可能会比定义的作用域更多次的调用fixture函数(因为需要创建不同参数的fixture)
autouse=True
yield
完成return的动作,返回数据
并记录了上一次的执行位置,下一次继续使用该位置执行
param
fixture 中的param相当于数据的载体,会将数据一条一条载入测试数据中
param放在函数装饰器中,函数本身不会return param中的数据,函数需要增加request的参数,然后返回request.param返回数据
fixture退出作用域时执行相关的清理/结束代码
使用yield而不是return关键字的时候,yield后面的语句将会在fixture退出作用域的时候被调用来清理测试用例
参考地址:https://juejin.cn/post/6910762367533973517
pytest --setup-show回溯fixture的执行过程
F代表函数级别的作用范围,S代表会话级别的作用范围
S 表示 session 即会话级别,M 表示 module 级别,C 表示 class 级别,F 表示 function 级别
pytest --fixtures test_fixture.py
查看可用的fixture(查看以_开头的fixture, -v参数)
使用fixture的优势在于:用户在编写测试函数时可以只考虑核心测试逻辑,而不需要考虑测试前的准备工作

Allure
介绍
轻量级,灵活,支持多语言的测试报告工具
多平台的report框架
可以为dev/QA提供详细的测试报告,测试步骤,log
可以为管理层提供测试统计报告
JAVA语言开发的,支持pytest,JavaScript,PHP,ruby等
可以集成到Jenkins
运行
1、生成中间结果
2、解析成最终报告 allure serve ./report
3、allure generate ./report
测试执行收集结果 pytest -s -q --alluredir=./report/
--alluredir用于指定存储测试结果的路径
查看测试报告
方式一:在线查看报告,直接打开默认浏览器展示
allure serve ./result
方式二:从结果生成报告,启动tomcat服务
生成报告 allure generate ./report -o ./report/ --clean(注意:覆盖路径+ -- clean)
打开报告 allure open -h 127.0.0.1 -p 8883 ./report/
常用特性
展示内容
@allure.feature('功能名称')
@allure.story('子功能名称')
@allure.step('测试步骤')
@allure.attach('附加信息') ---附加信息可以是数据,文本,图片,视频,网址
测试时可以限制过滤 pytest 文件名 --allure-features ‘ 功能’
feature/story
feature相当于一个功能,大模块,将case分类到某个feature中,报告在behaviore中显示,相当于testsuite
story相当于对应这个功能或者模块下的不同场景,分支功能,属于feature之下的结构,报告在features中显示,相当于testcase
step
测试的每个步骤,一般放在具体逻辑方法中
可以放在关键步骤中,在报告中显示
在App,Web自动化测试中,建议每切换一个新的页面当作一个step
用法
以装饰器的形式放在类或者方法上 @allure.step
放在测试用例方法中 with allure.step()
issue,testcase
关联bug及测试用例
重要性级别
用法:@allure.severity(allure.severity_level.XX)
级别
Blocker:中断缺陷 (客户端无响应,无法执行下一步操作)
Critical:临界缺陷(功能点缺失)
Normal:普通缺陷(数值计算错误)
Minor:次要缺陷(界面错误与UI需求不符)
Trivial:轻微缺陷(必输项无提示/提示不规范)
命令过滤
pytest -vs 文件名 --allure-severities normal,trivial

插件使用
pytest-ordering
@pytest.mark.run(order=xx)
注意:多个插件装饰器(>2)的时候,有可能会发生冲突
pytest-xdist
运行 pytest -n NUMCPUS
分布式执行测试用例原则
用例之间是独立的,不要有依赖关系
用例执行没有顺序,随机顺序都能正常执行
每个用例都能重复运行,运行结果不会影响其他用例
注意: 用例多的时候效果明显,多进程并发执行,同时支持 allure
pytest-rerunfailures
运行
pytest -vs --reruns 3 test_class.py
pytest -vs --reruns 5 --reruns-delay 1
@pytest.mark.flaky(reruns=5, reruns_delay=2)
用例的装饰器,指定这个用例rerun5次,每次延时2秒

pytest.ini
[pytest]
log_cli = true
日志开关 true false
log_cli_level = info
日志级别
addopts = --capture=no
打印详细日志,相当于命令行加 -vs
log_cli_format = %(asctime)s [%(levelname)s] %(message)s (%(filename)s:%(lineno)s)
日志格式
log_cli_date_format = %Y-%m-%d %H:%M:%S
日志时间格式
log_file = ./log/test.log
日志文件位置
log_file_level = info
日志文件等级
log_file_format = %(asctime)s [%(levelname)s] %(message)s (%(filename)s:%(lineno)s)
日志文件格式
log_file_date_format = %Y-%m-%d %H:%M:%S
日志文件日期格式

pycharm快捷键
command 长按点击文件多选
control+鼠标左键 快速定位方法/函数源码

posted @ 2021-09-12 16:50  Ada~  阅读(113)  评论(0)    收藏  举报