flask-sqlalchemy单元测试
1、单元测试
web程序开发过程一般包含下述几个阶段:需求分析、设计阶段、实现阶段、测试阶段,其中测试阶段就是通过自动、手动来测试某个系统的功能,目的就是检测是否满足需求,得到预期结果和实际结果的差别。
测试从软件开发过程可以分为:单元测试、集成测试、系统测试等。在这些测试的过程中,与开发人员最密切的就是单元测试。其他的测试均有专业的测试人员测试完成。
程序开发过程中,当我们的代码通过了编译,只是说明代码语法正确,功能是否有健壮性不能保障,因此当我们某些功能代码完成后,为了检测代码是否满足程序的需求,我们需要对代码进行单元测试,检测功能是否符合预期(单元测试就是开发者编写一小段代码,检测目标代码是否符合预期,通常情况下,单元测试主要面向一些功能单一的模块进行)。
2、断言
在web开发过程中,单元测试其实就是一些断言assert代码。断言就是判断一个函数或对象的一个方法所产生的结果是否达到预期结果。
def num_div(num1,num2):
# 断言是一个boolean类型表达式
# 表达式真 断言成功 程序继续执行
# 表达式假 断言失败 程序抛出异常AssertError 终止程序
assert isinstance(num1,int)
assert isinstance(num2,int)
assert num2 != 0
print(num1/num2)
num_div(10,0)
3、单元测试
python中提供了专门用于单元测试的模块unittest。我们可以创意一个单元测试案例类。
3.1、创建登陆接口
以登陆为例,form表单不同的参数返回不同的结果。
@app.route('/login',methods=['POST'])
def login():
# 接收参数
user_name = request.form.get('user_name')
user_pass = request.form.get('user_pass')
# 参数判断 并返回值
if not all([user_name,user_pass]):
resp = {
'code':1,
'message':'参数异常'
}
return jsonify(resp)
if user_name == 'admin' and user_pass == 'python':
resp = {
'code': 0,
'message': '登陆成功'
}
return jsonify(resp)
else:
resp = {
'code': 2,
'message': '用户名或者密码错误'
}
return jsonify(resp)
3.2、创建测试实例
创建测试类,引入unittest
import unittest
from login import app
import json
3.2.1、测试参数不完整情况
参数不完整分为三种情况:
1、缺少用户名
2、缺少密码
3、缺少用户名和密码
注意,方法要以test开头。
# 构建单元测试用例
# 测试用户名、密码不完整情况
# 注意单元测试用例 一定要以test开头
def test_empty_user_name_pass(self):
# 创建测试的客户端
client = app.test_client()
# 利用客户端模拟发送登陆请求 接收响应对象
# get请求使用Get post请求使用Post方法
# 1、测试用户名、密码均为空
ret = client.post('/login',data={})
# 获得响应体
response_str = ret.data
# 视图返回json字符串 转换为字段
response = json.loads(response_str)
# 利用断言进行测试
self.assertIn('code', response)
self.assertEqual(response['code'],1)
# 2、测试用户名为空或者密码为空
ret = client.post('/login', data={
'user_name':'admin'
})
# 获得响应体
response_str = ret.data
# 视图返回json字符串 转换为字段
response = json.loads(response_str)
# 利用断言进行测试
self.assertIn('code', response)
self.assertEqual(response['code'], 1)
# 3、测试用户名为空
ret = client.post('/login', data={
'user_pass': 'python'
})
# 获得响应体
response_str = ret.data
# 视图返回json字符串 转换为字段
response = json.loads(response_str)
# 利用断言进行测试
self.assertIn('code', response)
self.assertEqual(response['code'], 1)
运行测试用例
if __name__ == '__main__':
# 执行当前文件的所有测试行为
unittest.main()
3.2.2、测试参数不正确情况
参数不正确情况应该分三种情况:
1、用户名错误
2、密码错误
3、用户名和密码都错误
注意,方法要以test开头。
def test_wrong_user_name_pass(self):
# 创建测试的客户端
client = app.test_client()
# 利用客户端模拟发送登陆请求 接收响应对象
# get请求使用Get post请求使用Post方法
# 1、测试用户名错误
ret = client.post('/login',data={
'user_name':'root',
'user_pass':'python'
})
# 获得响应体
response_str = ret.data
# 视图返回json字符串 转换为字段
response = json.loads(response_str)
# 利用断言进行测试
self.assertIn('code', response)
self.assertEqual(response['code'],2)
# 2、测试密码错误
ret = client.post('/login', data={
'user_name':'admin',
'user_pass':'admin'
})
# 获得响应体
response_str = ret.data
# 视图返回json字符串 转换为字段
response = json.loads(response_str)
# 利用断言进行测试
self.assertIn('code', response)
self.assertEqual(response['code'], 2)
# 3、测试用户名、密码都错误
ret = client.post('/login', data={
'user_name':'admin1',
'user_pass': 'python1'
})
# 获得响应体
response_str = ret.data
# 视图返回json字符串 转换为字段
response = json.loads(response_str)
# 利用断言进行测试
self.assertIn('code', response)
self.assertEqual(response['code'], 2)
3.2.3、简单优化上述代码
在测试用例类中加入setUP方法,减少我们代码的重复性。该方法是在测试方法前先执行setUp方法。
class LoginTest(unittest.TestCase):
# 在测试方法执行前执行该方法
def setUp(self):
# 测试模式
app.config['TESTING'] = True
# 创建测试的客户端
self.client = app.test_client()
# 所有的测试执行后 执行 一般用来清理操作
def tearDown(self):
print('测试执行完毕')
# 构建单元测试用例
# 测试用户名、密码不完整情况
# 注意单元测试用例 一定要以test开头
def test_empty_user_name_pass(self):
# 利用客户端模拟发送登陆请求 接收响应对象
# get请求使用Get post请求使用Post方法
# 1、测试用户名、密码均为空
ret = self.client.post('/login', data={})
# 获得响应体
response_str = ret.data
# 视图返回json字符串 转换为字段
response = json.loads(response_str)
# 利用断言进行测试
self.assertIn('code', response)
self.assertEqual(response['code'], 1)
# 2、测试用户名为空或者密码为空
ret = self.client.post('/login', data={
'user_name': 'admin'
})
# 获得响应体
response_str = ret.data
# 视图返回json字符串 转换为字段
response = json.loads(response_str)
# 利用断言进行测试
self.assertIn('code', response)
self.assertEqual(response['code'], 1)
# 3、测试用户名为空
ret = self.client.post('/login', data={
'user_pass': 'python'
})
# 获得响应体
response_str = ret.data
# 视图返回json字符串 转换为字段
response = json.loads(response_str)
# 利用断言进行测试
self.assertIn('code', response)
self.assertEqual(response['code'], 1)
def test_wrong_user_name_pass(self):
# 利用客户端模拟发送登陆请求 接收响应对象
# get请求使用Get post请求使用Post方法
# 1、测试用户名错误
ret = self.client.post('/login', data={
'user_name': 'root',
'user_pass': 'python'
})
# 获得响应体
response_str = ret.data
# 视图返回json字符串 转换为字段
response = json.loads(response_str)
# 利用断言进行测试
self.assertIn('code', response)
self.assertEqual(response['code'], 2)
# 2、测试密码错误
ret = self.client.post('/login', data={
'user_name': 'admin',
'user_pass': 'admin'
})
# 获得响应体
response_str = ret.data
# 视图返回json字符串 转换为字段
response = json.loads(response_str)
# 利用断言进行测试
self.assertIn('code', response)
self.assertEqual(response['code'], 2)
# 3、测试用户名、密码都错误
ret = self.client.post('/login', data={
'user_name': 'admin1',
'user_pass': 'python1'
})
# 获得响应体
response_str = ret.data
# 视图返回json字符串 转换为字段
response = json.loads(response_str)
# 利用断言进行测试
self.assertIn('code', response)
self.assertEqual(response['code'], 2)