Django单元测试工具test client使用详解
Thetestclient
testclient是一个python类,来模拟一个简单的“哑”浏览器,允许你来测试你的view函数.你可以使用testclient完成下列事情:
1.模拟"Get"和"Post"请求,观察响应结果--从HTTP(headers,statuscodes)到页面内容.
2.检查重定向链(如果有的话),在每一步检查URL和statuscode。
3.用一个包括特定值的模板context来测试一个request被Django模板渲染。
>>>fromdjango.test.clientimportClient >>>c=Client() >>>response=c.post('/login/',{'username':'john','password':'smith'}) >>>response.status_code 200 >>>response=c.get('/customer/details/') >>>response.content '使用django.test.client.Client的实例来使用testclient。
注意:请求网页时,使用path而不是整个domain。
>>>c.get('/login/')是正确的。
>>>c.get('http://www.example.com/login/')是错误的。
testclient不适合操作不是由Django建立的网站.所以,请求其它网页时,请使用python的标准库--urllib或者urllib2.
为了解析URl,testclient使用由ROOT_URLCONF(settings.py)指定的URLconf。
默认情况下,testclient会忽略CSRF检查,如果要强制进行CSRF检查,可以
csrf_client=Client(enforce_csrf_checks=True)MakingRequests
使用django.test.client.Client()来执行请求。
classClient(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=7extra关键字参数可用作请求报头:
>>>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类型上传。
为一个参数提交多个多个值时--比如选住
域的多个值--这些值可以是列表或者元组.举例来说,提交choice域的三个被选中的值: {'choices':('a','b','d')}上传文件:
>>>c=Client() >>>withopen('wishlist.doc')asfp: ...c.post('/customers/wishes/',{'name':'fred','attachment':fp})文件的名字'attachment'是不相关的,取决于你处理文件的代码。
如果同一个文件要post多次,注意每次post都要恢复文件的指针,最简单的方法就是将文件关闭再重新打开。
注意文件要以正确的方式被打开以便于读取,如果文件是binarydata,例如读取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()
登出。
TestingResponses
client的get和post方法都返回response对象,和HttpResponse对象是不同的。
classResponse具有以下属性:
client:thetestclient
content:response的主体,string类型,是viewrender后的页面的最终内容,或者是错误信息。
context:用来渲染模板的context实例。如果页面使用了多个模板,那context就会是ContextObject列表.它们的排序方式就是它们被渲染的顺序。
>>>response=client.get('/foo/') >>>response.context['name'] 'Arthur'request:用于请求的数据。
status_code:状态码。
templates:被用来渲染最终的content的Template实例列表.template.name可以得到template的文件名,如果template是由文件载入的话(如'admin/index.html')。那template就会是Template列表,它们的排序方式就是它们被渲染的顺序.
response也可以当做字典来查询Httpheader:
response['Content-Type']Exceptions
如果你将TestClient指向了由view函数raise的异常,那这个异常在testcase里是可见的.你可以使用标准的try...except块或者assertRaises()来测试它们.对testclient唯一不可见的异常是Http404,PermissionDenied和SystemExit。django会在内部捕捉这些异常并返回合适的response.这种情况下,你可以查看下你的response.status_code.
Persistentstate
如果一个response返回了一个cookie,那么这个cookie就会被存储在testclient里,并被其后的所有get()和post()传送.如果你想要终止这个cookie,你可以新建一个Client实例,或者手动删除它。
一个testclient具有两个存储持久化状态信息的属性:
Client.cookies
一个pythonSimpleCookie对象,存储cilent的所有cookie。
Client.sessions
包含session信息的类字典对象。
如果要修改一个session并且存储,首先将session存储在变量中:
deftest_something(self): session=self.client.session session['somekey']='test' session.save()一个使用client进行测试的实例:
fromdjango.utilsimportunittest fromdjango.test.clientimportClient classSimpleTest(unittest.TestCase): defsetUp(self): #Everytestneedsaclient. self.client=Client() deftest_details(self): #IssueaGETrequest. response=self.client.get('/customer/details/') #Checkthattheresponseis200OK. self.assertEqual(response.status_code,200) #Checkthattherenderedcontextcontains5customers. self.assertEqual(len(response.context['customers']),5)Testcases的一些功能
默认的testclient
每个django.test.*TestCase的testcase实例都会访问djangotestclient,所以Client可以不用实例化,而直接用self.client访问:
fromdjango.testimportTestCase classSimpleTest(TestCase): deftest_details(self): response=self.client.get('/customer/details/') self.assertEqual(response.status_code,200) deftest_index(self): response=self.client.get('/customer/index/') self.assertEqual(response.status_code,200)Fixtureloading
如果数据库里没有数据,那么对于一个基于数据库的网站来说,testcase并无多大的用处.为了给测试数据库加入测试数据更方便,django提供了载入fixtures的方法.
fixture是一系列的数据集合,django知道如何将它导入数据库。
创建fixture最直接的方法就是使用manage.pydumpdata.当然,这假设你的实际数据库里已经有数据了.
注意:
如果你运行过manage.pysyncdb命令,那么你已经使用过fixture了--只是你不知道而已。当你使用syncdb去创建数据库时,会创建一个叫initial_data的fixture。
其他名字的Fixture可以通过manage.pyloaddata命令手动安装.
一旦建立了一个fixture,并将它放在了某个djangoapp的fixtures目录中,你就可以在你的测试类里使用它了:
fromdjango.testimportTestCase frommyapp.modelsimportAnimal classAnimalTestCase(TestCase): fixtures=['mammals.json','birds'] defsetUp(self): #Testdefinitionsasbefore. call_setup_methods() deftestFluffyAnimals(self): #Atestthatusesthefixtures. 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是否相当。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。