测试的场景

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

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

  2. 测试带有orm的模块

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

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

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

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

用请求测试 views函数

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

#coding:utf-8
from django.test import TestCase, Client from sendviews import *
from core.tests import create_user class SendviewsTestCase(TestCase): def setUp(self):
self.user = create_user()
self.device = Device(hostname="CN-BJ-0000-00",
mac="ff:ff:ff:ff:ff:ff", user=self.user).save() def test_creat_sms(self):
c = Client()
rep = c.post("/acquireportal/createsms",{"phone": "13988902345",
"ssid": "erya",
"dmac": "ff:ff:ff:ff:ff:ff"})
# 测试http请求的返回码是否正确
self.assertEqual(rep.status_code, 200)
# 测试response的内容是否包含字符串
self.assertContains(rep, "OK")
# 测试response的内容是否包含字符串 方法二
self.assertTrue('OK' in rep.content)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 操作 session,例如用户登录,特殊的session值
from django.test import Client

def init_client(user):
client = Client()
client.login(username=user.username, password="lzz")
s = client.session
s['cur_user_id'] = user.id
s.save()
return client
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 增加header
from django.test.utils import setup_test_environment
setup_test_environment()
from django.test.client import Client
c = Client() # get 请求,带参数,并增加header
c.get('/some/path/', {'qs_param':'foo'}, **{'HTTP_USER_AGENT':'silly-human', 'REMOTE_ADDR':'127.0.0.1'}) #get 请求,没有带参数,自定义headers
c.get('/some/path/', **{'HTTP_USER_AGENT':'silly-human', 'REMOTE_ADDR':'127.0.0.1'})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 使用 RequestFactory 对象来进行测试,不是从 http client来发起,某些情况会用到
from django.test import TestCase, RequestFactory
from django.http import HttpResponse
from util.sign import generate_sign, validate_sign
from util.decorators import apiauth_required, SIGN_KEY @apiauth_required()
def simpleapi(request):
return HttpResponse('ok') class DecoratorsTestCase(TestCase): def setUp(self):
self.factory = RequestFactory() def test_apiauth(self):
# create request object
key = SIGN_KEY
query_string = {u"name": u"lzz", u"age": u"20", u"data": u"[python, java, golang, lua]"}
token = generate_sign(query_string, key)
query_string.update({u"sign": token})
req = self.factory.post("/api/test", data=query_string)
response = simpleapi(req)
self.assertEqual(response.status_code, 200)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • HTML 文本测试,使用 constants 来判断并不是个好的选择,可以用render之后的字符串对比。

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

from django.test import Client

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

带有mock的测试

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

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

coverage

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

#测试并收集测试信息
coverage run --source='.' manage.py test --setting mandela.settings_test
#查看测试结果
coverage report -m
Name Stmts Miss Cover Missing
----------------------------------------------------------------------------------------
acquireportal/__init__.py 0 0 100%
acquireportal/controler.py 65 47 28% 22-56, 60-71, 76-79
acquireportal/migrations/0001_initial.py 6 0 100%
acquireportal/migrations/0002_auto_20160622_1059.py 6 0 100%
acquireportal/migrations/0003_auto_20160622_1100.py 5 0 100%
.... ----------------------------------------------------------------------------------------
TOTAL 8013 5858 27%
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

覆盖率挺低的��

其他

测试 Exception, 被测试的代码有抛异常的情况,单元测试中需要触发这个异常来测试。

又个函数中可能会出现 queryset get 返回多个结果

from django.test import TestCase
from django.core.exceptions import MultipleObjectsReturned class ControlerTest(TestCase):
def setUp(self):
self.user = User(username='test', email='lebing.zhou@cc.com', password='asdfadf')
self.user.save() self.mac_addr = "ff:ff:ff:ff:ff:ff"
self.mac = Mac(mac=self.mac_addr, user=self.user)
self.mac.save() self.plan = BasePlan(name="包月", plan_type=1, month_price=19.9, goods=200)
self.plan.save() def test_do_action3(self):
self.mac2 = Mac(mac="ff:ff:ff:ff:ff:11", user=self.user)
self.mac2.save()
order = Order.objects.create_order(self.user, self.plan, 1, 1, "ff:ff:ff:ff:ff:fd")
with self.assertRaises(MultipleObjectsReturned):
do_action(order) #在出现这种异常的情况下,进行后面的边界测试
self.assertNotEqual(Mac.objects.get(mac=self.mac_addr).timeleft, 200)

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

  1. django单元测试

        django 单元测试小结 django 测试 从前很少写单元测试了,特别是web应用.最近不知不觉喜欢起来这个事情了,发现单元测试对于软件的模块,正交性有很大促进作用,因为函数,模块写的不合 ...

  2. [Django] 单元测试小记

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

  3. 如何进行Django单元测试

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

  4. Django 单元测试

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

  5. Django单元测试 相关知识

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

  6. Django 单元测试笔记

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

  7. Django单元测试(一)

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

  8. django 单元测试错误总结

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

  9. Django单元测试中Fixtures用法

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

随机推荐

  1. 从request获取各种路径总结

    一.获得都是当前运行文件在服务器上的绝对路径 在servlet里用: this.getServletContext().getRealPath() 在struts用: this.getServlet( ...

  2. HTML5与XML的区别

    XHTML 是 XML 风格的 HTML 4.01. HTML5 是HTML的第五大版本,取代 HTML 4.01. XHTML是基于XML发布的HTML规范,旨在规范HTML的格式. 两者提出的目的 ...

  3. iOS swift String 换行显示

    在oc中换行的方式 NSString *str = @" aaaaa \ bbbbb \ cccc \ "; swift中这种方式不可用 ,swift中换行采用新的方双三引号 &q ...

  4. vim 设置

    TL;DR: $ git clone https://github.com/sontek/dotfiles.git $ cd dotfiles $ ./install.sh vim Download  ...

  5. windows7常用操作命令

    1.打开命令行 按住Windows键加R键,打开运行窗口 2.打开笔记本 运行窗口中输入:notepad,点击确定或回车,打开记事本工具 主要作用:浏览网页时,看到一些有用的话,那么你是怎么把它记录下 ...

  6. linux下出现ping:unknown host www.baidu.com问题时的解决办法——ubuntu下局域网络的配置

    如果ping域名的时候出现ping:unknown host  xxx.xxx 但是ping IP地址的时候可以通的话 可知是dns服务器没有配置好, 查看一下配置文件/etc/resolv.conf ...

  7. CentOS安装python setuptools and pip

    安装setup-tools wget https://pypi.python.org/packages/2.7/s/setuptools/setuptools-0.6c11-py2.7.egg --n ...

  8. linux less使用方法

    less 工具也是对文件或其它输出进行分页显示的工具,应该说是linux正统查看文件内容的工具,功能极其强大.less 的用法比起 more 更加的有弹性.在 more 的时候,我们并没有办法向前面翻 ...

  9. EM算法--原理

    EM算法即期望最大化(Expection Maximization)算法,是一种最优化算法,在机器学习领域用来求解含有隐变量的模型的最大似然问题.最大似然是一种求解模型参数的方法,顾名思义,在给定一组 ...

  10. Java 反射机制[Field反射]

    Java 反射机制[Field反射] 1.  反射概念及功能 反射就是把Java类中的各种成分映射成对应的Java类.比如一个Java类中用一个Class类的对象来表示. 一个类中的组成部分分为成员变 ...