一、unittest自动化测试结构
二、代码实现
1、导入需要的一些前置方法,用以获取cookie,生成测试数据等
# coding=utf-8
import sys
sys.path.append('..')
# 导入前置方法(登录接口获取cookie;通用的方法,如生成随机字符串、手机号;一些常用的参数设置等)
import PreProcessing as p
from PreProcessing import *
2、初始化 接口地址、机构、用户、数据库等
初始化要查询的数据库,参考https://blog.csdn.net/kk_gods/article/details/109054888
class AntibioticDict(p.unittest.TestCase): # 继承unittest的TestCase类
"""
新增抗生素字典测试
"""
@classmethod
def setUpClass(cls):
"""
必须使用@classmethod装饰器,所有case执行的前置条件,只运行一次
可以根据系统设计、接口特性等,进行测试前的初始化:机构ID, url, 用户ID,cookie,tooken,header等
:return:
"""
cls.header, cls.org_id, cls.user_id = p.header, p.org_id, p.user_id
cls.url_test = p.base_url + '/api/'
# 初始化一个查询sql(根据请求参数,查询数据库是否有新增一条相同得数据),用于断言
cls.sql = """
SELECT COUNT(id) AS counts
FROM
`table1`
WHERE
org_id = '{}'
AND `code` = '{}'
AND `name` = '{}'
and `is_valid` = '{}'
AND create_time LIKE '{}%';
"""
cls.db = p.readconfig.lis_db
3、初始化请求参数
调用公共函数CommonFunc生成随机字符串、数字,参考https://blog.csdn.net/kk_gods/article/details/109053179
def setUp(self):
"""
准备环境,执行每个测试用例的前置条件
:return:
"""
# is_valid = p.USE_FLAG
# 初始化请求参数
self.params_test = {
"isTrusted": True,
"isValid": 1,
"code": 'code' + p.CommonFunc.random_str,
"name": 'name' + p.CommonFunc.random_strs(10),
"inputCode": p.CommonFunc.random_strs(10),
"enName": p.CommonFunc.random_strs(10),
"kbMin": round(p.random.uniform(1, 10), 2),
"kbMax": round(p.random.uniform(11, 100), 2),
"micMin": round(p.random.uniform(1, 10), 2),
"micMax": round(p.random.uniform(11, 100), 2),
"remark": p.CommonFunc.random_strs(10),
"sort": p.random.randint(1, 10),
"orgId": self.org_id
}
4、编写测试用例
# 测试用例命名必须以test开头
def test_antibiotic_dict_001(self):
"""1、【新增字典】新增合法数据;预期:成功"""
# 发起请求
r = p.requests.request("post", url=self.__class__.url_test, json=self.params_test, headers=self.__class__.header)
# 将返回信息转换为json
test_result = p.json.loads(r.text)
# msg = p.CommonFunc.get_msg(test_result) # 调用函数,获取msg
# print(r.elapsed.total_seconds()) # 接口响应时间
if r.status_code == 200 and test_result['success']: # 判断http状态码和请求返回状态
# 将请求参数组装到SQL中
sql = self.__class__.sql.format(
self.params_test['orgId'], self.params_test['code'], self.params_test['name'],
self.params_test['isValid'],
p.CURRENT_DATE
)
# 执行SQL,获取数据库新增条数,参考https://blog.csdn.net/kk_gods/article/details/109053646
counts = p.CommonFunc.get_counts(sql, self.db)
# 判断数据库是否新增一条数据:counts等于1,测试用例执行通过;counts不等于1,执行失败,将接口URL、参数以及查询SQL输出
self.assertEqual(counts, 1, """
接口返回成功,但数据库未查询到数据
【URL】: {},
【PARAMS】: {},
【STATUS】: {},
【MSG】: {},
【SQL】: {}
""".format(r.url, self.params_test, r.status_code, msg, sql))
else:
self.assertTrue(
test_result['success'],
"""
测试不通过,ERROR
【URL】: {},
【PARAMS】: {},
【STATUS】: {},
【MSG】: {}
""".format(r.url, self.params_test, r.status_code, msg))
# 调用skip()装饰器跳过某个case,
# @p.unittest.skip("Don't run this case. ") # 无条件跳过
def test_antibiotic_dict_002(self):
"""2、【新增字典】编码重复;预期:新增失败"""
r = p.requests.request("post", url=self.__class__.url_test, json=self.params_test, headers=self.__class__.header)
test_result = p.json.loads(r.text)
msg = p.CommonFunc.get_msg(test_result)
if r.status_code == 200:
self.assertFalse(
test_result['success'],
"""
测试不通过,未校验编码是否重复
【URL】: {},
【PARAMS】: {},
【STATUS】: {},
【MSG】: {}
""".format(r.url, self.params_test, r.status_code, msg))
else:
self.assertFalse(
test_result['success'],
"""
测试不通过,ERROR
【URL】: {},
【PARAMS】: {},
【STATUS】: {},
【MSG】: {}
""".format(r.url, self.params_test, r.status_code, msg))
# @unittest.skipIf(condition,reason) # 如果condition为true,则 skip
def test_antibiotic_dict_003(self):
"""3、【新增字典】max值小于min;预期:新增失败"""
self.params_test.update(
{
"code": 'code' + p.CommonFunc.random_strs(10),
"kbMin": round(p.random.uniform(11, 100), 2),
"kbMax": round(p.random.uniform(1, 10), 2),
"micMin": round(p.random.uniform(11, 110), 2),
"micMax": round(p.random.uniform(1, 10), 2),
}
)
r = p.requests.request("post", url=self.__class__.url_test, json=self.params_test, headers=self.__class__.header)
test_result = p.json.loads(r.text)
msg = p.CommonFunc.get_msg(test_result)
if r.status_code == 200:
self.assertFalse(
test_result['success'],
"""
测试不通过,未校验KB、MIC值大小关系
【URL】: {},
【PARAMS】: {},
【STATUS】: {},
【MSG】: {}
""".format(r.url, self.params_test, r.status_code, msg))
else:
self.assertFalse(
test_result['success'],
"""
测试不通过,ERROR
【URL】: {},
【PARAMS】: {},
【STATUS】: {},
【MSG】: {}
""".format(r.url, self.params_test, r.status_code, msg))
# @unittest.skipUnless(condition,reason) # 如果condition为False,则skip
def test_antibiotic_dict_004(self):
"""4、【新增字典】新增不存在的状态,预期:失败"""
self.params_test.update(
{
"code": 'code' + p.CommonFunc.random_strs(10),
"isValid": 3
}
)
r = p.requests.request("post", url=self.__class__.url_test, json=self.params_test, headers=self.__class__.header)
test_result = p.json.loads(r.text)
msg = p.CommonFunc.get_msg(test_result)
if r.status_code == 200:
self.assertFalse(
test_result['success'],
"""
测试不通过,未校验停启用状态
【URL】: {},
【PARAMS】: {},
【STATUS】: {},
【MSG】: {}
""".format(r.url, self.params_test, r.status_code, msg))
else:
self.assertFalse(
test_result['success'],
"""
测试不通过,ERROR
【URL】: {},
【PARAMS】: {},
【STATUS】: {},
【MSG】: {}
""".format(r.url, self.params_test, r.status_code, msg))
def test_antibiotic_dict_005(self):
"""5、【新增字典】必填字段未填写;预期:新增失败"""
self.params_test.update(
{
"code": None
}
)
r = p.requests.request("post", url=self.__class__.url_test, json=self.params_test, headers=self.__class__.header)
test_result = p.json.loads(r.text)
msg = p.CommonFunc.get_msg(test_result)
if r.status_code == 200:
self.assertFalse(
test_result['success'],
"""
测试不通过,未校验必填字段
【URL】: {},
【PARAMS】: {},
【STATUS】: {},
【MSG】: {}
""".format(r.url, self.params_test, r.status_code, msg))
else:
self.assertFalse(
test_result['success'],
"""
测试不通过,ERROR
【URL】: {},
【PARAMS】: {},
【STATUS】: {},
【MSG】: {}
""".format(r.url, self.params_test, r.status_code, msg))
def test_antibiotic_dict_006(self):
"""6、【新增字典】字段长度超长;预期:新增失败"""
self.params_test.update(
{
"code": 'code' + p.CommonFunc.random_strs(100),
"name": 'name' + p.CommonFunc.random_strs(100)
}
)
r = p.requests.request("post", url=self.__class__.url_test, json=self.params_test, headers=self.__class__.header)
test_result = p.json.loads(r.text)
msg = p.CommonFunc.get_msg(test_result)
if r.status_code == 200:
self.assertFalse(test_result['success'],
'测试不通过,未校验字段长度;【URL: {}】,【PARAMS: {}】,【MSG: {}】'
.format(r.url, self.params_test, msg))
else:
self.assertFalse(
test_result['success'],
"""
测试不通过,ERROR
【URL】: {},
【PARAMS】: {},
【STATUS】: {},
【MSG】: {}
""".format(r.url, self.params_test, r.status_code, msg))
def test_antibiotic_dict_007(self):
"""7、【新增字典】新增停用状态,预期:成功"""
self.params_test.update(
{
"code": 'code' + p.CommonFunc.random_strs(10),
"isValid": 0
}
)
r = p.requests.request("post", url=self.__class__.url_test, json=self.params_test,
headers=self.__class__.header)
test_result = p.json.loads(r.text)
msg = p.CommonFunc.get_msg(test_result)
if r.status_code == 200:
self.assertTrue(
test_result['success'],
"""
测试不通过,未校验停启用状态
【URL】: {},
【PARAMS】: {},
【STATUS】: {},
【MSG】: {}
""".format(r.url, self.params_test, r.status_code, msg))
else:
self.assertTrue(
test_result['success'],
"""
测试不通过,ERROR
【URL】: {},
【PARAMS】: {},
【STATUS】: {},
【MSG】: {}
""".format(r.url, self.params_test, r.status_code, msg))
def test_antibiotic_dict_007(self):
"""8、【新增字典】"""
pass
def tearDown(self):
"""
环境的恢复还原,执行每个测试用例的后置条件,如:删除测试用例执行的脏数据等
"""
pass
@classmethod
def tearDownClass(cls):
"""
必须使用@classmethod装饰器,所有case执行的前置条件,只运行一次
"""
pass
4、运行测试用例
if __name__ == '__main__':
# verbosity=*:默认是1;设为0,则不输出每一个用例的执行结果;设为2 输出详细的执行结果
# 为1;执行成功输出为 . ,失败是 F,出错是 E,跳过是 S
# 为2:打印测试的注释
p.unittest.main(verbosity=2)