程序开发过程中,代码是为了完成需求,当代码编译通过后,能不能保证功能的正常实现,需要我们编写测试代码,模拟程序运行过程,检验功能是否符合预期。
单元测试主要面向一些功能单一的模块进行。
单元测试,实际上就是一些“断言”的代码,用于判断函数或对象的一个方法所产生的结果是否符合预期
python中,断言是申明结果为真的判定,如果表达式为假,程序会发生异常。
常用的断言有:
assertTrue() 条件为True,则pass
assertFalse() 条件为False,则pass
assertEqual() 两个值相等,则pass
assertNotEqual() 两个值不相等,则pass
assertIsNone() 不存在,则pass
assertIsNotNone 存在,则pass
Flask单元测试中用的是python自带的测试框架unittest
(flask,django等都可以直接使用这个框架,不过django对它进行了封装,具体可以看源代码django.test.TestCase)
基本的结构是:
import unittest
class Test(unittest.TestCase):
def setUp(self):
pass
def tearDown(self):
pass
def test_something1(self):
pass
def test_something2(self):
pass
if __name__=="__main__":
unittest.main()
上面代码执行顺序是:setUp()---->test_something1()---->tearDown()
setUp()---->test_something2()----->tearDown()
setUp():
用于初始化app,db等
tearDown():
用于释放资源等
test_something():
测试主题,函数名以test_开头
完整代码如下:
import unittest
from apps.model import db
class Test(unittest.TestCase)
from apps import instance_app
def setUp(self):
# 实例化核心对象
self.app = instance_app()
# 更新server_name
self.app.config.update(SERVER_NAME='your server name')
# 获取应用上下文
self.app_ctx = self.app.app_context()
self.app_ctx.push()
# 配置测试用数据库
self.app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+cymysql://用户名:密码@IP:PORT/DATABASE_NAME"
# 开启测试标记,可以帮忙定位测试信息
self.app.config("TESTING") = True
# 创建表
self.client = self.app.test_client()
db.create_all()
def tearDown(self):
移除数据库会话对应,如果没有移除数据库会话对象,会导致程序一直运行,无法结束。
db.session.remove()
# 删除测试数据库的所有表
db.drop_all()
def test_case(self):
res = self.client.get(url_for("endpoint"))
res1 = self.client.post(url_for(endpoint), data={})
# 断言:判断返回结果中包含test字符串 as_text=True是将结果转化为字符串
self.assertTrue("test" in res.get_data(as_text=True))
self.assertTrue(res1.status_code==200)
if __name__=="__main__":
unittest.main()
如果项目使用了蓝图,在使用url_for的时候,要传入(蓝图.endpoint)
如我项目中用到了两个蓝图
那么我在对应的做测试的时候,需要这样写: