Django单元测试(二)------测试工具
The test client
test client是一个python类,来模拟一个简单的“哑”浏览器,允许你来测试你的view函数.你可以使用test client完成下列事情:
1.模拟"Get"和"Post"请求,观察响应结果--从HTTP(headers,status codes)到页面内容.
2.检查重定向链(如果有的话),在每一步检查URL和status code。
3.用一个包括特定值的模板context来测试一个request被Django模板渲染。
>>> from django.test.client import Client
>>> c = Client()
>>> response = c.post('/login/', {'username': 'john', 'password': 'smith'})
>>> response.status_code
200
>>> response = c.get('/customer/details/')
>>> response.content
'<!DOCTYPE html...'
使用django.test.client.Client的实例来使用test client。
注意:请求网页时,使用path而不是整个domain。
>>> c.get('/login/')
是正确的。
>>> c.get('http://www.example.com/login/')
是错误的。
test client不适合操作不是由Django建立的网站.所以,请求其它网页时,请使用python的标准库--urllib或者urllib2.
为了解析URl,test client使用由ROOT_URLCONF(settings.py)指定的URLconf。
默认情况下,test client会忽略CSRF检查,如果要强制进行CSRF检查,可以
csrf_client = Client(enforce_csrf_checks=True)
Making Requests
使用django.test.client.Client()来执行请求。
class Client(enforce_csrf_checks=False, **defaults)
可以使用关键字参数来指定默认的请求报头:
c = Client(HTTP_USER_AGENT='Mozilla/5.0')
记得在USER_AGENT前加HTTP_。
Client实例具有以下方法:
get(path, data={}, follow=False, **extra)
执行一个GET请求并返回Response对象。
>>> c = Client()
>>> c.get('/customers/details/', {'name': 'fred', 'age': 7})
相当于向以下url执行GET:
/customers/details/?name=fred&age=7
extra关键字参数可用作请求报头:
>>> c = Client()
>>> c.get('/customers/details/', {'name': 'fred', 'age': 7},
... HTTP_X_REQUESTED_WITH='XMLHttpRequest')
当然也可以将查询字符对编码后加入url:
>>> c = Client()
>>> c.get('/customers/details/?name=fred&age=7')
data参数的优先级在编码后的url之上。
如果将follow设置为True,client会追踪任何重定向,返回的response有redirect_chain属性,包括所有重定向过程中的url和状态码组成的元祖列表。
如果有个URL /redirect_me/ 重定向向 /next/, 再重定向向 /final/:
>>> response = c.get('/redirect_me/', follow=True)
>>> response.redirect_chain
[(u'http://testserver/next/', 302), (u'http://testserver/final/', 302)]
post(path, data={}, content_type=MULTIPART_CONTENT, follow=False, **extra)
执行一个POST请求并返回response对象,data参数为POST数据。
如果提供content_type参数(例如 text/xml),数据会被作为报头中Content-Type的类型进行POST上传。
如果不提供content_type参数,数据会被作为multipart/form-data类型上传。
为一个参数提交多个多个值时--比如选住<select multiple>域的多个值--这些值可以是列表或者元组.举例来说,提交choice域的三个被选中的值:
{'choices': ('a', 'b', 'd')}
上传文件:
>>> c = Client()
>>> with open('wishlist.doc') as fp:
... c.post('/customers/wishes/', {'name': 'fred', 'attachment': fp})
文件的名字'attachment'是不相关的,取决于你处理文件的代码。
如果同一个文件要post多次,注意每次post都要恢复文件的指针,最简单的方法就是将文件关闭再重新打开。
注意文件要以正确的方式被打开以便于读取,如果文件是binary data,例如读取img时,要将打开模式设为rb。
post的路径中也可以包含查询字符对:
>>> c.post('/login/?visitor=true', {'name': 'fred', 'passwd': 'secret'})
这样既会通过post上传data数据,也向GET确定visitor=True。
options(path, data='', content_type='application/octet-stream', follow=False, **extra)
做OPTIONS请求,对测试REST接口很有用。data被用作请求的主体。
put(path, data='', content_type='application/octet-stream', follow=False, **extra)
做PUT请求,测试RESTful接口。
patch(path, data='', content_type='application/octet-stream', follow=False, **extra)
做PATCH请求,测试RESTful接口。
delete(path, data='', content_type='application/octet-stream', follow=False, **extra)
做DELETE请求,测试RESTful接口。
login(**credentials)
如果使用django的用户验证系统,可用login方法进行测试。
>>> c = Client()
>>> c.login(username='fred', password='secret')
登陆成功的话,返回True。
使用之前,当然要创建一个用户。由于测试数据库使用的是单独的数据库,原先数据库中的用户是不能用于测试的。
设置密码时,不能用user的密码属性进行设置,而是用set_password()方法设置正确的哈希密码,或者使用create_user()方法创建一个带哈希密码的用户。
logout()
登出。
Testing Responses
client的get和post方法都返回response对象,和HttpResponse对象是不同的。
class Response具有以下属性:
client:the test client
content:response的主体,string类型,是view render后的页面的最终内容,或者是错误信息。
context:用来渲染模板的context实例。如果页面使用了多个模板,那context就会是Context Object列表.它们的排序方式就是它们被渲染的顺序。
>>> response = client.get('/foo/')
>>> response.context['name']
'Arthur'
request:用于请求的数据。
status_code:状态码。
templates:被用来渲染最终的content的Template实例列表.template.name可以得到template的文件名,如果template是由文件载入的话(如 'admin/index.html')。那template就会是Template列表,它们的排序方式就是它们被渲染的顺序.
response也可以当做字典来查询Http header:
response['Content-Type']
Exceptions
如果你将TestClient指向了由view函数raise的异常,那这个异常在test case里是可见的.你可以使用标准的try...except块或者assertRaises()来测试它们.对test client唯一不可见的异常是Http404,PermissionDenied和SystemExit。django会在内部捕捉这些异常并返回合适的response.这种情况下,你可以查看下你的response.status_code.
Persistent state
如果一个response返回了一个cookie,那么这个cookie就会被存储在test client里,并被其后的所有get()和post()传送.如果你想要终止这个cookie,你可以新建一个Client实例,或者手动删除它。
一个test client具有两个存储持久化状态信息的属性:
Client.cookies
一个python SimpleCookie对象,存储cilent的所有cookie。
Client.sessions
包含session信息的类字典对象。
如果要修改一个session并且存储,首先将session存储在变量中:
def test_something(self):
session = self.client.session
session['somekey'] = 'test'
session.save()
一个使用client进行测试的实例:
from django.utils import unittest
from django.test.client import Client class SimpleTest(unittest.TestCase):
def setUp(self):
# Every test needs a client.
self.client = Client() def test_details(self):
# Issue a GET request.
response = self.client.get('/customer/details/') # Check that the response is 200 OK.
self.assertEqual(response.status_code, 200) # Check that the rendered context contains 5 customers.
self.assertEqual(len(response.context['customers']), 5)
Test cases的一些功能
默认的test client
每个django.test.*TestCase的test case实例都会访问django test client,所以Client可以不用实例化,而直接用self.client访问:
from django.test import TestCase class SimpleTest(TestCase):
def test_details(self):
response = self.client.get('/customer/details/')
self.assertEqual(response.status_code, 200) def test_index(self):
response = self.client.get('/customer/index/')
self.assertEqual(response.status_code, 200)
Fixture loading
如果数据库里没有数据,那么对于一个基于数据库的网站来说,test case并无多大的用处.为了给测试数据库加入测试数据更方便,django提供了载入fixtures的方法.
fixture是一系列的数据集合,django知道如何将它导入数据库。
创建fixture最直接的方法就是使用manage.py dumpdata.当然,这假设你的实际数据库里已经有数据了.
注意:
如果你运行过manage.py syncdb命令,那么你已经使用过fixture了--只是你不知道而已。当你使用syncdb去创建数据库时,会创建一个叫initial_data的fixture。
其他名字的Fixture可以通过manage.py loaddata命令手动安装.
一旦建立了一个fixture,并将它放在了某个django app的fixtures目录中,你就可以在你的测试类里使用它了:
from django.test import TestCase
from myapp.models import Animal class AnimalTestCase(TestCase):
fixtures = ['mammals.json', 'birds'] def setUp(self):
# Test definitions as before.
call_setup_methods() def testFluffyAnimals(self):
# A test that uses the fixtures.
call_some_test_code()
这是具体发生的过程:
1. 在setup()运行前,django会清空数据库,相当于你执行了syncdb。
2.然后,所有的fixture会被安装.在例子中,django会安装任何一个名字为mammals的JSON格式的fixture和名为birds的fixture数据。
Assertions
除了python中的assertEqual()和assertTrue()外,django的TestCase还提供了几个额外的assert方法。
assertContains(response, text, count=None, status_code=200, msg_prefix='', html=False)
断言response是否与status_code和text内容相应。将html设为True会将text作为html处理。
assertJSONEqual(raw, expected_data, msg=None)
断言Json片段raw和expected_data是否相当。
Django单元测试(二)------测试工具的更多相关文章
- Django单元测试二三事
零.前言 之前做过一个微信公众平台的开发者后台,功能比较简单,我个人也比较懒,所以就没有写测试.前段时间更新了一下版本,对代码进行了改动.结果昨天收到消息说后台出问题了,一个功能无法使用.我检查了半天 ...
- 小程序入口构造工具&二维码测试工具
小程序入口构造工具&二维码测试工具 本文将介绍我们小程序中隐藏的两个工具页面.原理虽不复杂,收益却实实在在,或许也能给诸君带来启发. 入口构造工具 痛点 PM&运营 投放链接 PM&a ...
- sysbench压力测试工具简介和使用(二)
sysbench压力测试工具使用: 2.1 测试数据库服务器的硬件配置信息如下: CPU: 24核心线程数,Intel(R) Xeon(R) CPU E5-2620 0 @ 2.00G ...
- Linux系统性能测试工具(二)——内存压力测试工具memtester
本文介绍关于Linux系统(适用于centos/ubuntu等)的内存压力测试工具-memtester.内存性能测试工具包括: 内存带宽测试工具——mbw: 内存压力测试工具——memtester: ...
- linux DRM/KMS 测试工具 modetest、kmscude、igt-gpu-tools (二)
kmscube kmscube is a little demonstration program for how to drive bare metal graphics without a c ...
- yb课堂之压力测试工具Jmeter5.X 实战《二十二》
目前常用的测试工具对比 LoadRunner 性能稳定,压测结果及细粒度大,可以自定义脚本进行压力,但是太过于重大,功能比较繁多 Apache AB(单接口压测最方便) 模拟多线程并发请求,ab命令对 ...
- django单元测试
django 单元测试小结 django 测试 从前很少写单元测试了,特别是web应用.最近不知不觉喜欢起来这个事情了,发现单元测试对于软件的模块,正交性有很大促进作用,因为函数,模块写的不合 ...
- [Django] 单元测试小记
从前很少写单元测试了,特别是web应用.最近不知不觉喜欢起来这个事情了,发现单元测试对于软件的模块,正交性有很大促进作用,因为函数,模块写的不合理,单元测试写起来就麻烦的多呀.公司的项目一直都是用Dj ...
- django 单元测试小结
测试的场景 框架Django1.8 测试工具 unittest, 要记得给test设置一个独特的settings. 测试请求 也就是测试整个view部分 官方案例 其中可能会遇到登录,或者时sessi ...
随机推荐
- 如何入侵Linux操作系统
我发现了一个网站,于是常规入侵.很好,它的FINGER开着,于是我编了一个SHELL,aaa帐号试到zzz(by the way,这是我发现的一个网上规律,那就是帐号的长度与口令的强度成正比, 如果一 ...
- java多线程总结四:volatile、synchronized示例
1.synchronized保证同步 先看一个生成偶数的类 <span style="font-size:16px;">package demo.thread; /** ...
- 自定义函数实现NULL值替换
数据库环境:SQL SERVER 2005 有时候,想将查询查询数来的数据格式化一下,不希望显示NULL值,或者复制表的数据时,被插入的表不允许有NULL. 我们可以通过ISNULL()函数或者COA ...
- Passbook教程中生成pass时遇到的“Couldn't find a passTypeIdentifier in the pass”
报错如下: 2014-03-28 15:19:17.990 signpass[6358:507] Couldn't find a passTypeIdentifier in the pass 解决方案 ...
- HDOJ1005 数列
Problem Description A number sequence is defined as follows:f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) ...
- Lua脚本之语法基础快速入门
要 1.基本数据类型 2.Lua中的常用语句结构以及函数 3.Lua中的常用语句结构介绍 4.Lua中的库函数 目录[-] 一.基本数据类型 二.Lua中的常用语句结构以及函数 1.Lua中的常用语句 ...
- redis 常用操作命令
操作相关的命令连接 quit:关闭连接(connection)auth:简单密码认证 持久化 save:将数据同步保存到磁盘bgsave:将数据异步保存到磁盘lastsave:返回上次成功将数据保存到 ...
- 【转】SQL2008清除日志
USE [master] GO ALTER DATABASE DNName SET RECOVERY SIMPLE WITH NO_WAIT GO ALTER DATABASE DNName SET ...
- PHP学习笔记(5) - 选择一个合格的框架
作为一个合格的PHP开发框架,个人觉得起码需要满足以下几点. 一.上梁不正下梁歪,好的框架首先自身要有良好的编码规范和文件目录结构,代码要易于阅读理解. 二.为了可以更好地适应OOP,框架必须可以提供 ...
- PHP之图形处理
图形处理 PHP 的图形处理,主要功能集中在 PHP 的图形处理函数. 需要先掌握一些要点.什么叫图片,怎么显示图片. 所谓的图片,其实也是一种文件,只是内容不是我们肉眼直接可见的.如果我们用记事本打 ...