Pytest
Note:本地跑测试的时候,一定要把封装的api里的调试的代码都注释掉,否则会打印出好多东西,莫名其妙,要找半天问题在哪,啊啊啊啊啊啊、、、、、,,,,
一:安装:
CMD窗口执行命令: pip install pytest
=> 执行命令pytest version (或者pip show pytest) 可以查看当前安装的pytest版本。
二:Pytest规则:
1:.py文件一定要以test开头或者_test结尾
2:测试类必须要Test开头,并且不能有init方法;
3:测试方法必须以test_开头
4:断言必须用assert
三:创建项目:
1:lib包: 主要存放 封装好的方法
2:data文件夹:主要存放数据
3:testcase包:测试用例
4:report文件夹:存放报告
四:初始化和清除:
模块级别: setup_module & teardown_module
类级别: setup_class & teardown_class
方法级别: setup_method & teardown_method
函数级别(非class下的每个测试函数):setup_function & teardown_function
五:数据驱动:其实就是参数化
使用装饰器: @pytest.mark.parametrize

六:Pytest结合Allure报告
allure:是一个报告库,不单单只适用于python, 也可以适用于java.
allure环境搭建:
step1: 下载allure文件包,解压
step2: 将解压后的,bin路径添加到系统的path中.
step4: CMD窗口执行pip install allure-pytest 安装 allure-pytest库
验证: CMD窗口执行 allure
# 需要显示打印信息的话,需要加参数-s
# 1: --alluredir : 存放用于生成allure的临时文件
pytest.main(['test_func01.py','-s','--alluredir','../report/tmp'])
# 2: allure generate allure报告 =>cmd命令, 此时需要os模块
# os.system('allure generate 用于生成报告的临时文件的所在路径 -o 生成的allure要存放的路径')
os.system('allure generate ../report/tmp -o ../report/report -clean')
七:allure报告分层: 需要导入allure库,代码中具体加标签
@allure.feature("登录模块") # 一级标签
@allure.story("登录login01") # 二级标签
@allure.title("login01") # 每个用例都会带
自动化全流程:配置GIT ==》代码上传到Linux ==》触发jekenis调用pytest去做自动化。
GIT Linux Jekenis
八: 代码中怎么表示json:

九: # 请求体;根据要求 请求体是JSON格式,但是代码中具体怎么表示为JSON呢,加引号
payload = {
"action": "add_course",
"data":'''{
"name":"初中语文",
"desc":"初中语文课程",
"display_idx":"1"
}'''
}
===》但是,如果数据是直接读取出来的,比如直接从Excel中读取出来的本身就是str类型的,那么就不需要再加引号了。
十: 数据格式:
表单格式: 键值对的形式,用&连接多个键值对
JSON格式:键值对形式的字符串;键必须用双引号
十一: data: 请求体参数,默认是表单类型
==》 如果是data的话,header可以不用传
json:请求体参数,默认是JSON类型
**kwargs: 格式:变量=值。 一般传 headers, cookies, proxy, ssl检验
token, cookie 一般封装在header
十二: 请求&响应信息打印
# 打印请求头
# 可以查看到user-agent直接发送的话python。。。: 'User-Agent': 'python-requests/2.25.1'
print(reps.request.headers)
# 打印请求体
print(reps.request.body)
# 查看响应头, 可以查看到响应体的格式
print(reps.headers)
# 查看响应体, text文本形式
print(reps.text,type(reps.text))
# 查看响应体, 字典格式。前提,响应体必须是json格式才能用此方法
print(reps.json(),type(reps.json()))
# 取响应中的某个信息,比如 retcode
print(json.loads(reps.text)["retcode"])
print(reps.json()["retcode"])
十三: unicode转中文:
\u7528\u6237\u6216\u8005\u5bc6\u7801\u9519\u8bef ==》这种是Unicode码, 可以用工具转为中文。
在代码中,也可以通过指定编码的方式,转为中文==》 reps.encoding="unicode_escape"
十四: requests.post方法,data与JSON参数的区别
一: params参数,如果传入的是字典,自动编码为表单。--------- 一般get请求需要
二:data参数,如果传入的是字典,自动编码为表单。--------- 一般对于put/post请求
三:data参数,如果传入的是字符串,原格式直接发出去。--------- 一般对于put/post请求
四:json参数,如果传入的参数是字典,自动编码为JSON字符串--------- 一般对于put/post请求
五:json参数,如果传入的是字符串,按照原格式添加上双引号发出--------- 一般对于put/post请求
六:headers参数,传递的是字典格式
七:delete请求里参数用data
==》 而且头部的信息一般都封装成字典,比如cookie
data=json.dumps(dictPayload) 等同于 json=dictPayload
十五: Requests库响应体四种格式:

十六: Cookie &Session & Token
第一个请求发给服务器的时候是没有cookie的,在第一个里服务器会把cookie信息放在响应头的setcookie里;
后面的请求,发送的时候就会带上这个cookie信息, 放在请求头里。
Cookie是存放在浏览器本地的。
session是服务器产生的存放在服务器的;
sessionid是session对象的一个属性,是全局的且唯一的。

token也是服务器产生的,存放在服务器的内存或者硬盘中。 ==》 也是为了减少数据库的访问量
==》 开发者提供一个获取token接口, 根据用户名+密码 来获取token值,返回一个token字符串。

十七: 获取cookie/sessionid 的方法:
# 方法一:直接从响应中获取cookie, 得到的是cookie对象。 但是不能对cookie进行二次封装
# return reps.cookies
# 方法二:
# return reps.headers["Set-Cookie"]
# 方法三, cookie对象本身就包含sessionid值,所以,可以直接通过sessionid键取获取其对应的值;
print(reps.headers)
return reps.cookies["sessionid"]
十八: 生成allure报告的两种写法:
#"--clean-alluredir" 可以清除掉以往的用于生成allure报告的内容,从而使生成的新的allure报告是最新的。
pytest.main(['test_login.py', '-s', '--alluredir','../report/tmp',"--clean-alluredir"])
# 方案1:直接生成报告
os.system('allure generate ../report/tmp -o ../report/report --clean')
# 方案2: 直接启动一个服务,自动打开浏览器
os.system('allure serve ../report/tmp')
十九: fixture
scope ='function', 级别,默认是函数。 级别有:function,class,module,session(package级别)
======》如果是模块级别的,而且某模块中既有函数级别用例又有类级别的,该初始化在该模块中只执行一次。

======》如果是类级别的, 在类中的第一个函数里进行调用就可以了。
======》如果是包级别的,在函数里可以不用传参。
===》在该包下创建conftest的Python文件, 比如:
@pytest.fixture(scope="session",autouse=True)
def start_demo():
print("------我是整个包的初始化------")
======》包级别的初始化和清除:

===> 模块中的fixture定义好之后,要调用,
比如: @pytest.mark.usefixtures('lesson_delete_fixture')。 而且一定要注意该定义的fixture的作用域

======》 重点解释function.
如果一个test_login1用例 使用了一个function级别的fixture,儿test_login1 可能执行的之后有多组登录测试数据,那么它每跑一组数据。都会自调用这个function级别的fixture。
假如 test_login01 有10组测试数据,那么那个function级别的fixture就会调用10次。
======》多层调用的时候,先执行离得最近的。
比如,如下图,先执行“xinian_test_fixture”.

二十:定制化执行用例
方式一[推荐使用]:
用例定制化执行,只执行一部分(mark)
===>1: 先创建pytest.ini文件,前提需要ini插件
===》2: 在ini文件正创建标签

===》3:在测试用例中使用标签

===》4:定制化执行用例,选择只执行部分用例
# 定制化执行,只指令lesson_add标签下的用例。如果执行多个,用or, pytest.main(['test_lesson.py', '-s','-m','lesson_add or lesson_list'])
pytest.main(['test_lesson.py', '-s','-m','lesson_add'])
方式二:

skip&skipif
@pytest.mark.skipif(1==2,reason="需要满足前面的条件,才会跳过该测试该方法的执行")
@pytest.mark.skip("无条件跳过")
二十一:yaml文件
yaml: 专门用来做配置文件的语言。
安装:pip install PyYaml

读取:===》只有一组数据时的读取
# 读取yaml文件操作
# yamlDir = './config/test.yaml'
# fo = open(yamlDir,"r",encoding='utf-8')
# # 使用操作库load 来加载读取文件; 文件在前
# res = yaml.load(fo,Loader = yaml.FullLoader)
# print(res)
多组数据时的读取:
# 读取yaml文件操作,当有多组数据时
yamlDir = './config/test.yaml'
fo = open(yamlDir,"r",encoding='utf-8')
# 使用操作库load 来加载读取文件; 文件在前
res = yaml.load_all(fo,Loader = yaml.FullLoader)
for one in res:
print(one)
二十二:Pytest做分布式测试
需要安装库: pip install pytest-sdist
运行方式:串行 和 并行:
二十三:Py同时运行多个文件
pytest test1.py test2.py -sq
当多个文件不在同一个路径下时,注意路径。
整体梳理:
************Pytest接口自动化部分:
Excel文件操作(xlrd 和 xlwt)
1:文件的打开
读取excel文件:xlrd.open_workbook("文件路径")
读取具体的sheet,可以通过sheet名字或者index
2:文件的写入
读取excel文件:xlrd.open_workbook("文件路径")
写入文件,调用write方法
******Pytest:
1:规则, 一些命名规则和文件存放规则。
2:初始化和清除【fixture 和 use fixture】以及作用域
包级别的初始化:其实就是定义函数&规定作用域,初始化方法里传入request参数,清除函数fin()写在初始化函数里,然后 request.addfinalizer(fin) 。
其他类级别和方法级别的初始化和清除都可以定义在conftest文件里,定义时注意其作用域,
然后在具体的测试用例中使用@pytest.mark.usefixtures('初始化或者清除方法名')来进行调用。
不用fixture,也可以用setup, teardown来做初始化和清除。
3:参数化:@pytest.mark.parametrize('参数名',参数的来源【可以是函数/方法】)
4:allure报告
优化报告:结合allure使用装饰器加标签来优化报告,使报告有层次感,很清晰。
5:yaml文件
读取yaml文件,使用open()函数
然后使用PyYaml库中的yaml.load()方法来加载/读取前面读取到的yaml文件中的数据。
数据存放到yaml文件中,然后 结合yaml库[PyYaml库] & open()函数,
读(yaml.load(前面使用open函数读取到的文件对象,Loader = yaml.FullLoader))
写入yaml文件:yaml.dump()
首先以写的方式发开yaml文件获取文件对象:fo = open(yamlDir,"w",encoding='utf-8')
yaml.dump(要写如的数据,fo[文件对象])
==》重点: 从yaml文件中获取到测试数据
*******跑pytest case时,自己封装方法的python文件里面额外的调试代码一定要注释或者删掉。
******Pycharm中跑代码,控制台碰到报错:allure报错:‘allure‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件
===》 解决办法:需要从官网下载allure压缩包,解压,然后将bin目录的路径存添加在系统环境变量path中。
如果已经在path中添加过,可能是以前的文件allure文件/文件夹被移动了,导致系统找不到,需要重新添加以下。

浙公网安备 33010602011771号