文章目录
1.python及django编写单元测试。
测试驱动开发: 我们知道自己需要的功能,但是代码不知道怎么写。可以利用测试驱动开发,先写出我们期待的结果,再去完善代码。
《改善Python的91个建议》一书中说:单元测试绝不是浪费时间的无用功,它是高质量代码的保障之一,在软件开发的一节中值得投入精力和时间去把好这一关。
这里先不说django.
python里面的单元测试应该怎么写?
用unittest
先写个除法功能
先写一个简单的除法 命名为divi.py
def divi(a, b):
if isinstance(a, (float, int)) and isinstance(b, (float, int)):
if b == 0:
return False
else:
return a / b
else:
return False
代码写完之后需要测,怎么测?
测试用例编写
# ddt need install. use pip3 install ddt
import ddt
import unittest
from divi import divi
import time, os
#import HTMLTestRunner
# 来一篇unitest。
# 后面再来一篇pytest的讲解.
data = [
{'num_a': 1, 'num_b': 2, 'result': 0.5},
{'num_a': 1, 'num_b': 0, 'result': False},
{'num_a': '4', 'num_b': 2, 'result': False},
{'num_a': 5.2, 'num_b': 2, 'result': 2.6},
{'num_a': 2.724, 'num_b': 10, 'result': 0.2724},
]
@ddt.ddt
class Test(unittest.TestCase):
def setUp(self):
# 这里是干嘛的?用于测试用例执行前的初始化操作。
# 连接数据库,初始化浏览器
print('======test start======')
@ddt.data(*data)
def test_01(self, data1):
self.assertEqual(divi(data1['num_a'], data1['num_b']), data1['result'])
def tearDown(self):
# 用于测试用例执行之后的善后工作。
# 关闭数据库,关闭浏览器之类的
print('======test end======')
# TestDivi().test_divi(data)
if __name__ == "__main__":
unittest.main()
这里面有个ddt, ddt是什么?
ddt包含类装饰器ddt和两个方法装饰器data(直接输入测试数据),file_data(可以从json或yaml中获取测试数据)
通常情况下,data中的数据按照一个参数传递给测试用例,如果data中含有多个数据,以元组,列表,字典等数据,需要自行在脚本中对数据进行分解或者使用unpack分解数据。
@data(a,b) # a, b 各运行一次用例
@data([a,d][c,b] # 如果没有@unpack, 那么[a,b]会被当作一个参数传入用例运行。
如果有unpack,那么[a,b]会被分解开,按照用例中的两个参数传递。
@file_data(filename) 对于json文件,每个json元素按照一个用例运行。
import unittest
from ddt import ddt,data,file_data,unpack
@ddt
class demotest(unittest.TestCase):
def setup(self):
print "this is the setup"
@data(2,3)
def testb(self,value):
print value
print "this is test b"
@data([2,3],[4,5])
def testa(self,value):
print value
print "this is test a"
@data([2, 3], [4, 5])
@unpack
def testc(self, first,second):
print first
print second
print "this is test c"
@file_data('d:/data_dic.json')
def test_dic(self,value):
print value
print 'this is dic'
@file_data('d:/data.yml')
def test_yml(self, value):
print value
print 'this is yml'
def teardown(self):
print "this is the down"
if __name__ == '__main__':
unittest.main()
#suite=unittest.TestLoader.getTestCaseNames(demotest)
#suite = unittest.TestLoader().loadTestsFromTestCase(demotest)
#unittest.TextTestRunner(verbosity=2).run(suite)
用pytest
TODO
django编写测试用例
1.引用的是TestCase基类
django 测试用例:django.test继承了python标准库unittest. 所以测试用例类继承django.test.TestCase即可:
from django.test import TestCase
class MyClassTestCase(TestCase):
def SetUp(self):
pass
def test_my_func(self):
pass
2.用例执行:
./manage.py test
默认用例执行语句:会发现当前目录下的所有以test开头的py文件,并执行;此外用户还可以自己指定用例所在目录以及用例文件名匹配规则。
3.Client使用:
主要用于模仿url请求,调用并返回请求结果。
response = self.client.get("/vpc/list")
self.assertEquals(response.status_code, 302)
4. RequestFactory使用:
主要用于构造request对象,与Client相比,没有发生url接口的调用。
request = self.request_factory.post('vpc/list', data={'start': 0, 'length': 10})
vpc_manage = VpcManage(request)
5.断言(Assertions):
判断用例执行结果的主要手段,断言测试函数返回结果跟预计结果的一致性。
self.assertEquals(res['recordsTotal'], 0)
6.mock的使用
单元测试主要测试的是函数级功能,所以需要通过mock对待测函数中调用到的方法进行打桩,返回便于测试的值。
vpc_manage.get_user_info = mock.Mock(return_value=mock.Mock(**self.user_info_attrs))
res = vpc_manage.vpc_list()
res = json.loads(res)
7.仅仅执行用例:
python manage.py test -v 2
更多信息参考:
https://docs.djangoproject.com/zh-hans/2.2/topics/testing/overview/ 官网
https://code.ziqiangxuetang.com/django/django-test.html
https://www.jianshu.com/p/b2a8665018e1 django单元测试需要指定mysql测试数据库
https://juejin.im/post/5d8593f1e51d453bb13b66fa 掘金测试方法总结
2.文件代码覆盖率问题。
什么是代码覆盖率?
我们自己写代码的时候,会尝试写一些测试用例来测试代码的每个分支是否都走到了。有可能有的分支走到了,而有的分支一直都没有走到。走到的分支是覆盖到的,没有走到的分支是没有覆盖的。
要实现代码覆盖,需要安装coverage 这个可以实现代码覆盖率的检测。
如何测试代码覆盖率呢?这里需要安装coverage模块。 pip3 install coverage
如果只是简单的python文件,比如我上面举到的例子,执行coverage run test_divi.py
即可。
如果是django项目。
coverage run --source '.' manage.py test -v 2
执行之后可以根据coverage report -m
来获取代码的覆盖率。这个不能生成覆盖率html图。
如果完全覆盖了,可以使用coverage html
来生成代码覆盖率html图
coverage erase
可以删除创建的.coverage.
需要注意的是,覆盖率数据只能代表你测试过哪些代码,不能代表你是否测试好这些代码。
重构那本书的作者曾经写过一篇博客来讨论这个问题,他指出:把测试覆盖作为质量目标没有任何意义,而我们应该把它作为一种发现未被测试覆盖的代码的手段。
关于django有一个插件django_coverage_plugin
更多coverage信息参考:
https://www.cnblogs.com/coderzh/archive/2009/03/29/1424344.html
https://www.bedjango.com/blog/package-week-coverage-django/
https://coverage.readthedocs.io/en/v4.5.x/
3.关于测试报告
如果想生成测试报告,不考虑框架的情况下,可以使用HTMLTestRunner.py 这个不适合直接安装,python3可以参考
https://github.com/defnngj/HTMLTestRunner
当然,我们项目要采用下面的持续集成,因为代码仓库用的是gitlab, 所以就不添加测试报告,直接测完之后看结果。
4.CI里面搭建持续集成环境
TODO
参考:
https://www.jianshu.com/p/705428ca1410
http://py3study.com/Article/details/id/139.html