创新互联Django4.0教程:Django4.0 测试工具-测试客户端

测试客户端是一个 Python 类,它充当虚拟 Web 浏览器,允许您测试视图并以编程方式与 Django 驱动的应用程序交互。

专注于为中小企业提供做网站、网站建设服务,电脑端+手机端+微信端的三站合一,更高效的管理,为中小企业宁强免费做网站提供优质的服务。我们立足成都,凝聚了一批互联网行业人才,有力地推动了数千家企业的稳健成长,帮助中小企业通过网站建设实现规模扩充和转变。

你可以使用测试客户端执行以下操作:

  • 模拟 URL 上的 ​GET​ 和 ​POST​请求并观察响应——从低级 HTTP(结果头和状态码)到页面内容,应有尽有。
  • 查看重定向链(如果有的话),并检查每个步骤的 URL 和状态码。
  • 测试给定的请求是否由给定的包含某些值以及模板上下文的 Django 模板渲染。

请注意,测试客户端并不是要取代 ​Selenium​ 或其他“浏览器内”框架。Django 的测试客户端有不同的侧重点。简而言之:

  • 使用 Django 的测试客户端来确定要渲染的模板正确,并且模板已传递了正确的上下文数据
  • 使用 ​Selenium ​等浏览器内框架来测试呈现的 HTML 和网页的行为,即 JavaScript 功能。 Django 还为这些框架提供了特殊支持

一个全面的测试套件应该使用这两种测试类型的组合。

概述和一个简单的例子

要使用测试客户端,请实例化 ​django.test.Client​ 并检索网页:

>>> from django.test import Client
>>> c = Client()
>>> response = c.post('/login/', {'username': 'john', 'password': 'smith'})
>>> response.status_code
200
>>> response = c.get('/customer/details/')
>>> response.content
b'

如本例所示,你可以从 Python 交互式解释器的会话中实例化 ​Client​。
请注意测试客户端如何工作的一些重要事项:

  • 测试客户端不需要运行 Web 服务器。 事实上,它会运行得很好,根本没有运行 Web 服务器! 那是因为它避免了 HTTP 的开销,直接与 Django 框架打交道。 这有助于使单元测试快速运行。
  • 检索页面时,请记住指定 URL 的 路径,而不是整个域。例如,这是正确的:
>>> c.get('/login/')

这是错误的:

>>> c.get('https://www.example.com/login/')

测试客户端无法检索不是由您的 Django 项目提供支持的网页。 如果您需要检索其他网页,请使用 Python 标准库模块,例如 ​urllib​。

  • 为了解析 URL,测试客户端使用你的 ​ROOT_URLCONF ​设置指向的任何 ​URLconf​。
  • 尽管上面的示例可以在 Python 交互式解释器中运行,但测试客户端的某些功能,尤其是与模板相关的功能,仅在测试运行时才可用。这样做的原因是 Django 的测试运行器执行了一些黑魔法,以确定给定视图加载了哪个模板。 这种黑魔法(本质上是在内存中修补 Django 的模板系统)仅在测试运行期间发生。
  • 默认情况下,测试客户端将禁用您的站点执行的任何 CSRF 检查。如果出于某种原因,您希望测试客户端执行 CSRF 检查,您可以创建一个强制执行 CSRF 检查的测试客户端实例。 为此,请在构建客户端时传入 ​enforce_csrf_checks ​参数:
>>> from django.test import Client
>>> csrf_client = Client(enforce_csrf_checks=True)

发出请求

使用 ​django.test.Client​ 类发出请求。

class Client(enforce_csrf_checks=False, json_encoder=DjangoJSONEncoder, **defaults)

它在构造时不需要任何参数。然而,你可以使用关键字参数来指定一些默认头信息。例如,这将在每个请求中发送一个 ​User-Agent​ HTTP 头:

>>> c = Client(HTTP_USER_AGENT='Mozilla/5.0')

传递给 ​get()​、​post()​ 等方法的 ​extra​ 关键字参数的值,优先于传递给类构造函数的默认值。
enforce_csrf_checks​参数可用于测试 CSRF 保护。
json_encoder​参数允许为 ​post()​ 中描述的 JSON 序列化设置一个自定义 JSON 编码器。
raise_request_exception​参数允许控制是否在请求过程中引出的异常也应该在测试中引出。默认值为 ​True​。
一旦有了 Client 实例,就可以调用以下任何一种方法:

get(path, data=None, follow=False, secure=False, **extra)

对提供的 ​path​上发出 ​GET​请求,并返回一个 ​Response​对象,如下所述。
data​字典中的键值对用于创建 ​GET​数据有效载荷。例如:

>>> c = Client()
>>> c.get('/customers/details/', {'name': 'fred', 'age': 7})

产生等效的 GET 请求:

/customers/details/?name=fred&age=7

extra​关键词参数可以用来指定请求中要发送的头信息。例如:

>>> c = Client()
>>> c.get('/customers/details/', {'name': 'fred', 'age': 7},
...       HTTP_ACCEPT='application/json')

将 HTTP 头 ​HTTP_ACCEPT​发送到 ​detail​视图,这是测试使用 ​django.http.HttpRequest.accepts()​ 方法的代码路径的好方法。

如果你已经有了 URL 编码形式的 ​GET​参数,你可以使用该编码代替使用数据参数。例如,之前的 ​GET​请求也可以改成:

>>> c = Client()
>>> c.get('/customers/details/?name=fred&age=7')

如果你提供的 URL 同时包含编码的 ​GET​数据和数据参数,数据参数将优先。
如果将 ​follow​设置为 ​True​,客户端将遵循所有重定向,并且将在响应对象中设置 ​redirect_chain​属性,该属性是包含中间 URL 和状态码的元组。
如果你有一个 URL ​/redirect_me/​,重定向到​ /next/​,再重定向到 ​/final/​,这是你会看到的:

>>> response = c.get('/redirect_me/', follow=True)
>>> response.redirect_chain
[('http://testserver/next/', 302), ('http://testserver/final/', 302)]

如果你把 ​secure​设置为 ​True​,则客户端将模拟 HTTPS 请求。

post(path, data=None, content_type=MULTIPART_CONTENT, follow=False, secure=False, **extra)

在提供的 ​path​上发出一个 ​POST​请求,并返回一个 ​Response​对象,如下所述。
data​字典中的键值对用于提交 ​POST​数据。例如:

>>> c = Client()
>>> c.post('/login/', {'name': 'fred', 'passwd': 'secret'})

这将产生对这个 URL 的 ​POST​请求:

/login/

且具有此 ​POST​数据:

name=fred&passwd=secret

如果你提供 ​application/json​ 为 ​content_type​,则如果 ​data​是一个字典、列表或元组时,使用 ​json.dumps()​ 进行序列化。序列化默认是通过 ​DjangoJSONEncoder​,可以通过为 Client 提供 ​json_encoder​参数覆盖。这个序列化也会发生在 ​put()​、​patch()​ 和 ​delete()​ 请求中。
如果你要提供任何其他的 ​content_type​(例如 ​text/xml​ 用于 XML 有效载荷),使用HTTP ​Content-Type​ 头中的 ​content_type​,​data​的内容在 ​POST​请求中按原样发送。
如果你没有为 ​content_type​提供一个值,data 中的值将以 ​multipart/form-data​ 的内容类型进行传输。在这种情况下,data 中的键值对将被编码为多部分消息,并用于创建 ​POST​数据有效载荷。
要为一个给定的键提交多个值——例如,要指定 ​