1.接口自动化框架
1.1 框架结构
接口测试框架的结构如下图所示:
接口测试框架的结构说明:
- API 用于封装被测系统的接口
- TestCase 将一个或者多个接口封装成测试用例,并使用UnitTest管理测试用例 TestCase 可以调用数据库进行数据的校验
- 为了方便维护测试数据,可以把测试脚本和测试数据分离开
- 通过UnitTest断言接口返回的数据,并生成测试报告
1.2框架目录结构
apiTestFramework # 项目名称
├── api # package:定义封装被测系统的接口
├── script # package: 定义测试用例脚本
├── data # dir:存放测试数据
├── report # dir: 存放生成的测试报告
├── lib # package: 存放第三方的文件
├── app.py # 定义项目的配置信息
├── utils.py # 定义工具类
└── run_suite.py # 执行测试套件的入口
1.3 封装TPShop登录接口案例
按照功能模块定义封装被测系统的接口,方便测试脚本的调用,并且能够到达代码的复用。 对登录功能的相关接口进行封装,示例代码:
# api/login.py
class LoginApi:
def __init__(self):
self.verify_code_url = "http://localhost/index.php?m=Home&c=User&a=verify"
self.login_url = "http://localhost/index.php?m=Home&c=User&a=do_login"
1.4 登录测试用例
将api模块中的一个或多个接口封装成一个测试用例,并使用测试框架UnitTest管理测试用例。 定义登录功能的测试用例,示例代码:
class TestLogin(unittest.TestCase):
def setUp(self):
self.session = Session()
def tearDown(self):
self.session.close()
# 登录成功:
def test_login_success(self):
# 获取验证码
response = self.login_api.get_login_verify_code(self.session)
# 判断是否为图片类型
self.assertIn("image", response.headers.get("Content-Type"))
# 登录
response = self.login_api.login(self.session, "13012345678", "123456", "8888")
result = response.json()
print("login response data=", result)
# 断言
self.assertEqual(200, response.status_code)
self.assertEqual(1, result.get("status"))
self.assertEqual("登陆成功", result.get("msg"))
1.5 集成测试报告
使用HTMLTestRunner生成HTML格式的测试报告
注意: 需要将HTMLTestRunner.py工具放置在lib中
import time
import unittest
from script.test_login import TestLogin
from tools.HTMLTestRunner import HTMLTestRunner
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestLogin))
# 测试报告文件路径
report_file = "./report/report{}.html".format(time.strftime("%Y%m%d-%H%M%S")) with open(report_file, "wb") as f:
# 创建HTMLTestRunner运行器
runner = HTMLTestRunner(f, title="TPshop接口自动化测试报告", description="V1.0")
# 运行测试套件
runner.run(suite)
2.参数化处理
2.1 参数化分析
2.2 构建json文件存放测试数据
[
{
"desc": "case01 登录成功",
"username": "13488888888",
"password": "123456",
"verify_code": "8888",
"content_type": "image",
"status_code": 200,
"status": 1,
"msg": "登陆成功"
},
{
"desc": "case02 账号不存在",
"username": "13488888899",
"password": "123456",
"verify_code": "8888",
"content_type": "image",
"status_code": 200,
"status": -1,
"msg": "账号不存在"
},
{
"desc": "case03 密码错误",
"username": "13488888888",
"password": "error",
"verify_code": "8888",
"content_type": "image",
"status_code": 200,
"status": -2,
"msg": "密码错误"
}
]
2.3 构建参数化数据
def build_data():
file = '../data/login.json'
test_data = []
with open(file, 'r', encoding='utf-8') as f:
json_data = json.load(f)
for case_data in json_data:
username = case_data.get('username')
password = case_data.get('password')
verify_code = case_Data.get('verify_code')
content_type = case_Data.get('content_type')
status_code = case_Data.get('status_code')
status = case_Data.get('status')
msg = case_Data.get('msg')
test_data.append((username, password, verify_code, content_type, status_code, status, msg))
return tst_data
2.4 测试用例实现参数化
class TestLogin(unittest.TestCase):
# 2.1 前置处理
def setUp(self):
self.login_api = LoginAPI() # 实例化接口类
self.session = requests.Session() # 创建session对象
# 2.2 后置处理
def tearDown(self):
if self.session:
self.session.close()
@parameterized.expand(build_data)
# 2.3.创建测试用例
def test01_login(self, username, password, verify_code, content_type, status_code, status, msg):
pass
3.db数据承载形式实现参数化
3.1 构建数据库数据
执行SQL脚本, 将数据写入数据库中
3.2 修改构建数据函数
def build_data():
# 获取数据库的数据
sql = "select * from t_login"
db_data = DBUtil.exe_sql(sql)
test_data = []
for case_data in db_data:
username = case_data[2]
password = case_data[3]
verify_code = case_data[4]
status_code = case_data[5]
content_type = case_data[6]
status = case_data[7]
msg = case_data[8]
test_data.append((username, password, verify_code, content_type, status_code, status, msg))
print(test_data)
return test_data