django 单元测试小结

django 测试


从前很少写单元测试了,特别是web应用。最近不知不觉喜欢起来这个事情了,发现单元测试对于软件的模块,正交性有很大促进作用,因为函数,模块写的不合理,单元测试写起来就麻烦的多呀。公司的项目一直都是用Django,所以写点django单元测试的小总结,记录为主,备查。

 

测试的场景

框架Django1.8 测试工具 unittest, 要记得给test设置一个独特的settings。

  1. 测试请求 也就是测试整个view部分 官方案例 其中可能会遇到登录,或者时session怎么模拟的问题

  2. 测试带有orm的模块

  3. 需要mock的测试,比较多的情况是有第三方API调用, 发邮件,发短信这种

unittest提供的断言种类挺多,但是经常用的也就几个 self.assertContains, self.assertEqual, self.assertTrue

顺便提下有用的选项(我这里是单独给测试写了一个settings), 为了提高测试速度,可以把用不到的中间件,installed_apps之类的多余配置给去掉。

 
  1. 测试全部用例
  2. python manage.py test --setting settings_test
  3. 测试某个APP
  4. python manage.py test appname --setting settings_test
  5. 测试某个app下的TeseCase类
  6. python manage.py test alarm.tests.ModelTestCase--setting settings_test
  7. -v {1,2,3}数字越大,显示的输出越详细,测试的日志信息
  8. python manage.py test --setting settings_test -v3
  9. 其他的选项请查看--help
  10. python manage.py test --help
 

用请求测试 views函数

DJANGO中提供了Client类来模拟http请求,可以模拟不同的method,然后就是请求参数的模拟,用起来很方面。

 
  1. #coding:utf-8
  2. from django.test importTestCase,Client
  3. from sendviews import*
  4. from core.tests import create_user
  5. classSendviewsTestCase(TestCase):
  6. def setUp(self):
  7. self.user = create_user()
  8. self.device =Device(hostname="CN-BJ-0000-00",
  9. mac="ff:ff:ff:ff:ff:ff", user=self.user).save()
  10. def test_creat_sms(self):
  11. c =Client()
  12. rep = c.post("/acquireportal/createsms",{"phone":"13988902345",
  13. "ssid":"erya",
  14. "dmac":"ff:ff:ff:ff:ff:ff"})
  15. # 测试http请求的返回码是否正确
  16. self.assertEqual(rep.status_code,200)
  17. # 测试response的内容是否包含字符串
  18. self.assertContains(rep,"OK")
  19. # 测试response的内容是否包含字符串 方法二
  20. self.assertTrue('OK'in rep.content)
  • 操作 session,例如用户登录,特殊的session值
 
  1. from django.test importClient
  2. def init_client(user):
  3. client =Client()
  4. client.login(username=user.username, password="lzz")
  5. s = client.session
  6. s['cur_user_id']= user.id
  7. s.save()
  8. return client
  • 增加header
 
  1. from django.test.utils import setup_test_environment
  2. setup_test_environment()
  3. from django.test.client importClient
  4. c =Client()
  5. # get 请求,带参数,并增加header
  6. c.get('/some/path/',{'qs_param':'foo'},**{'HTTP_USER_AGENT':'silly-human','REMOTE_ADDR':'127.0.0.1'})
  7. #get 请求,没有带参数,自定义headers
  8. c.get('/some/path/',**{'HTTP_USER_AGENT':'silly-human','REMOTE_ADDR':'127.0.0.1'})
  • 使用 RequestFactory 对象来进行测试,不是从 http client来发起,某些情况会用到
 
  1. from django.test importTestCase,RequestFactory
  2. from django.http importHttpResponse
  3. from util.sign import generate_sign, validate_sign
  4. from util.decorators import apiauth_required, SIGN_KEY
  5. @apiauth_required()
  6. def simpleapi(request):
  7. returnHttpResponse('ok')
  8. classDecoratorsTestCase(TestCase):
  9. def setUp(self):
  10. self.factory =RequestFactory()
  11. def test_apiauth(self):
  12. # create request object
  13. key = SIGN_KEY
  14. query_string ={u"name": u"lzz", u"age": u"20", u"data": u"[python, java, golang, lua]"}
  15. token = generate_sign(query_string, key)
  16. query_string.update({u"sign": token})
  17. req =self.factory.post("/api/test", data=query_string)
  18. response = simpleapi(req)
  19. self.assertEqual(response.status_code,200)
  • HTML 文本测试,使用 constants 来判断并不是个好的选择,可以用render之后的字符串对比。

对于需要登陆的view,有client也比较容易操作,还有一些特殊的session的检测等, 我这里做了一个简单的封装

 
  1. from django.test importClient
  2. def init_client(user):
  3. client =Client()
  4. client.login(username=user.username, password="lzz")
  5. s = client.session
  6. s['cur_user_id']= user.id
  7. s.save()
  8. return client
 

带有mock的测试

对模块中的方法mock或者是对一个对象中的方法进行mock。真对测试函数中一些无法直接测试的函数设置默认的返回值, py3标准库中已经有了mock模块,py2需要自己安装, 推荐教程 使用Pyhton Mock进行单元测试1。 下面是个实际的代码片段。

 
  1. import mock
  2. from django.test importTestCase
  3. from core.models importTenant
  4. from alarm.models import*
  5. from.controler importTenantAlarm
  6. classModelTestCase(TestCase):
  7. def setUp(self):
  8. self.tenant =Tenant.objects.create(domainname="erya", comname=u"尔雅")
  9. @mock.patch.object(TenantAlarm,"sendAlarm")
  10. def test_record_alarm(self, mock_method):
  11. # record_alarm 这个中会调用sendAlarm方法
  12. mock_method.return_value =None
  13. content ="ccccc"
  14. atype =0
  15. rec_uid =0
  16. Alarm().record_alarm(content=content, atype=0,
  17. rec_tid=self.tenant.id)
  18. classTenantAlarmTestCase(TestCase):
  19. def setUp(self):
  20. self.tenant =Tenant.objects.create(domainname="erya", comname=u"尔雅")
  21. @mock.patch.object(TenantAlarm,"sendSMS", return_value=None)
  22. @mock.patch.object(TenantAlarm,"sendEmail", return_value=None)
  23. def test_send_alarm(self, method1, method2):
  24. content = u"报警了"
  25. ta =TenantAlarm(self.tenant.id, content,{u'SMS':0, u'EMAIL':0})
  26. ta.sendAlarm()
  27. @mock.patch('util.sendsms_com.send', return_value=1)
  28. def test_sendsms(self, send):
  29. ta =TenantAlarm(self.tenant.id,self.content,{u'SMS':0, u'EMAIL':0})
  30. ta.sendSMS()
  31. self.assertEqual(0,Account.objects.get(tenant=self.tenant).sms_num)
  32. self.account.sms_num =100
  33. self.account.save()
  34. ta.sendSMS()
  35. self.assertEqual(99,Account.objects.get(tenant=self.tenant).sms_num)
 

coverage

coverage是一个检查单元测试覆盖率的工具,django的文档中也有简要的说明coverage的集成 文档地址

 
  1. #测试并收集测试信息
  2. coverage run --source='.' manage.py test --setting mandela.settings_test
  3. #查看测试结果
  4. coverage report -m
  5. NameStmtsMissCoverMissing
  6. ----------------------------------------------------------------------------------------
  7. acquireportal/__init__.py 00100%
  8. acquireportal/controler.py 654728%22-56,60-71,76-79
  9. acquireportal/migrations/0001_initial.py 60100%
  10. acquireportal/migrations/0002_auto_20160622_1059.py 60100%
  11. acquireportal/migrations/0003_auto_20160622_1100.py 50100%
  12. ....
  13. ----------------------------------------------------------------------------------------
  14. TOTAL 8013585827%

覆盖率挺低的

django单元测试的更多相关文章

  1. [Django] 单元测试小记

    从前很少写单元测试了,特别是web应用.最近不知不觉喜欢起来这个事情了,发现单元测试对于软件的模块,正交性有很大促进作用,因为函数,模块写的不合理,单元测试写起来就麻烦的多呀.公司的项目一直都是用Dj ...

  2. 如何进行Django单元测试

    如何进行Django单元测试 Django的单元测试使用python的unittest模块,这个模块使用基于类的方法来定义测试.类名为django.test.TestCase,继承于python的un ...

  3. Django 单元测试

    mock 测试 mock 是辅助单元测试的模块,用于测试不方便调用的别人的接口.举个简单的例子,比如说,我们测试django 写的微信登录接口,正常流程下,我们需要前端拉起授权窗口,获取jscode或 ...

  4. Django单元测试 相关知识

    前言 本文,旨在说明python Django如何编写单元测试,从“背景”,“测试要求”,“代码编写”,“如何运行”,“检验测试覆盖度” 这几个方面来说明附上django的官方文档单元测试章节=> ...

  5. Django 单元测试笔记

    引言 关于单元测试的基本知识这里不再讲述,简单一句话:单元测试是用一段代码去测试另一段代码.最常用的框架是unittest,这是python的单元测试框架,而django单元测试框架test.Test ...

  6. Django单元测试(一)

    Django测试框架非常简单,首选方法是使用python标准库中的unittest模块. Writing tests Django的单元测试使用python的unittest模块,这个模块使用基于类的 ...

  7. django 单元测试错误总结

    TestCase django自带有一个TestCase模块来进行测试,我们可以参考官网 来写单元测试的代码.我这里主要是总结一些错误. 用户无法登陆 我们有些api登录后才可以进行测试,所以我们可以 ...

  8. django 单元测试小结

    测试的场景 框架Django1.8 测试工具 unittest, 要记得给test设置一个独特的settings. 测试请求 也就是测试整个view部分 官方案例 其中可能会遇到登录,或者时sessi ...

  9. Django单元测试中Fixtures用法

    在使用单元测试时,有时候需要测试数据库中有数据,这时我们可以使用Django的Fixtures来生成测试数据. 基础配置 在settings.py 中配置如下内容: FIXTURE_DIRS = (' ...

随机推荐

  1. 单片机中用c编程时头文件reg51.h及reg52.h解析

    单片机中用c编程时头文件reg51.h及reg52.h解析 我们在用c语言编程是往往第一行就是reg51.h或者其他的自定义头文件,我们怎么样来理解呢? 1)“文件包含”处理. 程序的第一行是一个“文 ...

  2. 安卓APP测试验证点总结

    最近较懒,加之闺女出生后记忆没完全恢复,总是忘东忘西,关于安卓APP测试的验证点还是总结一下,方便设计测试用例时查阅,也给各位博友参考! 1.除APP的正常功能点外,还有以下验证点: 安装/卸载(考虑 ...

  3. 移动web app 中的meta 标签

    <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scal ...

  4. MongoDB可视化工具RoboMongo----Windows安装 1

    https://robomongo.org/download 非常小白的安装 自动安装完成. 启动MongoDB Mongodb启动教程 启动RoMongo 创建新的Mongodb 自定义db名称 连 ...

  5. js中array的join和concat的区别

    首先:concat方法定义:concat() 方法用于连接两个或多个数组.该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本.举例说明:1 /*concat()结果返回的是一个数组*/ 2 3 ...

  6. MacBook Pro/Air 下使用 linux ubuntu 系统 波浪号“~”变成其他 符号 的完美解决办法

    打开终端,输入: sudo su - > /sys/module/hid_apple/parameters/iso_layout sudo su -需要root权限,所以使用前请注意已下载roo ...

  7. 基于 EntityFramework 的数据库主从读写分离

    现在刚开始来研究EntityFramwork,起初是在vs2012中通过工具来创建EF ,但是对我这种不熟悉菜鸟来说 有很多业务用EF做出来还是有点难度的,今天来手动搭建一个EF框架,大神勿喷

  8. 转 LoadRunner 技巧之 IP欺骗 (推荐)

    IP欺骗也是也loadrunner自带的一个非常有用的功能. 需要使用ip欺骗的原因: 1.当某个IP的访问过于频繁,或者访问量过大是,服务器会拒绝访问请求,这时候通过IP欺骗可以增加访问频率和访问量 ...

  9. CSAPP学习笔记(异常控制流1)

    1:诸如子进程结束之后父进程需要被告知,有时候应用程序需要系统调用,内核通过上下文切换将控制从一个进程切换到另一个进程,还有一个进程发送信号到另一个进程时接收者转而到它的信号处理函数去执行等等,我们的 ...

  10. Log Buffer

    Log Buffer 一.Log Buffer的引入 Oracle有一个原则:只要是已经提交的数据,就不会丢失,保证数据库的一致性.这该如何实现?事物提交时,直接写入dbf中,效率是极低的.因为直接写 ...