Django单元测试工具test client使用详解


Posted in Python onAugust 02, 2019

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是否相当。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python二叉搜索树与双向链表转换实现方法
Apr 29 Python
Python使用Paramiko模块编写脚本进行远程服务器操作
May 05 Python
Windows下Eclipse+PyDev配置Python+PyQt4开发环境
May 17 Python
Python实现二维数组输出为图片
Apr 03 Python
[原创]Python入门教程3. 列表基本操作【定义、运算、常用函数】
Oct 30 Python
Python3+Appium安装使用教程
Jul 05 Python
使用Python项目生成所有依赖包的清单方式
Jul 13 Python
vscode配置anaconda3的方法步骤
Aug 08 Python
Python爬取网站图片并保存的实现示例
Feb 26 Python
关于PySnooper 永远不要使用print进行调试的问题
Mar 04 Python
Python-typing: 类型标注与支持 Any类型详解
May 10 Python
Pandas搭配lambda组合使用详解
Jan 22 Python
Django使用unittest模块进行单元测试过程解析
Aug 02 #Python
pip安装python库的方法总结
Aug 02 #Python
python twilio模块实现发送手机短信功能
Aug 02 #Python
python代码 FTP备份交换机配置脚本实例解析
Aug 01 #Python
Windows系统Python直接调用C++ DLL的方法
Aug 01 #Python
Python CVXOPT模块安装及使用解析
Aug 01 #Python
Python Selenium 之数据驱动测试的实现
Aug 01 #Python
You might like
php include的妙用,实现路径加密
2008/07/29 PHP
PHP session有效期问题
2009/04/26 PHP
探讨:如何通过stats命令分析Memcached的内部状态
2013/06/14 PHP
Yii 框架控制器创建使用及控制器响应操作示例
2019/10/14 PHP
云网广告中的代码,提示出错,大家找找
2006/11/21 Javascript
Extjs4 GridPanel 的几种样式使用介绍
2013/04/18 Javascript
SuperSlide2实现图片滚动特效
2014/06/20 Javascript
JavaScript function 的 length 属性使用介绍
2014/09/15 Javascript
JavaScript函数详解
2014/11/17 Javascript
javascript实现状态栏文字首尾相接循环滚动的方法
2015/07/22 Javascript
JavaScript定义函数_动力节点Java学院整理
2017/06/27 Javascript
详解用webpack把我们的业务模块分开打包的方法
2017/07/20 Javascript
基于Jquery Ajax type的4种类型(详解)
2017/08/02 jQuery
基于vue.js的分页插件详解
2017/11/27 Javascript
Vue.js递归组件构建树形菜单
2017/12/24 Javascript
Vue的实例、生命周期与Vue脚手架(vue-cli)实例详解
2017/12/27 Javascript
Vue使用watch监听一个对象中的属性的实现方法
2019/05/10 Javascript
vue引用外部JS的两种种方法
2020/01/28 Javascript
Vue双向绑定实现原理与方法详解
2020/05/07 Javascript
JS script脚本中async和defer区别详解
2020/06/24 Javascript
Python multiprocessing.Manager介绍和实例(进程间共享数据)
2014/11/21 Python
Python实现分割文件及合并文件的方法
2015/07/10 Python
Python实现查找二叉搜索树第k大的节点功能示例
2019/01/24 Python
CSS3制作气泡对话框的实例教程
2016/05/10 HTML / CSS
基于HTML5 Canvas 实现商场监控实例详解
2017/11/20 HTML / CSS
Veronica Beard官网:在酷、经典和别致之间找到了平衡
2018/01/11 全球购物
Omio波兰:全欧洲低价大巴、火车和航班搜索和比价
2018/02/16 全球购物
Java提供了哪些企业应用编程接口
2015/02/13 面试题
出生医学证明样本
2014/01/17 职场文书
六五普法规划实施方案
2014/03/21 职场文书
基层党组织公开承诺书
2014/03/28 职场文书
揭牌仪式策划方案
2014/05/28 职场文书
员工工作能力评语
2014/12/31 职场文书
市场部岗位职责范本
2015/04/15 职场文书
2015年政治教研组工作总结
2015/07/22 职场文书
pytorch实现加载保存查看checkpoint文件
2022/07/15 Python