pytest + allure框架
**************************************************************************************
第一部分 requests
1. 安装requests,使用命令 pip install requests
若在线安装失败,则使用以下镜像命令安装:
pip install requests -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
2. Python接口入门练习
课件\09_接口测试\python+requests库的接口自动化测试.docx
http://www.pingan.com/cms-tmplt/pinganlife/synShopList.do
参数dateUpdated:2017-12-02
平安接口是2017-12-02有数据,2020-06-09能跑,2010-06-09不能跑
***************************************************************************************
第二部分 pytest+allure框架
1. 环境准备
1-1. pycharm设置(默认Unittests):
Tools → Python Integrated Tools → 第2行的 Default test runner选择py.test
如果pycharm控制台报 Empty test suite 空测试套件,需要修改默认执行程序
1-2. 安装pytest框架: pip install -U pytest
验证是否成功:pytest --version
1-3. 安装allure
1)首先安装jdk8及以上版本,即1.8+(注意环境变量的配置)
JAVA_HOME: C:\Program Files\Java\jdk1.8.0_60\
CLASSPATH: .;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar
Path: %JAVA_HOME%\bin;%JAVA_HOME%\jre\bin
2)allure下载地址:https://github.com/allure-framework/allure2/releases
解压zip包后(路径不要中文),配置Path环境变量: C:\allure-2.17.2\bin
DOS窗口验证: allure --version
1-4. 安装allure-pytest 插件,用来生成 Allure 测试报告所需要的数据
pip install allure-pytest
2. pytest框架的文件命名规则
pytest的文件名,要以test_*.py 或*_test.py命名
pytest的类,要以Test开头
pytest的方法,要以test开头
3. pytest常用断言方式
assert a in b:判断b包含a
assert a == b:判断a等于b
assert a != b:判断a不等于b
4. pytest框架示例代码如下:
import pytest
class TestCase(): # 创建测试类,以Test开头
def setup_class(self):
# def setup(self):
print("环境准备")
def testCase_01(self): # 测试用例,以test开头
print("测试用例1步骤")
assert "a" == "a"
def testCase_02(self):
print("测试用例2步骤")
assert "a" in "ab"
def teardown_class(self):
# def teardown(self):
print("环境恢复")
if __name__ == "__main__":
pytest.main()
# 指定文件运行
# pytest.main(["-s","testCase.py"])
注意:setup、teardown适用于执行单条用例,setup_class、teardown_class适用于批量执行
5. pytest中装饰器@pytest.mark.parametrize("参数名",data)可以实现测试用例参数化,
放在类或类函数前面,作用类似DDT的数据驱动, parametrize读音 /pə'ræmətraɪz/,
测试数据data常用列表形式(也支持元组),如:简单列表、列表套字典、列表套列表套多个字典
如:@pytest.mark.parametrize("inputData, expectRes",
[ ( '{"page":1}', '{"code":0,"msg":"成功"}' ),
( '{"page":2}', '{"code":0,"msg":"成功"}' ) ] )
1).测试数据封装成列表的具体示例:
data = [ [ {"username":"juzi01","password":"123456","password_confirmation":"123456"},
{"expect":"juzi01"} ],
[ {"username":"","password":"123456","password_confirmation":"123456"},
{"expect":"\"code\":2001,\"msg\":\"missing username or password or password_confirmation\""} ],
[ {"username":"juzi02","password":"123456","password_confirmation":"123456000"},
{"expect":"\"code\":2002,\"msg\":\"password/password_confirmation not identical\""} ] ]
# 引入测试数据,并分解
@pytest.mark.parametrize("testData,expected",data)
# 测试用例,以test开头
def testCase(self,testData,expected):
print("这是用例具体步骤")
2).测试数据放到yaml文件示例(需将测试数据转成yaml格式,可百度json转yaml):
安装yaml:pip install pyyaml
# 将测试数据放到yaml文件: 获取yaml文件完整路径→读取yaml文件,并转成列表格式
import os,yaml
yaml_path = os.path.join(os.path.dirname(__file__),"test_01_register.yaml")
with open(yaml_path,"r",encoding="utf-8") as f:
data = yaml.load(f.read(),Loader=yaml.FullLoader)
# 引入测试数据
@pytest.mark.parametrize("testData,expected",data)
# 测试用例,以test开头
def testCase(self,testData,expected):
print("这是用例具体步骤")
3).测试数据放到yaml文件示例(将读取yaml文件封装成函数,可以直接调用) → 不要求掌握
# 定义函数法
def getYaml(yamlName):
yaml_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))),"testCases",yamlName)
with open(yaml_path,"r",encoding="utf-8") as f:
res = f.read()
data = yaml.load(res,Loader=yaml.FullLoader)
return data
# 调用函数getYaml
data = getYaml("test_01_register.yaml")
6. 生成allure测试报告的三种方法
方法1. 在pycharm中,以非py.test方式运行(文件名以test_开头)
if __name__ == "__main__":
# 如果工作路径有误,需要将工作路径切换到当前目录下
# cur_path = os.path.dirname(os.path.abspath(__file__))
# os.chdir(cur_path)
# 第一步,指定在当前文件夹的temp下,生成测试报告需要的数据
os.system("pytest --alluredir=./temp")
# 第二步,清空原来reports的报告,并根据temp下的数据,生成测试报告放在reports下
os.system("allure generate ./temp -o ./reports --clean")
注:在pycharm中能正常运行,但没有生成allure报告,且控制台报一串红色方框问号,
原因是环境变量没有生效,需要重启pycharm,或重启电脑。
方法2. 在DOS中,以pytest方式运行(py文件名可以任意)
打开文件所在路径,命令行输入可以生成allure报告的2个命令
命令1,运行程序,生成报告:pytest py文件 --alluredir 生成报告文件的临时文件夹
如:pytest pytest框架.py --alluredir ./temp
命令2,启动服务,查看临时报告:allure serve 生成报告文件的临时文件夹
如:allure serve ./temp
方法3. 在DOS中,以python方式运行(py文件名必须以test_开头)
1). py文件的调试入口 if __name__ 里面,需要写入以下内容:
if __name__ == "__main__":
# 第一步,指定在当前文件夹的temp下,生成测试报告需要的数据
os.system("pytest --alluredir=./temp")
# 第二步,清空原来reports的报告,并根据temp下的数据,生成测试报告放在reports下
os.system("allure generate ./temp -o ./reports --clean")
2). 打开文件所在路径,命令行输入以下2个命令:
python test_pytest框架.py
allure open reports
7. 打开allure报告的方法
在report下index.html文件是不能直接用浏览器打开的,出现页面都是loading的情况,
需要用allure命令渲染之后打开才能展示效果。可用以下两种方法:
1. 可以直接在pycharm中用浏览器打开
2. 可以在DOS窗口用命令打开: allure open 存放报告的文件夹
如C盘: allure open C:\pytest框架\reports
或D盘: D: → cd D:\pytest框架\reports → allure open ./
8. @allure 装饰器中的一些功能点:
想对用例集分层,增加可读性,可以使用以下三个装饰器,写在类或方法前面:
import allure # 先导包
@allure.epic("版本号") # 敏捷里的概念,或者项目版本,如V1.0.5
@allure.feature("测试模块") # 定义被测试对象的功能点,如商品管理
@allure.story("测试功能点") # 定义被测功能的用户场景,即子功能点,如新增商品
9. br_api 项目练习
9-1. 如在C盘根目录创建项目文件夹br_api,里面有如下内容:
public 公共部分,存放公共数据、方法等,如封装token、服务器信息等
public.py
testCases 用例层,存放测试用例
test_01_register.py
test_02_login.py
reports 存放测试报告
runMain.py 主程序文件,调用所有接口用例执行,并生成测试报告
9-2. 调用公共部分时,报错 ModuleNotFoundError: No module named 'xxx',可能路径问题,
可以参考下方的 13.注意事项里面的第3条,或者定义项目路径为绝对路径,具体如下:
import os,sys
# 构造项目路径
projectPath = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(projectPath)
from public.public import host,getToken
9-3. 如果pycharm里面没有生成报告,可以到DOS窗口执行如下命令:
cd C:\课堂练习\python练习\br-api
python runMain.py
allure open reports
9-4. 脚本调试好,使用Jenkins做持续集成测试
Jenkins日程表设置:00 18 * * *
(分时日月周,表示每晚18:00执行脚本)
Jenkins命令:
项目文件在C盘: cd C:\br_api → python runMain.py
项目文件在D盘: D: → cd C:\br_api → python runMain.py
10. 注意事项:
1.同一模块中,变量名和函数名不能相同,
2.变量名不能和从别的模块导入的变量名相同
3.如果报错 No module named 'public',需要设置项目文件夹,具体为:
选择项目文件夹如br_api,右键选择底部的Mark Directory as → Sources Root
4.如果报 No such file or directory: 'D:\\Program Files\\JetBrains\
\PyCharm 5.0.3\\jre\\jre\\bin\\test_03_task.yaml'
可能是临时路径问题,可用os.path.dirname(os.path.abspath(__file__))代替os.getcwd()
------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------
**************************************************************************************
以下是代码示例
-------------------------------------------------------------------------------------------
yaml文件名:test_data.yaml
文件内容如下:
- - name: tom
age: 20
- expectRes: hello
- - name: 橘子
age: 25
- expectRes: 'hello,world'
pytest框架示例----------------------------------------------------------------------------
文件名:test_case.py,实际项目中可以写成test_01_register、test_02_login等
import pytest,os,yaml
class TestExample():
# 1.测试用例:无参数
'''
def test_case01(self):
# 测试步骤
print("测试步骤,无参数")
# 断言
expectRes = "hello"
actualRes = "hello,world"
# 判断actualRes包含expectRes
assert expectRes in actualRes
'''
# 2.测试用例:只有一个参数
'''
data = "赚大钱"
@pytest.mark.parametrize("args",[data]) # 列表格式传参
def test_case02(self,args):
# 测试步骤
print("测试步骤,只有一个参数:%s"%args)
# 断言
expectRes = "hello"
actualRes = "hello"
assert expectRes == actualRes
'''
# 3.测试用例:参数为列表中嵌套了字典
'''
data = [ {"name":"tom","age":20},
{"name":"橘子","age":25}
]
@pytest.mark.parametrize("args",data)
def test_case02(self,args):
# 测试步骤
print("测试步骤,传入参数是:%s,%d"%(args["name"],args["age"]))
# 断言
expectRes = "hello"
actualRes = "hello666"
assert expectRes != actualRes
'''
# 4.测试用例:参数为列表中嵌套列表和多个字典
'''
data = [ [{"name":"tom","age":20},{"expectRes":"hello"}],
[{"name":"橘子","age":25},{"expectRes":"hello,world"}]
]
@pytest.mark.parametrize("inputData,expect",data)
def test_case02(self,inputData,expect):
# 测试步骤
print("测试步骤,传入参数是:%s,%d"%(inputData["name"],inputData["age"]))
# 断言
expectRes = expect["expectRes"]
print("预期结果expectRes是:",expectRes)
actualRes = "hello666"
assert expectRes != actualRes
'''
# 5.测试用例:将测试数据放入yaml文件,地址:https://oktools.net/json2yaml
# 拼接yaml文件的完整路径
yaml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),"test_data.yaml")
# 读取yaml文件内容
with open(yaml_path,"r",encoding="utf-8") as f:
res = f.read()
data = yaml.load(res,Loader=yaml.FullLoader)
# data = [ [{"name":"tom","age":20},{"expectRes":"hello"}],
# [{"name":"橘子","age":25},{"expectRes":"hello,world"}]
# ]
@pytest.mark.parametrize("inputData,expect",data)
def test_case02(self,inputData,expect):
# 测试步骤
print("测试步骤,传入参数是:%s,%d"%(inputData["name"],inputData["age"]))
# 断言
expectRes = expect["expectRes"]
print("预期结果expectRes是:",expectRes)
actualRes = "hello666"
assert expectRes != actualRes
if __name__ == "__main__":
# 运行当前文件夹下所有以test_开头的py文件
# pytest.main()
# 运行指定py文件
pytest.main(["-s","test_case.py"])
引入allure测试报告----------------------------------------------------------------------------
import pytest,os,yaml,allure
@allure.epic("V1R2C03") # 版本号
@allure.feature("商品管理") # 测试模块
@allure.story("添加商品") # 测试模块中的子功能点
class TestExample():
# 拼接yaml文件的完整路径
yaml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),"test_data.yaml")
# 读取yaml文件内容
with open(yaml_path,"r",encoding="utf-8") as f:
res = f.read()
data = yaml.load(res,Loader=yaml.FullLoader)
# data = [ [{"name":"tom","age":20},{"expectRes":"hello"}],
# [{"name":"橘子","age":25},{"expectRes":"hello,world"}]
# ]
@pytest.mark.parametrize("inputData,expect",data)
def test_case02(self,inputData,expect):
# 测试步骤
# print("测试步骤,传入参数是:%s,%d"%(inputData["name"],inputData["age"]))
# 断言
expectRes = expect["expectRes"]
# print("预期结果expectRes是:",expectRes)
actualRes = "hello6660"
assert expectRes != actualRes
if __name__ == "__main__":
# 第一步,指定在当前文件夹的temp下,生成测试报告需要的数据
os.system("pytest --alluredir=./temp")
# 第二步,根据temp下的数据,生成测试报告放在reports下,并清空原来的报告
os.system("allure generate ./temp -o ./reports --clean")