pytest
- 什么是单元测试框架?
单元测试是指在软件开发当中,针对软件的最小单元(函数、方法)进行正确性的检查测试。 - 单元测试框架主要做什么?
测试发现:从多个文件里面去找到我们测试用例。
测试执行:按照一定的顺序和规则去执行,并生成结果。
测试判断:通过断言判断预期结果和实际结果的差异。
测试报告:统计测试进度、耗时、通过率、生成测试报告。 - 单元测试框架和自动化测试框架有什么关系?
单元测试框架只是自动化测试框架中的组成部分之一;
POM设计模式只是自动化测试框架中的组成部分之一;
数据驱动…
关键字驱动…
日志监控…
断言…
报告邮件… - 自动化测试框架的作用
a.提供测试效率,降低维护成本;
b.减少人工干预,提高测试准确性、增加代码的重用性;
c’核心思想是让不懂代码的人也能够通过这个框架实现自动化测试。 - pytest测试用例的运行方式
主函数模式运行:
运行所有:pytest.main()
指定运行:pytest.main([‘’,‘test_login.py’])
指定目录:
指定
命令行:
c、通过读取pytest.ini配置文件运行
pytest.ini这个文件它是pytest单元测试框架的核心配置文件
(1)位置:一般放在项目的根目录下
(2)编码:必须是ANSI
(3)作用:改变pytest默认的行为
(4)运行规则:不管是主函数的模式运行,命令行模式运行,都会去读取这个配置文件。
pytest.ini文件内的主要内容如下:
#执行命令的参数,多个命令之间用空格分隔
addopts= -vs -x
#测试用例默认执行路径
testpaths=./TestCase
#模块名的规则,即项目名称
python_files=test_*.py
#类名规则
python_classes=Test*
#方法名的规则,即用例开头名称
python_functions=test
#冒烟测试标记:
markers=
smoke:冒烟用例
shopping:购物车模块
- pytest的执行顺序:
unittest默认的执行顺序是:ascll的大小的顺序执行
pytest默认的执行顺序是从上到下的顺序执行。
改变pytest的执行顺序:可以在执行用例函数前加@pytest.mark.run(order=次数) - 如何分组执行(冒烟)
在需要分组的测试用例前加@pytest.mark.标记名称,运行时命令参数-m “标记名称”:pytest -vs -m “标记名称” - pytest跳过测试用例
在需要跳过的测试用例前加@pytest.mark.skip,
无条件跳过:@pytest.mark.skip(reason=“写注名跳过的原因”)
有条件跳过:@pytest.mark.skipif(条件表达式,reason=“写注名跳过的原因”) - pytest前后置处理方法
第一种方式:使用setup/teardown、setup_class/teardown_class、setup_module/teardown_module来实现所有用例的前后置。
setup/teardown:在每个用例的前后都会执行一次
setup_class/teardown_class:在每个类的前后都会执行一次
setup_module/teardown_module
第二种方式:使用@pytest.fixture(scope=“”,params=“”,autouse=“”,ids=“”,name=“”)装饰器来实现部分用例的前后置。
使用:在方法前使用@pytest.fixture()标记,再在需要前置的测试用例中传入标记的方法名称。
参数代表意义:
scope表示的是被@pytest.fixture()标记的方法的作用域,function(默认)、class、module、package/session
params:参数化(支持列表、元组、字典列表和字典元组四种格式),使用时方法中必须使用request接收该值
@pytest.fixture(scope="session",params=["one","two","first"])
def my_fixture(request):
print("前置")
yield request.param
print("后置")
autouse=True:自动执行,默认False
ids:当使用params参数化时,给每一个值设置一个变量名
name:给表示的是被@pytest.fixture()标记的方法取一个别名
-
通过conftest.py和@pytest.fixture()结合使用全局 的前置应用(比如项目的全局登录,公用模块的全局处理)
注意事项:
a.conftest.py文件是单独存放的一个配置文件,名称不能更改。
b.使用:可以在不同的py文件中使用同一个fixture函数
c.原则上conftest.py需要和运行的用例放在同一层,并且使用不需要做任何import导入操作 -
pytest自动化测试框架params参数实现参数化
-
pytest集成allure生成企业级测试报告
pytest-html插件生成报告:
allure-pytest插件生成报告:
1)下载解压,并把bin的路径配置到path路径(官网下载地址:https://github.com/allure-framework/allure2/releases)
验证是否安装成功:输入命令allure --version
2)生成报告
生成临时文件:
#执行命令的参数,多个命令之间用空格分隔
addopts= -vs --alluredir ./temp
#测试用例默认执行路径
testpaths=./TestCase
#模块名的规则,即项目名称
python_files=test_*.py
#类名规则
python_classes=Test*
#方法名的规则,即用例开头名称
python_functions=test
一次性生成allure测试报告
#-*-coding:gbk-*-
import pytest
import os
if __name__ == '__main__':
#执行测试用例获取测试数据和数据目录
pytest.main(['-s','test_pytest.py','--alluredir','../allure-temp','--clean-alluredir'])
# 生成html测试报告 找到测试数据 生成测试报告目录,-c在生成报告之前先清理之前的报告目录 -o输出 --clean清空原来的测试报告
os.system('allure generate ../allure-temp -c -o ../report --clean')
#在一个临时文件中生成报告并启动浏览器打开,但是在关闭浏览器之后这个报告就再也打不开,不建议使用
#os.popen('allure serve ../allure-temp')
#自动使用浏览器打开测试报告report目录下的文件
os.popen('allure open ../report')
- pytest数据驱动装饰器@pytest.marks.parametrize详解以及YAML数据驱动
@pytest.mark.parametrize(args_name,args_value)
args_name:参数名称
args_value:参数值(使用list列表,tuple元组,字典列表,字典元组等),在数据中有多少个值那么用例就执行多少次。
import pytest
class TestAPI:
#基础用法,执行三次,打印出girl boy bady
@pytest.mark.parametrize(args,["girl","boy","bady"])
def test_api(self,args):
print(args)
#解包,执行三次,打印出 小于,15 小化,12 小李,25
@pytest.mark.parametrize('name,age',[['小于',15],['小化',12],['小李',25]])
def test_api(self,name,age):
print(name,age)
YAML详解:
主要作用:
1.用于做配置文件
2. 用于做测试用例
数据组成:
1.map对象:例如:键值对(键(空格)值) name: 小于
2.列表,用“-”开头的
#pytest.mark.parametrize集合YAML一块使用
@pytest.mark.parametrize('ceseinfo',ReadFile("../Data/appDesiredCaps.yaml").ReadYaml())
def test_01(self,ceseinfo):
print(ceseinfo)
- requests模块
requests第三方库,主要用于发送http请求,做接口自动化。
安装命令:pip install requests
requests全局观,知道有哪些方法,每个方法的用处:
#requests库常用的请求方法如下
requests.get() #发送get请求
requests.post()#发送post请求
requests.delete()#发送delete请求
requests.put()#发送put请求
requests.request()#最核心的方法
#响应方法如下:response对象
rep=requests.request()
#返回字符串的数据
print(rep.text)
#返回字节格式的数据(非文本请求,比如图片)
print(rep.content)
#返回字典格式的数据
print(rep.json())
#返回状态码
print(rep.status_code)
#返回状态信息
print(rep.reason)
#返回cookie信息
print(rep.cookies)
#返回编码格式
print(rep.encoding)
#返回响应头信息
print(rep.headers)