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中函数的参数传递
Jun 21 Python
Python中强大的命令行库click入门教程
Dec 26 Python
Python运行不显示DOS窗口的解决方法
Oct 22 Python
Python设计模式之代理模式实例详解
Jan 19 Python
Python3实现汉语转换为汉语拼音
Jul 08 Python
Python秒算24点实现及原理详解
Jul 29 Python
python psutil模块使用方法解析
Aug 01 Python
使用 Python 写一个简易的抽奖程序
Dec 08 Python
python字符串替换re.sub()实例解析
Feb 09 Python
浅析Python中字符串的intern机制
Oct 03 Python
详解pandas赋值失败问题解决
Nov 29 Python
Python使用Pygame绘制时钟
Nov 29 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
PHP5+UTF8多文件上传类
2008/10/17 PHP
PHP遍历二维数组的代码
2011/04/22 PHP
php分页代码学习示例分享
2014/02/20 PHP
从零开始学习jQuery (十一) 实战表单验证与自动完成提示插件
2011/02/23 Javascript
javascript日期转换 时间戳转日期格式
2011/11/05 Javascript
EasyUI的treegrid组件动态加载数据问题的解决办法
2011/12/11 Javascript
利用Javascript判断操作系统的类型实现不同操作系统下的兼容性
2013/01/29 Javascript
jQuery 关于伪类选择符的使用说明
2013/04/24 Javascript
KnockoutJS 3.X API 第四章之数据控制流if绑定和ifnot绑定
2016/10/10 Javascript
原生JS实现简单放大镜效果
2017/02/08 Javascript
详解有关easyUI的拖动操作中droppable,draggable用法例子
2017/06/03 Javascript
微信小程序开发(一):服务器获取数据列表渲染操作示例
2020/06/01 Javascript
jquery实现抽奖功能
2020/10/22 jQuery
vue 通过base64实现图片下载功能
2020/12/19 Vue.js
[45:59]EG vs OG 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/18 DOTA
[01:08:30]DOTA2-DPC中国联赛 正赛 Ehome vs Elephant BO3 第一场 2月28日
2021/03/11 DOTA
python测试驱动开发实例
2014/10/08 Python
Python中的is和==比较两个对象的两种方法
2017/09/06 Python
Centos 升级到python3后pip 无法使用的解决方法
2018/06/12 Python
python分批定量读取文件内容,输出到不同文件中的方法
2018/12/08 Python
使用Django搭建网站实现商品分页功能
2020/05/22 Python
pycharm实现猜数游戏
2020/12/07 Python
美国受欢迎的眼影品牌:BH Cosmetics
2016/10/25 全球购物
Martinelli官方商店:西班牙皮鞋和高跟鞋品牌
2019/07/30 全球购物
奠基仪式主持词
2014/03/20 职场文书
《孔繁森》教学反思
2014/04/17 职场文书
优秀学生评语大全
2014/04/25 职场文书
党支部综合考察材料
2014/05/19 职场文书
销售人才自我评价范文
2014/09/27 职场文书
放弃继承权公证书
2015/01/23 职场文书
银行自荐信范文
2015/03/25 职场文书
运动会广播稿20字
2015/08/19 职场文书
导游词之山海关
2019/12/10 职场文书
Python词云的正确实现方法实例
2021/05/08 Python
在pycharm中无法import所安装的库解决方案
2021/05/31 Python
设置IIS Express并发数
2022/07/07 Servers