一、什么是单元测试?
1. 单元测试是用来对一个模块、函数、类、接口等进行正确性检验的工作。
2. 比如测试接口,输入不同的参数,其运行结果是否与我们期待的结果一致,把许多测试用例放到一个测试模块里,就是一个完整的单元测试
3. python的单元测试有unittest、pytest、PyUnit等测试框架
4. 也可以使用requests包,模拟浏览器请求进行接口测试,例如:
import requests
def test_duty_add(self):
params = {'departId': 1, 'roleId': 1, 'staffId': 2, 'dutyDate': '2018-08-02'}
url = 'http://127.0.0.1:5000/duty/'
test_result_01 = requests.post(url, params=params, headers=self.headers)
print u'测试1:新增单条值班记录 '+test_result_01.url
if test_result_01.json()['msg'] == u'数据提交成功':
print 'Success'
else:
print 'Fail:'+test_result_01.json()['msg']
二、unittest工作原理
1. unittest中最核心的四部分是:TestCase,TestSuite,TestRunner,TestFixture
2. 一个TestCase的实例就是一个测试用例。测试用例就是指一个完整的测试流程,包括测试前准备环境的搭建(setUp),执行测试代码(run),以及测试后环境的还原(tearDown)。元测试(unit test)的本质也就在这里,一个测试用例是一个完整的测试单元,通过运行这个测试单元,可以对某一个问题进行验证。
3. 而多个测试用例集合在一起,就是TestSuite,而且TestSuite也可以嵌套TestSuite。
4. TestLoader是用来加载TestCase到TestSuite中的。
5. TextTestRunner是来执行测试用例的,其中的run(test)会执行TestSuite/TestCase中的run(result)方法
6. 测试的结果会保存到TextTestResult实例中,包括运行了多少测试用例,成功了多少,失败了多少等信息。
7. 整个流程就是首先要写好TestCase,然后由TestLoader加载TestCase到TestSuite,然后由TextTestRunner来运行TestSuite,运行的结果保存在TextTestResult中,整个过程集成在unittest.main模块中。
三、开始单元测试
3.1 说明:
1. 以下代码演示的是:对Flask项目进行接口测试,测试所有接口是否返回预期的结果,形成单元测试流程
2. 利用Flask自带的测试客户端test_client,模拟一个Flask app,进行接口测试,加上unittest进行单元测试
3.2 具体操作
1. 首先在与app文件夹同级的目录,创建一个teses文件夹,用于所有的单元测试
2. 之后在testapi.py文件下引入一个 Flask app,创建一个测试客户端,集成到unittest测试框架中,可以在测试初始化中(setUpClass)创建一个test_client,之后在环境的销毁中(tearDownClass)销毁所有的东西
#### testapi.py 文件
import unittest
import json
from app import create_app, db
test_app = create_app('test_config')
LOGINED_HEADERS = None
LOGINED_USER_INFO = None
class AllTestInit(unittest.TestCase):
# 第一个测试前初始化
@classmethod
def setUpClass(cls):
# 测试客户端初始化
cls.test_app = test_app.test_client()
db.create_all(app=test_app)
cls.headers = {'Content-Type': 'application/json;charset=UTF-8', 'jwt_token': ''}
# 测试结束清理
@classmethod
def tearDownClass(cls):
with test_app.app_context():
db.session.remove()
db.drop_all()
del LOGINED_HEADERS, LOGINED_USER_INFO
class AllTestDemo(AllTestInit):
####################
# Helper Functions #
####################
# BlueUser
def register(self, username, fullname, mobile, password, client_type):
# 参数为json类型的数据
return self.test_app.post('/users/register', data=json.dumps(
dict(username=username, fullname=fullname, mobile=mobile, password=password, client_type=client_type)),
headers=self.headers)
####################
# TEST Functions #
####################
# 带有test开头的函数,会识别为测试方法
def test_data_init(self):
# 在flask上下文中进行数据初始化
with test_app.app_context():
data_init()
def test_register(self):
response = self.register(TEST_REGISTER_USER['uname'], TEST_REGISTER_USER['fname'],
TEST_REGISTER_USER['mobile'], TEST_REGISTER_USER['pwd'],TEST_REGISTER_USER['client_type'])
self.assertEqual(u'数据提交成功', json.loads(response.data)['msg'])
3. 在runtest.py中启动测试方法,可以指定测试的顺序
### runtest.py 文件
import unittest
from testapi import AllTestDemo
if __name__ == '__main__':
test_suite = unittest.TestSuite()
# 如只测试数据初始化、注册、登录
test_cases_logout = [AllTestDemo('test_data_init'), AllTestDemo('test_register'), AllTestDemo('test_user_login')]
# 加载到测试中
test_suite.addTests(test_cases_logout)
runner = unittest.TextTestRunner(verbosity=2)
runner.run(test_suite)
4. 总结就是,首先写一个TestCase类,里边测试环境准备,测试方法,环境销毁;多个TestCase类加载到TestSuit中(可以控制测试类及测试方法顺序);由TextTestRunner来运行TestSuite;运行的结果保存在TextTestResult中
5. 也可以用HTMLTestRunner输出漂亮的HTML报告; 首先需要下载HTMLTestRunner.py,并放到当前目录下,或者python目录下的Lib中,就可以导入运行了。下载地址:http://tungwaiyip.info/software/HTMLTestRunner.html
6. 具体的可以参照更为详细的一位大牛的博客:https://blog.csdn.net/xiaoquantouer/article/details/75089200?utm_source=blogxgwz1