{"title":"测试工具","version":"5.2","locale":"zh-hans","docname":"topics/testing/tools","url":"/zh-hans/5.2/topics/testing/tools/","canonical":"https://djangodocs.dev/zh-hans/5.2/topics/testing/tools/","summary":"Django 提供了一小组在编写测试时会派上用场的工具。 测试客户端 Link to this heading # 测试客户端是一个 Python 类，它充当虚拟的网络浏览器，允许你以编程方式测试你的视图并与你的基于 Django 的应用程序进行交互。 你可以使用测试客户端执行以下操作： 模拟 URL 上的 GET 和…","html":"<h1>测试工具<a class=\"heading-anchor\" href=\"#testing-tools\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>Django 提供了一小组在编写测试时会派上用场的工具。</p>\n<section id=\"the-test-client\">\n<span id=\"test-client\"></span><h2>测试客户端<a class=\"heading-anchor\" href=\"#the-test-client\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>测试客户端是一个 Python 类，它充当虚拟的网络浏览器，允许你以编程方式测试你的视图并与你的基于 Django 的应用程序进行交互。</p>\n<p>你可以使用测试客户端执行以下操作：</p>\n<ul class=\"simple\">\n<li><p>模拟 URL 上的 GET 和 POST 请求并观察响应——从低级 HTTP（结果头和状态码）到页面内容，应有尽有。</p></li>\n<li><p>查看重定向链（如果有的话），并检查每个步骤的 URL 和状态码。</p></li>\n<li><p>测试给定的请求是否由给定的包含某些值以及模板上下文的 Django 模板渲染。</p></li>\n</ul>\n<p>请注意，测试客户端并不是要取代 <a class=\"reference external\" href=\"https://www.selenium.dev/\">Selenium</a> 或其他“浏览器内”框架。Django 的测试客户端有不同的侧重点。简而言之：</p>\n<ul class=\"simple\">\n<li><p>使用 Django 的测试客户端来确定要渲染的模板正确，并且模板已传递了正确的上下文数据。</p></li>\n<li><p>使用 <a class=\"reference internal\" href=\"/zh-hans/5.2/topics/testing/advanced/#django.test.RequestFactory\" title=\"django.test.RequestFactory\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">RequestFactory</span></code></a> 直接测试视图函数，绕过路由和中间件层。</p></li>\n<li><p>使用像 <a class=\"reference external\" href=\"https://www.selenium.dev/\">Selenium</a> 这样的浏览器框架来测试 <em>渲染的</em> HTML 和网页的 <em>行为</em>，即 JavaScript 功能。Django 还为这些框架提供了特殊的支持；请参阅 <a class=\"reference internal\" href=\"#django.test.LiveServerTestCase\" title=\"django.test.LiveServerTestCase\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">LiveServerTestCase</span></code></a> 部分以获取更多详细信息。</p></li>\n</ul>\n<p>一个全面的测试套件应该使用所有这些测试类型的组合。</p>\n<section id=\"overview-and-a-quick-example\">\n<h3>概述和一个简单的例子<a class=\"heading-anchor\" href=\"#overview-and-a-quick-example\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>要使用测试客户端，请实例化 <code class=\"docutils literal notranslate\"><span class=\"pre\">django.test.Client</span></code> 并获取 web 页面：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.test</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Client</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">c</span> <span class=\"o\">=</span> <span class=\"n\">Client</span><span class=\"p\">()</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"n\">c</span><span class=\"o\">.</span><span class=\"n\">post</span><span class=\"p\">(</span><span class=\"s2\">&quot;/login/&quot;</span><span class=\"p\">,</span> <span class=\"p\">{</span><span class=\"s2\">&quot;username&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;john&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;password&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;smith&quot;</span><span class=\"p\">})</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">status_code</span>\n<span class=\"go\">200</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"n\">c</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s2\">&quot;/customer/details/&quot;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">content</span>\n<span class=\"go\">b&#39;&lt;!DOCTYPE html...&#39;</span>\n</code></pre></div>\n<p>如本例所示，你可以从 Python 交互式解释器的会话中实例化 <code class=\"docutils literal notranslate\"><span class=\"pre\">Client</span></code>。</p>\n<p>请注意测试客户端如何工作的一些重要事项：</p>\n<ul>\n<li><p>测试客户端 <em>不需要</em> web 服务器正在运行。事实上，它甚至可以在没有任何 web 服务器运行的情况下正常工作！这是因为它避免了 HTTP 的开销，直接与 Django 框架交互。这有助于快速运行单元测试。</p></li>\n<li><p>在检索页面时，请记住指定 URL 的 <em>路径</em>，而不是整个域名。例如，这是正确的：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">c</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s2\">&quot;/login/&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>这是不正确的：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">c</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s2\">&quot;https://www.example.com/login/&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>测试客户端无法获取不由你的 Django 项目提供支持的网页。如果你需要获取其他网页，使用 Python 标准库模块如 <a class=\"reference external\" href=\"https://docs.python.org/3/library/urllib.html#module-urllib\" title=\"(in Python v3.14)\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">urllib</span></code></a>。</p>\n</li>\n<li><p>为了解析 URL，测试客户端使用你的 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/settings/#std-setting-ROOT_URLCONF\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">ROOT_URLCONF</span></code></a> 配置指向的任何 URLconf。</p></li>\n<li><p>虽然上面的例子可以在 Python 交互式解释器中工作，但是测试客户端的一些功能，尤其是与模板相关的功能，只有在 <em>测试运行时</em> 才可以使用。</p>\n<p>原因是 Django 的测试运行器为了确定哪个模板被给定的视图加载，执行了一点黑魔法。这个黑魔法（本质上是内存中 Django 模板系统的补丁）只发生在测试运行期间。</p>\n</li>\n<li><p>默认情况下，测试客户端将禁用站点执行的任何 CSRF 检查。</p>\n<p>如果出于某种原因，你 <em>想要</em> 测试客户端执行 CSRF 检查，你可以创建一个强制执行 CSRF 检查的测试客户端实例。要做到这一点，构建客户端时传入 <code class=\"docutils literal notranslate\"><span class=\"pre\">enforce_csrf_checks</span></code> 参数：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.test</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Client</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">csrf_client</span> <span class=\"o\">=</span> <span class=\"n\">Client</span><span class=\"p\">(</span><span class=\"n\">enforce_csrf_checks</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n</code></pre></div>\n</li>\n</ul>\n</section>\n<section id=\"making-requests\">\n<h3>发出请求<a class=\"heading-anchor\" href=\"#making-requests\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">django.test.Client</span></code> 类发出请求。</p>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.test.Client\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">Client</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">enforce_csrf_checks</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">False</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">raise_request_exception</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">True</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">json_encoder</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">DjangoJSONEncoder</span></span></em>, <em class=\"sig-param\"><span class=\"keyword-only-separator o\"><abbr title=\"Keyword-only parameters separator (PEP 3102)\"><span class=\"pre\">*</span></abbr></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">headers</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">query_params</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">defaults</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.Client\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>一个用于测试的 HTTP 客户端。接受多个参数，可以自定义其行为。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">headers</span></code> 允许你指定默认头信息，这些头信息将与每个请求一起发送。例如，要设置一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">User-Agent</span></code> 头信息：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">client</span> <span class=\"o\">=</span> <span class=\"n\">Client</span><span class=\"p\">(</span><span class=\"n\">headers</span><span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s2\">&quot;user-agent&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;curl/7.79.1&quot;</span><span class=\"p\">})</span>\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">query_params</span></code> 允许你指定将在每个请求上设置的默认查询字符串。</p>\n<p>在 <code class=\"docutils literal notranslate\"><span class=\"pre\">**defaults</span></code> 中的任意关键字参数设置了 WSGI <span class=\"target\" id=\"index-10\"></span><a class=\"pep reference external\" href=\"https://peps.python.org/pep-3333/#environ-variables\"><strong>environ 变量</strong></a>。例如，要设置脚本名称：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">client</span> <span class=\"o\">=</span> <span class=\"n\">Client</span><span class=\"p\">(</span><span class=\"n\">SCRIPT_NAME</span><span class=\"o\">=</span><span class=\"s2\">&quot;/app/&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>以 <code class=\"docutils literal notranslate\"><span class=\"pre\">HTTP_</span></code> 前缀开头的关键字参数将被设置为头信息，但为了可读性，应该优先使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">headers</span></code> 参数。</p>\n</aside>\n<p>传递给 <a class=\"reference internal\" href=\"#django.test.Client.get\" title=\"django.test.Client.get\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get()</span></code></a>、<a class=\"reference internal\" href=\"#django.test.Client.post\" title=\"django.test.Client.post\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">post()</span></code></a> 等的 <code class=\"docutils literal notranslate\"><span class=\"pre\">headers</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">query_params</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">extra</span></code> 关键字参数的值优先于传递给类构造函数的默认值。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">enforce_csrf_checks</span></code> 参数可用于测试 CSRF 保护（见上文）。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">raise_request_exception</span></code> 参数允许控制是否在请求过程中引出的异常也应该在测试中引出。默认值为 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">json_encoder</span></code> 参数允许为 <a class=\"reference internal\" href=\"#django.test.Client.post\" title=\"django.test.Client.post\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">post()</span></code></a> 中描述的 JSON 序列化设置一个自定义 JSON 编码器。</p>\n<aside class=\"version-note version-changed\" data-version=\"5.1\">\n<p class=\"version-note-title\">Changed in Django 5.1</p><p>增加了 <code class=\"docutils literal notranslate\"><span class=\"pre\">query_params</span></code> 参数。</p>\n</aside>\n<p>一旦有了 <code class=\"docutils literal notranslate\"><span class=\"pre\">Client</span></code> 实例，就可以调用以下任何一种方法：</p>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.Client.get\">\n<span class=\"sig-name descname\"><span class=\"pre\">get</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">path</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">data</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">follow</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">False</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">secure</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">False</span></span></em>, <em class=\"sig-param\"><span class=\"keyword-only-separator o\"><abbr title=\"Keyword-only parameters separator (PEP 3102)\"><span class=\"pre\">*</span></abbr></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">headers</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">query_params</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">extra</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.Client.get\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>对提供的 <code class=\"docutils literal notranslate\"><span class=\"pre\">path</span></code> 上发出 GET 请求，并返回一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">Response</span></code> 对象，如下所述。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">query_params</span></code> 字典中的键值对用于设置查询字符串。例如：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">c</span> <span class=\"o\">=</span> <span class=\"n\">Client</span><span class=\"p\">()</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">c</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s2\">&quot;/customers/details/&quot;</span><span class=\"p\">,</span> <span class=\"n\">query_params</span><span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;fred&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;age&quot;</span><span class=\"p\">:</span> <span class=\"mi\">7</span><span class=\"p\">})</span>\n</code></pre></div>\n<p>...将导致等同于以下 GET 请求的评估：</p>\n<div class=\"code-block\" data-language=\"text\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Text</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Text code\"><code>/customers/details/?name=fred&amp;age=7\n</code></pre></div>\n<p>也可以将这些参数传递给 <code class=\"docutils literal notranslate\"><span class=\"pre\">data</span></code> 参数。但是，<code class=\"docutils literal notranslate\"><span class=\"pre\">query_params</span></code> 是首选，因为它适用于任何 HTTP 方法。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">headers</span></code> 参数可用于指定要在请求中发送的头信息。例如：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">c</span> <span class=\"o\">=</span> <span class=\"n\">Client</span><span class=\"p\">()</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">c</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span>\n<span class=\"gp\">... </span>    <span class=\"s2\">&quot;/customers/details/&quot;</span><span class=\"p\">,</span>\n<span class=\"gp\">... </span>    <span class=\"n\">query_params</span><span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;fred&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;age&quot;</span><span class=\"p\">:</span> <span class=\"mi\">7</span><span class=\"p\">},</span>\n<span class=\"gp\">... </span>    <span class=\"n\">headers</span><span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s2\">&quot;accept&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;application/json&quot;</span><span class=\"p\">},</span>\n<span class=\"gp\">... </span><span class=\"p\">)</span>\n</code></pre></div>\n<p>......会将 HTTP 头 <code class=\"docutils literal notranslate\"><span class=\"pre\">HTTP_ACCEPT</span></code> 发送到 detail 视图，这是测试使用 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/request-response/#django.http.HttpRequest.accepts\" title=\"django.http.HttpRequest.accepts\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">django.http.HttpRequest.accepts()</span></code></a> 方法的代码路径的好方法。</p>\n<p>任意关键字参数设置了 WSGI <span class=\"target\" id=\"index-11\"></span><a class=\"pep reference external\" href=\"https://peps.python.org/pep-3333/#environ-variables\"><strong>environ 变量</strong></a>。例如，设置脚本名称的头信息：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">c</span> <span class=\"o\">=</span> <span class=\"n\">Client</span><span class=\"p\">()</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">c</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s2\">&quot;/&quot;</span><span class=\"p\">,</span> <span class=\"n\">SCRIPT_NAME</span><span class=\"o\">=</span><span class=\"s2\">&quot;/app/&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>如果你已经有了 URL 编码形式的 GET 参数，你可以使用该编码而不是使用 data 参数。例如，之前的 GET 请求也可以这样表示：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">c</span> <span class=\"o\">=</span> <span class=\"n\">Client</span><span class=\"p\">()</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">c</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s2\">&quot;/customers/details/?name=fred&amp;age=7&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>如果你提供的 URL 同时包含编码的 GET 数据和 <code class=\"docutils literal notranslate\"><span class=\"pre\">query_params</span></code> 或 <code class=\"docutils literal notranslate\"><span class=\"pre\">data</span></code> 参数，这些参数将优先。</p>\n<p>如果将 <code class=\"docutils literal notranslate\"><span class=\"pre\">follow</span></code> 设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>，客户端将遵循所有重定向，并且将在响应对象中设置 <code class=\"docutils literal notranslate\"><span class=\"pre\">redirect_chain</span></code> 属性，该属性是包含中间 URL 和状态码的元组。</p>\n<p>如果你有一个 URL <code class=\"docutils literal notranslate\"><span class=\"pre\">/redirect_me/</span></code>，它重定向到 <code class=\"docutils literal notranslate\"><span class=\"pre\">/next/</span></code>，然后重定向到 <code class=\"docutils literal notranslate\"><span class=\"pre\">/final/</span></code>，你会看到以下内容：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"n\">c</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s2\">&quot;/redirect_me/&quot;</span><span class=\"p\">,</span> <span class=\"n\">follow</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">redirect_chain</span>\n<span class=\"go\">[(&#39;http://testserver/next/&#39;, 302), (&#39;http://testserver/final/&#39;, 302)]</span>\n</code></pre></div>\n<p>如果你把 <code class=\"docutils literal notranslate\"><span class=\"pre\">secure</span></code> 设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>，则客户端将模拟 HTTPS 请求。</p>\n<aside class=\"version-note version-changed\" data-version=\"5.1\">\n<p class=\"version-note-title\">Changed in Django 5.1</p><p>增加了 <code class=\"docutils literal notranslate\"><span class=\"pre\">query_params</span></code> 参数。</p>\n</aside>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.Client.post\">\n<span class=\"sig-name descname\"><span class=\"pre\">post</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">path</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">data</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">content_type</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">MULTIPART_CONTENT</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">follow</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">False</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">secure</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">False</span></span></em>, <em class=\"sig-param\"><span class=\"keyword-only-separator o\"><abbr title=\"Keyword-only parameters separator (PEP 3102)\"><span class=\"pre\">*</span></abbr></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">headers</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">query_params</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">extra</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.Client.post\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>在提供的 <code class=\"docutils literal notranslate\"><span class=\"pre\">path</span></code> 上发出一个 POST 请求，并返回一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">Response</span></code> 对象，如下所述。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">data</span></code> 字典中的键值对用于提交 POST 数据。例如：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">c</span> <span class=\"o\">=</span> <span class=\"n\">Client</span><span class=\"p\">()</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">c</span><span class=\"o\">.</span><span class=\"n\">post</span><span class=\"p\">(</span><span class=\"s2\">&quot;/login/&quot;</span><span class=\"p\">,</span> <span class=\"p\">{</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;fred&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;passwd&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;secret&quot;</span><span class=\"p\">})</span>\n</code></pre></div>\n<p>...将导致对该 URL 发起 POST 请求的评估：</p>\n<div class=\"code-block\" data-language=\"text\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Text</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Text code\"><code>/login/\n</code></pre></div>\n<p>...使用以下 POST 数据：</p>\n<div class=\"code-block\" data-language=\"text\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Text</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Text code\"><code>name=fred&amp;passwd=secret\n</code></pre></div>\n<p>如果你提供 <em class=\"mimetype\">application/json</em> 为 <code class=\"docutils literal notranslate\"><span class=\"pre\">content_type</span></code>，则如果 <code class=\"docutils literal notranslate\"><span class=\"pre\">data</span></code> 是一个字典、列表或元组时，使用 <a class=\"reference external\" href=\"https://docs.python.org/3/library/json.html#json.dumps\" title=\"(in Python v3.14)\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">json.dumps()</span></code></a> 进行序列化。序列化默认是通过 <a class=\"reference internal\" href=\"/zh-hans/5.2/topics/serialization/#django.core.serializers.json.DjangoJSONEncoder\" title=\"django.core.serializers.json.DjangoJSONEncoder\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DjangoJSONEncoder</span></code></a>，可以通过为 <a class=\"reference internal\" href=\"#django.test.Client\" title=\"django.test.Client\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Client</span></code></a> 提供 <code class=\"docutils literal notranslate\"><span class=\"pre\">json_encoder</span></code> 参数覆盖。这个序列化也会发生在 <a class=\"reference internal\" href=\"#django.test.Client.put\" title=\"django.test.Client.put\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">put()</span></code></a>、<a class=\"reference internal\" href=\"#django.test.Client.patch\" title=\"django.test.Client.patch\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">patch()</span></code></a> 和 <a class=\"reference internal\" href=\"#django.test.Client.delete\" title=\"django.test.Client.delete\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">delete()</span></code></a> 请求中。</p>\n<p>如果你要提供任何其他的 <code class=\"docutils literal notranslate\"><span class=\"pre\">content_type</span></code> （例如 <em class=\"mimetype\">text/xml</em> 用于 XML 有效载荷），使用HTTP <code class=\"docutils literal notranslate\"><span class=\"pre\">Content-Type</span></code> 头中的 <code class=\"docutils literal notranslate\"><span class=\"pre\">content_type</span></code>，<code class=\"docutils literal notranslate\"><span class=\"pre\">data</span></code> 的内容在 POST 请求中按原样发送。</p>\n<p>如果你没有为 <code class=\"docutils literal notranslate\"><span class=\"pre\">content_type</span></code> 提供一个值，<code class=\"docutils literal notranslate\"><span class=\"pre\">data</span></code> 中的值将以 <em class=\"mimetype\">multipart/form-data</em> 的内容类型进行传输。在这种情况下，<code class=\"docutils literal notranslate\"><span class=\"pre\">data</span></code> 中的键值对将被编码为多部分消息，并用于创建 POST 数据有效载荷。</p>\n<p>要为一个给定的键提交多个值——例如，要指定 <code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;select</span> <span class=\"pre\">multiple&gt;</span></code> 的选择——为所需键提供一个列表或元组的值。例如，这个 <code class=\"docutils literal notranslate\"><span class=\"pre\">data</span></code> 的值将为名为 <code class=\"docutils literal notranslate\"><span class=\"pre\">choices</span></code> 的字段提交三个选择值：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"p\">{</span><span class=\"s2\">&quot;choices&quot;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s2\">&quot;a&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;b&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;d&quot;</span><span class=\"p\">]}</span>\n</code></pre></div>\n<p>提交文件是一个特殊情况。要提交文件，你只需提供文件字段名称作为键，以及要上传的文件的文件句柄作为值。例如，如果你的表单有字段 <code class=\"docutils literal notranslate\"><span class=\"pre\">name</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">attachment</span></code>，后者是一个 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/forms/fields/#django.forms.FileField\" title=\"django.forms.FileField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">FileField</span></code></a>：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">c</span> <span class=\"o\">=</span> <span class=\"n\">Client</span><span class=\"p\">()</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"k\">with</span> <span class=\"nb\">open</span><span class=\"p\">(</span><span class=\"s2\">&quot;wishlist.doc&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;rb&quot;</span><span class=\"p\">)</span> <span class=\"k\">as</span> <span class=\"n\">fp</span><span class=\"p\">:</span>\n<span class=\"gp\">... </span>    <span class=\"n\">c</span><span class=\"o\">.</span><span class=\"n\">post</span><span class=\"p\">(</span><span class=\"s2\">&quot;/customers/wishes/&quot;</span><span class=\"p\">,</span> <span class=\"p\">{</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;fred&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;attachment&quot;</span><span class=\"p\">:</span> <span class=\"n\">fp</span><span class=\"p\">})</span>\n<span class=\"gp\">...</span>\n</code></pre></div>\n<p>你也可以提供任何类似文件的对象（例如：<a class=\"reference external\" href=\"https://docs.python.org/3/library/io.html#io.StringIO\" title=\"(in Python v3.14)\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">StringIO</span></code></a> 或 <a class=\"reference external\" href=\"https://docs.python.org/3/library/io.html#io.BytesIO\" title=\"(in Python v3.14)\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">BytesIO</span></code></a>）作为文件句柄。如果你要上传到一个 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/models/fields/#django.db.models.ImageField\" title=\"django.db.models.ImageField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ImageField</span></code></a>，这个对象需要一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">name</span></code> 属性，以通过 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/validators/#django.core.validators.validate_image_file_extension\" title=\"django.core.validators.validate_image_file_extension\"><code class=\"xref py py-data docutils literal notranslate\"><span class=\"pre\">validate_image_file_extension</span></code></a> 验证器。例如：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">io</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">BytesIO</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">img</span> <span class=\"o\">=</span> <span class=\"n\">BytesIO</span><span class=\"p\">(</span>\n<span class=\"gp\">... </span>    <span class=\"sa\">b</span><span class=\"s2\">&quot;GIF89a</span><span class=\"se\">\\x01\\x00\\x01\\x00\\x00\\x00\\x00</span><span class=\"s2\">!</span><span class=\"se\">\\xf9\\x04\\x01\\x00\\x00\\x00</span><span class=\"s2\">&quot;</span>\n<span class=\"gp\">... </span>    <span class=\"sa\">b</span><span class=\"s2\">&quot;</span><span class=\"se\">\\x00</span><span class=\"s2\">,</span><span class=\"se\">\\x00\\x00\\x00\\x00\\x01\\x00\\x01\\x00\\x00\\x02\\x01\\x00\\x00</span><span class=\"s2\">&quot;</span>\n<span class=\"gp\">... </span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">img</span><span class=\"o\">.</span><span class=\"n\">name</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;myimage.gif&quot;</span>\n</code></pre></div>\n<p>请注意，如果你想在多次调用 <code class=\"docutils literal notranslate\"><span class=\"pre\">post()</span></code> 时使用同一个文件句柄，那么你需要在两次调用之间手动重置文件指针。最简单的方法是在向 <code class=\"docutils literal notranslate\"><span class=\"pre\">post()</span></code> 提供文件后手动关闭文件，如上所示。</p>\n<p>你还应确保文件的打开方式允许数据被读取。如果你的文件包含二进制数据，如图像，这意味着你需要以 <code class=\"docutils literal notranslate\"><span class=\"pre\">rb</span></code> （读取二进制）模式打开文件。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">headers</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">query_params</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">extra</span></code> 参数的作用与 <a class=\"reference internal\" href=\"#django.test.Client.get\" title=\"django.test.Client.get\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">Client.get()</span></code></a> 相同。</p>\n<p>如果你使用 POST 请求的 URL 包含编码的参数，这些参数将在 request.GET 数据中可用。例如，如果你发出请求：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">c</span><span class=\"o\">.</span><span class=\"n\">post</span><span class=\"p\">(</span>\n<span class=\"gp\">... </span>    <span class=\"s2\">&quot;/login/&quot;</span><span class=\"p\">,</span> <span class=\"p\">{</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;fred&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;passwd&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;secret&quot;</span><span class=\"p\">},</span> <span class=\"n\">query_params</span><span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s2\">&quot;visitor&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;true&quot;</span><span class=\"p\">}</span>\n<span class=\"gp\">... </span><span class=\"p\">)</span>\n</code></pre></div>\n<p>......处理这个请求的视图可以询问 request.POST 来检索用户名和密码，也可以询问 request.GET 来确定该用户是否是访客。</p>\n<p>如果将 <code class=\"docutils literal notranslate\"><span class=\"pre\">follow</span></code> 设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>，客户端将遵循所有重定向，并且将在响应对象中设置 <code class=\"docutils literal notranslate\"><span class=\"pre\">redirect_chain</span></code> 属性，该属性是包含中间 URL 和状态码的元组。</p>\n<p>如果你把 <code class=\"docutils literal notranslate\"><span class=\"pre\">secure</span></code> 设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>，则客户端将模拟 HTTPS 请求。</p>\n<aside class=\"version-note version-changed\" data-version=\"5.1\">\n<p class=\"version-note-title\">Changed in Django 5.1</p><p>增加了 <code class=\"docutils literal notranslate\"><span class=\"pre\">query_params</span></code> 参数。</p>\n</aside>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.Client.head\">\n<span class=\"sig-name descname\"><span class=\"pre\">head</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">path</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">data</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">follow</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">False</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">secure</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">False</span></span></em>, <em class=\"sig-param\"><span class=\"keyword-only-separator o\"><abbr title=\"Keyword-only parameters separator (PEP 3102)\"><span class=\"pre\">*</span></abbr></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">headers</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">query_params</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">extra</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.Client.head\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>对提供的 <code class=\"docutils literal notranslate\"><span class=\"pre\">path</span></code> 发出 HEAD 请求并返回一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">Response</span></code> 对象。此方法与 <a class=\"reference internal\" href=\"#django.test.Client.get\" title=\"django.test.Client.get\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">Client.get()</span></code></a> 类似，包括 <code class=\"docutils literal notranslate\"><span class=\"pre\">follow</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">secure</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">headers</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">query_params</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">extra</span></code> 参数，只是它不返回消息正文。</p>\n<aside class=\"version-note version-changed\" data-version=\"5.1\">\n<p class=\"version-note-title\">Changed in Django 5.1</p><p>增加了 <code class=\"docutils literal notranslate\"><span class=\"pre\">query_params</span></code> 参数。</p>\n</aside>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.Client.options\">\n<span class=\"sig-name descname\"><span class=\"pre\">options</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">path</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">data</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">''</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">content_type</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">'application/octet-stream'</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">follow</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">False</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">secure</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">False</span></span></em>, <em class=\"sig-param\"><span class=\"keyword-only-separator o\"><abbr title=\"Keyword-only parameters separator (PEP 3102)\"><span class=\"pre\">*</span></abbr></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">headers</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">query_params</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">extra</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.Client.options\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>在提供的 <code class=\"docutils literal notranslate\"><span class=\"pre\">path</span></code> 上发出一个 OPTIONS 请求并返回一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">Response</span></code> 对象。用于测试 RESTful 接口。</p>\n<p>当提供 <code class=\"docutils literal notranslate\"><span class=\"pre\">data</span></code> 时，它将被用作请求主体并且 <code class=\"docutils literal notranslate\"><span class=\"pre\">Content-Type</span></code> 头被设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">content_type</span></code>。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">follow</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">secure</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">headers</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">query_params</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">extra</span></code> 参数的作用与 <a class=\"reference internal\" href=\"#django.test.Client.get\" title=\"django.test.Client.get\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">Client.get()</span></code></a> 相同。</p>\n<aside class=\"version-note version-changed\" data-version=\"5.1\">\n<p class=\"version-note-title\">Changed in Django 5.1</p><p>增加了 <code class=\"docutils literal notranslate\"><span class=\"pre\">query_params</span></code> 参数。</p>\n</aside>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.Client.put\">\n<span class=\"sig-name descname\"><span class=\"pre\">put</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">path</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">data</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">''</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">content_type</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">'application/octet-stream'</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">follow</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">False</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">secure</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">False</span></span></em>, <em class=\"sig-param\"><span class=\"keyword-only-separator o\"><abbr title=\"Keyword-only parameters separator (PEP 3102)\"><span class=\"pre\">*</span></abbr></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">headers</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">query_params</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">extra</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.Client.put\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>在提供的 <code class=\"docutils literal notranslate\"><span class=\"pre\">path</span></code> 上发出一个 PUT 请求，并返回一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">Response</span></code> 对象。用于测试 RESTful 接口。</p>\n<p>当提供 <code class=\"docutils literal notranslate\"><span class=\"pre\">data</span></code> 时，它将被用作请求主体并且 <code class=\"docutils literal notranslate\"><span class=\"pre\">Content-Type</span></code> 头被设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">content_type</span></code>。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">follow</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">secure</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">headers</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">query_params</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">extra</span></code> 参数的作用与 <a class=\"reference internal\" href=\"#django.test.Client.get\" title=\"django.test.Client.get\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">Client.get()</span></code></a> 相同。</p>\n<aside class=\"version-note version-changed\" data-version=\"5.1\">\n<p class=\"version-note-title\">Changed in Django 5.1</p><p>增加了 <code class=\"docutils literal notranslate\"><span class=\"pre\">query_params</span></code> 参数。</p>\n</aside>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.Client.patch\">\n<span class=\"sig-name descname\"><span class=\"pre\">patch</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">path</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">data</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">''</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">content_type</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">'application/octet-stream'</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">follow</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">False</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">secure</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">False</span></span></em>, <em class=\"sig-param\"><span class=\"keyword-only-separator o\"><abbr title=\"Keyword-only parameters separator (PEP 3102)\"><span class=\"pre\">*</span></abbr></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">headers</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">query_params</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">extra</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.Client.patch\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>在提供的 <code class=\"docutils literal notranslate\"><span class=\"pre\">path</span></code> 上发出一个 PATCH 请求，并返回一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">Response</span></code> 对象。用于测试 RESTful 接口。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">follow</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">secure</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">headers</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">query_params</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">extra</span></code> 参数的作用与 <a class=\"reference internal\" href=\"#django.test.Client.get\" title=\"django.test.Client.get\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">Client.get()</span></code></a> 相同。</p>\n<aside class=\"version-note version-changed\" data-version=\"5.1\">\n<p class=\"version-note-title\">Changed in Django 5.1</p><p>增加了 <code class=\"docutils literal notranslate\"><span class=\"pre\">query_params</span></code> 参数。</p>\n</aside>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.Client.delete\">\n<span class=\"sig-name descname\"><span class=\"pre\">delete</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">path</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">data</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">''</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">content_type</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">'application/octet-stream'</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">follow</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">False</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">secure</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">False</span></span></em>, <em class=\"sig-param\"><span class=\"keyword-only-separator o\"><abbr title=\"Keyword-only parameters separator (PEP 3102)\"><span class=\"pre\">*</span></abbr></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">headers</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">query_params</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">extra</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.Client.delete\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>在提供的 <code class=\"docutils literal notranslate\"><span class=\"pre\">path</span></code> 上发出一个 DELETE 请求，并返回一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">Response</span></code> 对象。用于测试 RESTful 接口。</p>\n<p>当提供 <code class=\"docutils literal notranslate\"><span class=\"pre\">data</span></code> 时，它将被用作请求主体并且 <code class=\"docutils literal notranslate\"><span class=\"pre\">Content-Type</span></code> 头被设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">content_type</span></code>。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">follow</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">secure</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">headers</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">query_params</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">extra</span></code> 参数的作用与 <a class=\"reference internal\" href=\"#django.test.Client.get\" title=\"django.test.Client.get\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">Client.get()</span></code></a> 相同。</p>\n<aside class=\"version-note version-changed\" data-version=\"5.1\">\n<p class=\"version-note-title\">Changed in Django 5.1</p><p>增加了 <code class=\"docutils literal notranslate\"><span class=\"pre\">query_params</span></code> 参数。</p>\n</aside>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.Client.trace\">\n<span class=\"sig-name descname\"><span class=\"pre\">trace</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">path</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">follow</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">False</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">secure</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">False</span></span></em>, <em class=\"sig-param\"><span class=\"keyword-only-separator o\"><abbr title=\"Keyword-only parameters separator (PEP 3102)\"><span class=\"pre\">*</span></abbr></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">headers</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">query_params</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">extra</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.Client.trace\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>在提供的 <code class=\"docutils literal notranslate\"><span class=\"pre\">path</span></code> 上发出一个 TRACE 请求，并返回一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">Response</span></code> 对象。用于模拟诊断探针。</p>\n<p>与其他请求方法不同，<code class=\"docutils literal notranslate\"><span class=\"pre\">data</span></code> 不作为关键字参数提供，以遵守 <span class=\"target\" id=\"index-12\"></span><a class=\"rfc reference external\" href=\"https://datatracker.ietf.org/doc/html/rfc9110.html#section-9.3.8\"><strong>RFC 9110 Section 9.3.8</strong></a>，该规定要求 TRACE 请求不得包含主体。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">follow</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">secure</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">headers</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">query_params</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">extra</span></code> 参数的作用与 <a class=\"reference internal\" href=\"#django.test.Client.get\" title=\"django.test.Client.get\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">Client.get()</span></code></a> 相同。</p>\n<aside class=\"version-note version-changed\" data-version=\"5.1\">\n<p class=\"version-note-title\">Changed in Django 5.1</p><p>增加了 <code class=\"docutils literal notranslate\"><span class=\"pre\">query_params</span></code> 参数。</p>\n</aside>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.Client.login\">\n<span class=\"sig-name descname\"><span class=\"pre\">login</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">credentials</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.Client.login\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.Client.alogin\">\n<span class=\"sig-name descname\"><span class=\"pre\">alogin</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">credentials</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.Client.alogin\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><em>异步版本</em>：<code class=\"docutils literal notranslate\"><span class=\"pre\">alogin()</span></code></p>\n<p>如果你的网站使用了 Django 的 <a class=\"reference internal\" href=\"/zh-hans/5.2/topics/auth/\"><span class=\"doc\">认证系统</span></a>，并且你需要处理登录用户的问题，你可以使用测试客户端的 <code class=\"docutils literal notranslate\"><span class=\"pre\">login()</span></code> 方法来模拟用户登录网站的效果。</p>\n<p>调用此方法后，测试客户端将拥有通过任何可能构成视图一部分的基于登录的测试所需的所有 cookie 和会话数据。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">credentials</span></code> 参数的格式取决于你正在使用哪个 <a class=\"reference internal\" href=\"/zh-hans/5.2/topics/auth/customizing/#authentication-backends\"><span class=\"std std-ref\">authentication backend</span></a> （由你的 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/settings/#std-setting-AUTHENTICATION_BACKENDS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTHENTICATION_BACKENDS</span></code></a> 设置配置）。如果你正在使用 Django 提供的标准认证后端（<code class=\"docutils literal notranslate\"><span class=\"pre\">ModelBackend</span></code>），那么 <code class=\"docutils literal notranslate\"><span class=\"pre\">credentials</span></code> 应该是用户的用户名和密码，以关键字参数的形式提供：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">c</span> <span class=\"o\">=</span> <span class=\"n\">Client</span><span class=\"p\">()</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">c</span><span class=\"o\">.</span><span class=\"n\">login</span><span class=\"p\">(</span><span class=\"n\">username</span><span class=\"o\">=</span><span class=\"s2\">&quot;fred&quot;</span><span class=\"p\">,</span> <span class=\"n\">password</span><span class=\"o\">=</span><span class=\"s2\">&quot;secret&quot;</span><span class=\"p\">)</span>\n\n<span class=\"go\"># Now you can access a view that&#39;s only available to logged-in users.</span>\n</code></pre></div>\n<p>如果你使用的是不同的认证后端，这个方法可能需要不同的凭证。它需要你的后端 <code class=\"docutils literal notranslate\"><span class=\"pre\">authenticate()</span></code> 方法所需要的任何凭证。</p>\n<p>如果凭证被接受且登录成功，则 <code class=\"docutils literal notranslate\"><span class=\"pre\">login()</span></code> 返回 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>。</p>\n<p>最后，在使用这个方法之前，你需要记得创建用户账户。正如我们上面所解释的，测试运行器是使用测试数据库执行的，默认情况下，数据库中不包含用户。因此，在生产站点上有效的用户账户在测试条件下将无法工作。你需要创建用户作为测试套件的一部分--无论是手动创建（使用 Django 模型 API）还是使用测试夹具。记住，如果你想让你的测试用户有一个密码，你不能直接通过设置密码属性来设置用户的密码——你必须使用 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/contrib/auth/#django.contrib.auth.models.User.set_password\" title=\"django.contrib.auth.models.User.set_password\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">set_password()</span></code></a> 函数来存储一个正确的哈希密码。或者，你可以使用 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/contrib/auth/#django.contrib.auth.models.UserManager.create_user\" title=\"django.contrib.auth.models.UserManager.create_user\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">create_user()</span></code></a> 辅助方法来创建一个具有正确哈希密码的新用户。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.Client.force_login\">\n<span class=\"sig-name descname\"><span class=\"pre\">force_login</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">user</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">backend</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.Client.force_login\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.Client.aforce_login\">\n<span class=\"sig-name descname\"><span class=\"pre\">aforce_login</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">user</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">backend</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.Client.aforce_login\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><em>异步版本</em>：<code class=\"docutils literal notranslate\"><span class=\"pre\">aforce_login()</span></code></p>\n<p>如果你的网站使用了 Django 的 <a class=\"reference internal\" href=\"/zh-hans/5.2/topics/auth/\"><span class=\"doc\">认证系统</span></a>，你可以使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">force_login()</span></code> 方法来模拟用户登录网站的效果。当测试需要用户登录，而用户如何登录的细节并不重要时，可以使用这个方法代替 <a class=\"reference internal\" href=\"#django.test.Client.login\" title=\"django.test.Client.login\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">login()</span></code></a>。</p>\n<p>与 <code class=\"docutils literal notranslate\"><span class=\"pre\">login()</span></code> 不同的是，这个方法跳过了认证和验证步骤：不活跃的用户（<a class=\"reference internal\" href=\"/zh-hans/5.2/ref/contrib/auth/#django.contrib.auth.models.User.is_active\" title=\"django.contrib.auth.models.User.is_active\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">is_active=False</span></code></a>）被允许登录，并且不需要提供用户凭证。</p>\n<p>用户的 <code class=\"docutils literal notranslate\"><span class=\"pre\">backend</span></code> 属性将被设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">backend</span></code> 参数的值（应该是一个点分隔 Python 路径字符串），如果没有提供值，则设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">settings.AUTHENTICATION_BACKENDS[0]</span></code>。<a class=\"reference internal\" href=\"#django.test.Client.login\" title=\"django.test.Client.login\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">login()</span></code></a> 调用的 <a class=\"reference internal\" href=\"/zh-hans/5.2/topics/auth/default/#django.contrib.auth.authenticate\" title=\"django.contrib.auth.authenticate\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">authenticate()</span></code></a> 函数通常会对用户进行注释。</p>\n<p>这个方法比 <code class=\"docutils literal notranslate\"><span class=\"pre\">login()</span></code> 快，因为它绕过了昂贵的密码散列算法。另外，你也可以通过 <a class=\"reference internal\" href=\"/zh-hans/5.2/topics/testing/overview/#speeding-up-tests-auth-hashers\"><span class=\"std std-ref\">在测试时使用较弱的哈希算法</span></a> 来加快 <code class=\"docutils literal notranslate\"><span class=\"pre\">login()</span></code> 速度。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.Client.logout\">\n<span class=\"sig-name descname\"><span class=\"pre\">logout</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.Client.logout\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.Client.alogout\">\n<span class=\"sig-name descname\"><span class=\"pre\">alogout</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.Client.alogout\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><em>异步版本</em>：<code class=\"docutils literal notranslate\"><span class=\"pre\">alogout()</span></code></p>\n<p>如果你的网站使用了 Django 的 <a class=\"reference internal\" href=\"/zh-hans/5.2/topics/auth/\"><span class=\"doc\">认证系统</span></a>，<code class=\"docutils literal notranslate\"><span class=\"pre\">logout()</span></code> 方法可以用来模拟用户注销网站的效果。</p>\n<p>调用此方法后，测试客户端的所有 cookie 和会话数据都会被清除为默认值。随后的请求将看起来来自一个 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/contrib/auth/#django.contrib.auth.models.AnonymousUser\" title=\"django.contrib.auth.models.AnonymousUser\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AnonymousUser</span></code></a>。</p>\n</dd></dl>\n\n</dd></dl>\n\n</section>\n<section id=\"testing-responses\">\n<h3>测试响应<a class=\"heading-anchor\" href=\"#testing-responses\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">get()</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">post()</span></code> 方法都会返回一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">Response</span></code> 对象，这个 <code class=\"docutils literal notranslate\"><span class=\"pre\">Response</span></code> 对象与 Django 视图返回的 <code class=\"docutils literal notranslate\"><span class=\"pre\">HttpResponse</span></code> 对象是 <em>不</em> 一样的；测试响应对象有一些额外的数据，对测试代码验证很有用。</p>\n<p>具体来说，<code class=\"docutils literal notranslate\"><span class=\"pre\">Response</span></code> 对象具有以下属性：</p>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.test.Response\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">Response</span></span><a class=\"heading-anchor\" href=\"#django.test.Response\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.test.Response.client\">\n<span class=\"sig-name descname\"><span class=\"pre\">client</span></span><a class=\"heading-anchor\" href=\"#django.test.Response.client\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>用于发出请求并得到响应的测试客户端。</p>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.test.Response.content\">\n<span class=\"sig-name descname\"><span class=\"pre\">content</span></span><a class=\"heading-anchor\" href=\"#django.test.Response.content\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>以字节字符串形式的响应主体。 这是视图或任何错误消息所呈现的最终页面内容。</p>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.test.Response.context\">\n<span class=\"sig-name descname\"><span class=\"pre\">context</span></span><a class=\"heading-anchor\" href=\"#django.test.Response.context\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>模板 <code class=\"docutils literal notranslate\"><span class=\"pre\">Context</span></code> 实例，用于渲染产生响应内容的模板。</p>\n<p>如果渲染的页面使用了多个模板，那么 <code class=\"docutils literal notranslate\"><span class=\"pre\">context</span></code> 将是一个按渲染顺序排列的 <code class=\"docutils literal notranslate\"><span class=\"pre\">Context</span></code> 对象列表。</p>\n<p>在渲染过程中使用了多少个模板，你都可以使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">[]</span></code> 运算符检索上下文值。例如，可以使用以下方式检索上下文变量 <code class=\"docutils literal notranslate\"><span class=\"pre\">name</span></code>：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s2\">&quot;/foo/&quot;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">context</span><span class=\"p\">[</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">]</span>\n<span class=\"go\">&#39;Arthur&#39;</span>\n</code></pre></div>\n<aside class=\"admonition-not-using-django-templates admonition\">\n<p class=\"admonition-title\">没有使用 Django 模板？</p>\n<p>这个属性只有在使用 <a class=\"reference internal\" href=\"/zh-hans/5.2/topics/templates/#django.template.backends.django.DjangoTemplates\" title=\"django.template.backends.django.DjangoTemplates\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DjangoTemplates</span></code></a> 后端时才会被填充。如果你正在使用其他模板引擎，在带有该属性的响应上，<a class=\"reference internal\" href=\"/zh-hans/5.2/ref/template-response/#django.template.response.SimpleTemplateResponse.context_data\" title=\"django.template.response.SimpleTemplateResponse.context_data\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">context_data</span></code></a> 可能是一个合适的选择。</p>\n</aside>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.test.Response.exc_info\">\n<span class=\"sig-name descname\"><span class=\"pre\">exc_info</span></span><a class=\"heading-anchor\" href=\"#django.test.Response.exc_info\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>一个由三个值组成的元组，它提供了关于在视图期间发生的未处理异常（如果有）的信息。</p>\n<p>值是（type，value，traceback），与 Python 的 <a class=\"reference external\" href=\"https://docs.python.org/3/library/sys.html#sys.exc_info\" title=\"(in Python v3.14)\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">sys.exc_info()</span></code></a> 返回的值相同。它们的含义是：</p>\n<ul class=\"simple\">\n<li><p><em>type</em>：异常的类型。</p></li>\n<li><p><em>value</em>：异常的实例。</p></li>\n<li><p><em>traceback</em>：一个追溯对象，在最初发生异常的地方封装了调用堆栈。</p></li>\n</ul>\n<p>如果没有发生异常，那么 <code class=\"docutils literal notranslate\"><span class=\"pre\">exc_info</span></code> 将是 <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code>。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.Response.json\">\n<span class=\"sig-name descname\"><span class=\"pre\">json</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">kwargs</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.Response.json\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>响应的主体，解析为 JSON。额外的关键字参数将传递给 <a class=\"reference external\" href=\"https://docs.python.org/3/library/json.html#json.loads\" title=\"(in Python v3.14)\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">json.loads()</span></code></a>。例如：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s2\">&quot;/foo/&quot;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">json</span><span class=\"p\">()[</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">]</span>\n<span class=\"go\">&#39;Arthur&#39;</span>\n</code></pre></div>\n<p>如果 <code class=\"docutils literal notranslate\"><span class=\"pre\">Content-Type</span></code> 头不是 <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;application/json&quot;</span></code>，那么在试图解析响应时将会出现一个 <a class=\"reference external\" href=\"https://docs.python.org/3/library/exceptions.html#ValueError\" title=\"(in Python v3.14)\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">ValueError</span></code></a>。</p>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.test.Response.request\">\n<span class=\"sig-name descname\"><span class=\"pre\">request</span></span><a class=\"heading-anchor\" href=\"#django.test.Response.request\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>激发响应的请求数据。</p>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.test.Response.wsgi_request\">\n<span class=\"sig-name descname\"><span class=\"pre\">wsgi_request</span></span><a class=\"heading-anchor\" href=\"#django.test.Response.wsgi_request\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>由生成响应的测试处理程序生成的 <code class=\"docutils literal notranslate\"><span class=\"pre\">WSGIRequest</span></code> 实例。</p>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.test.Response.status_code\">\n<span class=\"sig-name descname\"><span class=\"pre\">status_code</span></span><a class=\"heading-anchor\" href=\"#django.test.Response.status_code\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>整数形式的响应 HTTP 状态。关于定义代码的完整列表，查看 <a class=\"reference external\" href=\"https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml\">IANA status code registry</a>.</p>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.test.Response.templates\">\n<span class=\"sig-name descname\"><span class=\"pre\">templates</span></span><a class=\"heading-anchor\" href=\"#django.test.Response.templates\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>用于渲染最终内容的 <code class=\"docutils literal notranslate\"><span class=\"pre\">Template</span></code> 实例列表，按渲染顺序排列。对于列表中的每个模板，如果模板是从文件中加载的，则使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">template.name</span></code> 获得模板的文件名。（名字是一个字符串，如 <code class=\"docutils literal notranslate\"><span class=\"pre\">'admin/index.html'</span></code>。）</p>\n<aside class=\"admonition-not-using-django-templates admonition\">\n<p class=\"admonition-title\">没有使用 Django 模板？</p>\n<p>这个属性只有在使用 <a class=\"reference internal\" href=\"/zh-hans/5.2/topics/templates/#django.template.backends.django.DjangoTemplates\" title=\"django.template.backends.django.DjangoTemplates\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DjangoTemplates</span></code></a> 后端时才会被填充。如果你使用的是其他模板引擎，并且你只需要渲染所用模板的名称，那么 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/template-response/#django.template.response.SimpleTemplateResponse.template_name\" title=\"django.template.response.SimpleTemplateResponse.template_name\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">template_name</span></code></a> 可能是一个合适的选择。</p>\n</aside>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.test.Response.resolver_match\">\n<span class=\"sig-name descname\"><span class=\"pre\">resolver_match</span></span><a class=\"heading-anchor\" href=\"#django.test.Response.resolver_match\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>响应的 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/urlresolvers/#django.urls.ResolverMatch\" title=\"django.urls.ResolverMatch\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ResolverMatch</span></code></a> 的实例。你可以使用 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/urlresolvers/#django.urls.ResolverMatch.func\" title=\"django.urls.ResolverMatch.func\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">func</span></code></a> 属性，例如，验证服务于响应的视图：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"c1\"># my_view here is a function based view.</span>\n<span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertEqual</span><span class=\"p\">(</span><span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">resolver_match</span><span class=\"o\">.</span><span class=\"n\">func</span><span class=\"p\">,</span> <span class=\"n\">my_view</span><span class=\"p\">)</span>\n\n<span class=\"c1\"># Class-based views need to compare the view_class, as the</span>\n<span class=\"c1\"># functions generated by as_view() won&#39;t be equal.</span>\n<span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertIs</span><span class=\"p\">(</span><span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">resolver_match</span><span class=\"o\">.</span><span class=\"n\">func</span><span class=\"o\">.</span><span class=\"n\">view_class</span><span class=\"p\">,</span> <span class=\"n\">MyView</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>如果找不到给定的 URL，访问这个属性会引发一个 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/exceptions/#django.urls.Resolver404\" title=\"django.urls.Resolver404\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">Resolver404</span></code></a> 异常。</p>\n</dd></dl>\n\n</dd></dl>\n\n<p>和普通的响应一样，你也可以通过 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/request-response/#django.http.HttpResponse.headers\" title=\"django.http.HttpResponse.headers\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">HttpResponse.headers</span></code></a> 访问头信息。例如，你可以使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">response.headers['Content-Type']</span></code> 来确定一个响应的内容类型。</p>\n</section>\n<section id=\"exceptions\">\n<h3>例外<a class=\"heading-anchor\" href=\"#exceptions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>如果你把测试客户端指向一个会引发异常的视图，并且 <code class=\"docutils literal notranslate\"><span class=\"pre\">Client.raise_request_exception</span></code> 是 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>，那么这个异常将在测试用例中可见。然后你可以使用标准的 <code class=\"docutils literal notranslate\"><span class=\"pre\">try</span> <span class=\"pre\">...</span> <span class=\"pre\">except</span></code> 块或 <a class=\"reference external\" href=\"https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertRaises\" title=\"(in Python v3.14)\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">assertRaises()</span></code></a> 来测试异常。</p>\n<p>测试客户端看不到的异常只有 <a class=\"reference internal\" href=\"/zh-hans/5.2/topics/http/views/#django.http.Http404\" title=\"django.http.Http404\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Http404</span></code></a>、<a class=\"reference internal\" href=\"/zh-hans/5.2/ref/exceptions/#django.core.exceptions.PermissionDenied\" title=\"django.core.exceptions.PermissionDenied\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">PermissionDenied</span></code></a>、<a class=\"reference external\" href=\"https://docs.python.org/3/library/exceptions.html#SystemExit\" title=\"(in Python v3.14)\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">SystemExit</span></code></a> 和 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/exceptions/#django.core.exceptions.SuspiciousOperation\" title=\"django.core.exceptions.SuspiciousOperation\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SuspiciousOperation</span></code></a>。Django 在内部捕获这些异常，并将其转换为相应的 HTTP 响应代码。在这些情况下，你可以在测试中检查 <code class=\"docutils literal notranslate\"><span class=\"pre\">response.status_code</span></code>。</p>\n<p>如果 <code class=\"docutils literal notranslate\"><span class=\"pre\">Client.raise_request_exception</span></code> 为 <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code>，测试客户端将返回一个 500 的响应，就像返回给浏览器一样。响应有属性 <a class=\"reference internal\" href=\"#django.test.Response.exc_info\" title=\"django.test.Response.exc_info\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">exc_info</span></code></a> 来提供关于未处理的异常的信息。</p>\n</section>\n<section id=\"persistent-state\">\n<h3>持久状态<a class=\"heading-anchor\" href=\"#persistent-state\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>测试客户端是有状态的。如果一个响应返回一个 cookie，那么这个 cookie 将被存储在测试客户端，并与所有后续的 <code class=\"docutils literal notranslate\"><span class=\"pre\">get()</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">post()</span></code> 请求一起发送。</p>\n<p>不遵循这些 cookie 的过期策略。如果你希望 cookie 过期，请手动删除它或创建一个新的 <code class=\"docutils literal notranslate\"><span class=\"pre\">Client</span></code> 实例（这将有效地删除所有 cookie）。</p>\n<p>测试客户端具有存储持久状态信息的属性。你可以在测试条件的一部分访问这些属性。</p>\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.test.Client.cookies\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">Client.</span></span><span class=\"sig-name descname\"><span class=\"pre\">cookies</span></span><a class=\"heading-anchor\" href=\"#django.test.Client.cookies\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>一个 Python <a class=\"reference external\" href=\"https://docs.python.org/3/library/http.cookies.html#http.cookies.SimpleCookie\" title=\"(in Python v3.14)\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SimpleCookie</span></code></a> 对象，包含所有客户端 cookie 的当前值。更多信息请参见 <a class=\"reference external\" href=\"https://docs.python.org/3/library/http.cookies.html#module-http.cookies\" title=\"(in Python v3.14)\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">http.cookies</span></code></a> 模块的文档。</p>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.test.Client.session\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">Client.</span></span><span class=\"sig-name descname\"><span class=\"pre\">session</span></span><a class=\"heading-anchor\" href=\"#django.test.Client.session\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>一个类似字典的对象，包含会话信息。详细内容请参见 <a class=\"reference internal\" href=\"/zh-hans/5.2/topics/http/sessions/\"><span class=\"doc\">会话文档</span></a>。</p>\n<p>要修改会话然后保存，必须先将其存储在一个变量中（因为每次访问该属性时都会创建一个新的 <code class=\"docutils literal notranslate\"><span class=\"pre\">SessionStore</span></code>）：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_something</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n    <span class=\"n\">session</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">session</span>\n    <span class=\"n\">session</span><span class=\"p\">[</span><span class=\"s2\">&quot;somekey&quot;</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;test&quot;</span>\n    <span class=\"n\">session</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span>\n</code></pre></div>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.Client.asession\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">Client.</span></span><span class=\"sig-name descname\"><span class=\"pre\">asession</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.Client.asession\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>这类似于 <a class=\"reference internal\" href=\"#django.test.Client.session\" title=\"django.test.Client.session\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">session</span></code></a> 属性，但它在异步上下文中工作。</p>\n</dd></dl>\n\n</section>\n<section id=\"setting-the-language\">\n<h3>设置语言<a class=\"heading-anchor\" href=\"#setting-the-language\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>在测试支持国际化和本地化的应用程序时，你可能想为测试客户端请求设置语言。这样做的方法取决于 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/middleware/#django.middleware.locale.LocaleMiddleware\" title=\"django.middleware.locale.LocaleMiddleware\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">LocaleMiddleware</span></code></a> 是否启用。</p>\n<p>如果启用了中间件，可以通过创建一个名为 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/settings/#std-setting-LANGUAGE_COOKIE_NAME\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">LANGUAGE_COOKIE_NAME</span></code></a> 的 cookie 来设置语言，其值为语言代码：。</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.conf</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">settings</span>\n\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_language_using_cookie</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n    <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">cookies</span><span class=\"o\">.</span><span class=\"n\">load</span><span class=\"p\">({</span><span class=\"n\">settings</span><span class=\"o\">.</span><span class=\"n\">LANGUAGE_COOKIE_NAME</span><span class=\"p\">:</span> <span class=\"s2\">&quot;fr&quot;</span><span class=\"p\">})</span>\n    <span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s2\">&quot;/&quot;</span><span class=\"p\">)</span>\n    <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertEqual</span><span class=\"p\">(</span><span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">content</span><span class=\"p\">,</span> <span class=\"sa\">b</span><span class=\"s2\">&quot;Bienvenue sur mon site.&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>或在请求中加入 <code class=\"docutils literal notranslate\"><span class=\"pre\">Accept-Language</span></code> HTTP 头：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_language_using_header</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n    <span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s2\">&quot;/&quot;</span><span class=\"p\">,</span> <span class=\"n\">headers</span><span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s2\">&quot;accept-language&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;fr&quot;</span><span class=\"p\">})</span>\n    <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertEqual</span><span class=\"p\">(</span><span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">content</span><span class=\"p\">,</span> <span class=\"sa\">b</span><span class=\"s2\">&quot;Bienvenue sur mon site.&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>在使用这些方法时，请确保在每个测试结束时重置活动语言：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">tearDown</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n    <span class=\"n\">translation</span><span class=\"o\">.</span><span class=\"n\">activate</span><span class=\"p\">(</span><span class=\"n\">settings</span><span class=\"o\">.</span><span class=\"n\">LANGUAGE_CODE</span><span class=\"p\">)</span>\n</code></pre></div>\n</aside>\n<p>更多细节请参考 <a class=\"reference internal\" href=\"/zh-hans/5.2/topics/i18n/translation/#how-django-discovers-language-preference\"><span class=\"std std-ref\">Django 如何发现语言偏好</span></a>。</p>\n<p>如果中间件没有启用，可以使用 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/utils/#django.utils.translation.override\" title=\"django.utils.translation.override\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">translation.override()</span></code></a> 设置活动语言：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.utils</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">translation</span>\n\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_language_using_override</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n    <span class=\"k\">with</span> <span class=\"n\">translation</span><span class=\"o\">.</span><span class=\"n\">override</span><span class=\"p\">(</span><span class=\"s2\">&quot;fr&quot;</span><span class=\"p\">):</span>\n        <span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s2\">&quot;/&quot;</span><span class=\"p\">)</span>\n    <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertEqual</span><span class=\"p\">(</span><span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">content</span><span class=\"p\">,</span> <span class=\"sa\">b</span><span class=\"s2\">&quot;Bienvenue sur mon site.&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>更多细节见 <a class=\"reference internal\" href=\"/zh-hans/5.2/topics/i18n/translation/#explicitly-setting-the-active-language\"><span class=\"std std-ref\">显式设置语言</span></a>。</p>\n</section>\n<section id=\"example\">\n<h3>例如<a class=\"heading-anchor\" href=\"#example\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>以下是使用测试客户端进行的单元测试：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">import</span><span class=\"w\"> </span><span class=\"nn\">unittest</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.test</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Client</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">SimpleTest</span><span class=\"p\">(</span><span class=\"n\">unittest</span><span class=\"o\">.</span><span class=\"n\">TestCase</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">setUp</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Every test needs a client.</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">client</span> <span class=\"o\">=</span> <span class=\"n\">Client</span><span class=\"p\">()</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_details</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Issue a GET request.</span>\n        <span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s2\">&quot;/customer/details/&quot;</span><span class=\"p\">)</span>\n\n        <span class=\"c1\"># Check that the response is 200 OK.</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertEqual</span><span class=\"p\">(</span><span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">status_code</span><span class=\"p\">,</span> <span class=\"mi\">200</span><span class=\"p\">)</span>\n\n        <span class=\"c1\"># Check that the rendered context contains 5 customers.</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertEqual</span><span class=\"p\">(</span><span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">context</span><span class=\"p\">[</span><span class=\"s2\">&quot;customers&quot;</span><span class=\"p\">]),</span> <span class=\"mi\">5</span><span class=\"p\">)</span>\n</code></pre></div>\n<aside class=\"admonition admonition-seealso\">\n<p class=\"admonition-title\">See also</p>\n<p><a class=\"reference internal\" href=\"/zh-hans/5.2/topics/testing/advanced/#django.test.RequestFactory\" title=\"django.test.RequestFactory\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">django.test.RequestFactory</span></code></a></p>\n</aside>\n</section>\n</section>\n<section id=\"provided-test-case-classes\">\n<span id=\"django-testcase-subclasses\"></span><h2>提供的测试用例类<a class=\"heading-anchor\" href=\"#provided-test-case-classes\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>一般的 Python 单元测试类都会扩展一个基类 <a class=\"reference external\" href=\"https://docs.python.org/3/library/unittest.html#unittest.TestCase\" title=\"(in Python v3.14)\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">unittest.TestCase</span></code></a>。Django 提供了这个基类的一些扩展。</p>\n<figure class=\"align-default\" id=\"id4\">\n<span id=\"testcase-hierarchy-diagram\"></span><a class=\"reference internal image-reference\" href=\"../../../../../../_images/django_unittest_classes_hierarchy.svg\"><img alt=\"Django 单元测试类（TestCase 子类）的层次结构\" src=\"/zh-hans/5.2/_images/django_unittest_classes_hierarchy.svg\" style=\"width: 508px; height: 328px;\" />\n</a>\n<figcaption>\n<p><span class=\"caption-text\">Django 单元测试类的层次结构</span><a class=\"heading-anchor\" href=\"#id4\"><span class=\"visually-hidden\">Link to this image</span><span aria-hidden=\"true\">#</span></a></p>\n</figcaption>\n</figure>\n<p>你可以将一个普通的 <a class=\"reference external\" href=\"https://docs.python.org/3/library/unittest.html#unittest.TestCase\" title=\"(in Python v3.14)\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">unittest.TestCase</span></code></a> 转换为任何一个子类：将你的测试基类从 <code class=\"docutils literal notranslate\"><span class=\"pre\">unittest.TestCase</span></code> 改为子类。所有标准的 Python 单元测试功能都将是可用的，并且它将被一些有用的附加功能所增强，如下面每节所述。</p>\n<section id=\"simpletestcase\">\n<h3><code class=\"docutils literal notranslate\"><span class=\"pre\">SimpleTestCase</span></code><a class=\"heading-anchor\" href=\"#simpletestcase\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.test.SimpleTestCase\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">SimpleTestCase</span></span><a class=\"heading-anchor\" href=\"#django.test.SimpleTestCase\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p><a class=\"reference external\" href=\"https://docs.python.org/3/library/unittest.html#unittest.TestCase\" title=\"(in Python v3.14)\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">unittest.TestCase</span></code></a> 的一个子类，增加了以下功能：</p>\n<ul class=\"simple\">\n<li><p>一些有用的断言，例如：</p>\n<ul>\n<li><p>检查一个可调用对象 <a class=\"reference internal\" href=\"#django.test.SimpleTestCase.assertRaisesMessage\" title=\"django.test.SimpleTestCase.assertRaisesMessage\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">会引发某个异常</span></code></a>。</p></li>\n<li><p>检查一个可调用对象 <a class=\"reference internal\" href=\"#django.test.SimpleTestCase.assertWarnsMessage\" title=\"django.test.SimpleTestCase.assertWarnsMessage\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">会触发某个警告</span></code></a>。</p></li>\n<li><p>测试表单字段 <a class=\"reference internal\" href=\"#django.test.SimpleTestCase.assertFieldOutput\" title=\"django.test.SimpleTestCase.assertFieldOutput\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">渲染和错误处理</span></code></a>。</p></li>\n<li><p>测试 <a class=\"reference internal\" href=\"#django.test.SimpleTestCase.assertContains\" title=\"django.test.SimpleTestCase.assertContains\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">HTML</span> <span class=\"pre\">响应是否存在／缺乏给定的片段</span></code></a>。</p></li>\n<li><p>验证模板 <a class=\"reference internal\" href=\"#django.test.SimpleTestCase.assertTemplateUsed\" title=\"django.test.SimpleTestCase.assertTemplateUsed\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">是否被用于生成给定的响应内容</span></code></a>。</p></li>\n<li><p>验证两个 <a class=\"reference internal\" href=\"#django.test.SimpleTestCase.assertURLEqual\" title=\"django.test.SimpleTestCase.assertURLEqual\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">URL</span></code></a> 是否相等。</p></li>\n<li><p>验证应用程序是否执行了HTTP <a class=\"reference internal\" href=\"#django.test.SimpleTestCase.assertRedirects\" title=\"django.test.SimpleTestCase.assertRedirects\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">redirect</span></code></a>。</p></li>\n<li><p>严格测试两个 <a class=\"reference internal\" href=\"#django.test.SimpleTestCase.assertHTMLEqual\" title=\"django.test.SimpleTestCase.assertHTMLEqual\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">HTML</span> <span class=\"pre\">片段</span></code></a> 是否相等或 <a class=\"reference internal\" href=\"#django.test.SimpleTestCase.assertInHTML\" title=\"django.test.SimpleTestCase.assertInHTML\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">包含</span></code></a>。</p></li>\n<li><p>严格测试两个 <a class=\"reference internal\" href=\"#django.test.SimpleTestCase.assertXMLEqual\" title=\"django.test.SimpleTestCase.assertXMLEqual\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">XML</span> <span class=\"pre\">片段</span></code></a> 是否相等。</p></li>\n<li><p>严格测试两个 <a class=\"reference internal\" href=\"#django.test.SimpleTestCase.assertJSONEqual\" title=\"django.test.SimpleTestCase.assertJSONEqual\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">JSON</span> <span class=\"pre\">片段</span></code></a> 相等。</p></li>\n</ul>\n</li>\n<li><p>能够用 <a class=\"reference internal\" href=\"#overriding-settings\"><span class=\"std std-ref\">修改后的配置</span></a> 运行测试。</p></li>\n<li><p>使用 <a class=\"reference internal\" href=\"#django.test.SimpleTestCase.client\" title=\"django.test.SimpleTestCase.client\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">client</span></code></a> <a class=\"reference internal\" href=\"#django.test.Client\" title=\"django.test.Client\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Client</span></code></a>。</p></li>\n</ul>\n<p>如果你的测试进行任何数据库查询，请使用子类 <a class=\"reference internal\" href=\"#django.test.TransactionTestCase\" title=\"django.test.TransactionTestCase\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TransactionTestCase</span></code></a> 或 <a class=\"reference internal\" href=\"#django.test.TestCase\" title=\"django.test.TestCase\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TestCase</span></code></a>。</p>\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.test.SimpleTestCase.databases\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">SimpleTestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">databases</span></span><a class=\"heading-anchor\" href=\"#django.test.SimpleTestCase.databases\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><a class=\"reference internal\" href=\"#django.test.SimpleTestCase\" title=\"django.test.SimpleTestCase\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SimpleTestCase</span></code></a> 默认不允许数据库查询。这有助于避免执行写查询而影响其他测试，因为每个 <code class=\"docutils literal notranslate\"><span class=\"pre\">SimpleTestCase</span></code> 测试不是在事务中运行的。如果你不关心这个问题，你可以通过在你的测试类上设置 <code class=\"docutils literal notranslate\"><span class=\"pre\">databases</span></code> 类属性为 <code class=\"docutils literal notranslate\"><span class=\"pre\">'__all__'</span></code> 来禁止这个行为。</p>\n</dd></dl>\n\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Warning</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">SimpleTestCase</span></code> 和它的子类（如 <code class=\"docutils literal notranslate\"><span class=\"pre\">TestCase</span></code>）依靠 <code class=\"docutils literal notranslate\"><span class=\"pre\">setUpClass()</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">tearDownClass()</span></code> 来执行一些全类范围的初始化（如覆盖配置）。如果你需要覆盖这些方法，别忘了调用 <code class=\"docutils literal notranslate\"><span class=\"pre\">super</span></code> 实现：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MyTestCase</span><span class=\"p\">(</span><span class=\"n\">TestCase</span><span class=\"p\">):</span>\n    <span class=\"nd\">@classmethod</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">setUpClass</span><span class=\"p\">(</span><span class=\"bp\">cls</span><span class=\"p\">):</span>\n        <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">setUpClass</span><span class=\"p\">()</span>\n        <span class=\"o\">...</span>\n\n    <span class=\"nd\">@classmethod</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">tearDownClass</span><span class=\"p\">(</span><span class=\"bp\">cls</span><span class=\"p\">):</span>\n        <span class=\"o\">...</span>\n        <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">tearDownClass</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>如果在 <code class=\"docutils literal notranslate\"><span class=\"pre\">setUpClass()</span></code> 过程中出现异常，一定要考虑到 Python 的行为。如果发生这种情况，类中的测试和 <code class=\"docutils literal notranslate\"><span class=\"pre\">tearDownClass()</span></code> 都不会被运行。在 <a class=\"reference internal\" href=\"#django.test.TestCase\" title=\"django.test.TestCase\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">django.test.TestCase</span></code></a> 的情况下，这将会泄露在 <code class=\"docutils literal notranslate\"><span class=\"pre\">super()</span></code> 中创建的事务，从而导致各种症状，包括在某些平台上的分段故障（在 macOS 上报告）。如果你想在 <code class=\"docutils literal notranslate\"><span class=\"pre\">setUpClass()</span></code> 中故意引发一个异常，如 <a class=\"reference external\" href=\"https://docs.python.org/3/library/unittest.html#unittest.SkipTest\" title=\"(in Python v3.14)\"><code class=\"xref py py-exc docutils literal notranslate\"><span class=\"pre\">unittest.SkipTest</span></code></a>，一定要在调用 <code class=\"docutils literal notranslate\"><span class=\"pre\">super()</span></code> 之前进行，以避免这种情况。</p>\n</aside>\n</section>\n<section id=\"transactiontestcase\">\n<h3><code class=\"docutils literal notranslate\"><span class=\"pre\">TransactionTestCase</span></code><a class=\"heading-anchor\" href=\"#transactiontestcase\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.test.TransactionTestCase\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">TransactionTestCase</span></span><a class=\"heading-anchor\" href=\"#django.test.TransactionTestCase\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">TransactionTestCase</span></code> 继承自 <a class=\"reference internal\" href=\"#django.test.SimpleTestCase\" title=\"django.test.SimpleTestCase\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SimpleTestCase</span></code></a> 以增加一些数据库特有的功能：</p>\n<ul class=\"simple\">\n<li><p>Resetting the database to a known state at the end of each test to ease\ntesting and using the ORM.</p></li>\n<li><p>数据库 <a class=\"reference internal\" href=\"#django.test.TransactionTestCase.fixtures\" title=\"django.test.TransactionTestCase.fixtures\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">fixtures</span></code></a>.</p></li>\n<li><p>测试 <a class=\"reference internal\" href=\"#skipping-tests\"><span class=\"std std-ref\">基于数据库后端功能的跳过</span></a>.</p></li>\n<li><p>剩下的专用 <a class=\"reference internal\" href=\"#django.test.TransactionTestCase.assertQuerySetEqual\" title=\"django.test.TransactionTestCase.assertQuerySetEqual\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">assert*</span></code></a> 方法。</p></li>\n</ul>\n<p>Django's <a class=\"reference internal\" href=\"#django.test.TestCase\" title=\"django.test.TestCase\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TestCase</span></code></a> class is a more commonly used subclass of\n<code class=\"docutils literal notranslate\"><span class=\"pre\">TransactionTestCase</span></code> that makes use of database transaction facilities\nto speed up the process of resetting the database to a known state at the\nend of each test. A consequence of this, however, is that some database\nbehaviors cannot be tested within a Django <code class=\"docutils literal notranslate\"><span class=\"pre\">TestCase</span></code> class. For instance,\nyou cannot test that a block of code is executing within a transaction, as is\nrequired when using\n<a class=\"reference internal\" href=\"/zh-hans/5.2/ref/models/querysets/#django.db.models.query.QuerySet.select_for_update\" title=\"django.db.models.query.QuerySet.select_for_update\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">select_for_update()</span></code></a>. In those cases,\nyou should use <code class=\"docutils literal notranslate\"><span class=\"pre\">TransactionTestCase</span></code>.</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">TransactionTestCase</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">TestCase</span></code> 除了将数据库重设为已知状态的方式和测试与测试提交和回滚效果的相关代码外，其他都是相同的。</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">TransactionTestCase</span></code> 在测试运行后，通过清空所有表来重置数据库。<code class=\"docutils literal notranslate\"><span class=\"pre\">TransactionTestCase</span></code> 可以调用提交和回滚，并观察这些调用对数据库的影响。</p></li>\n<li><p>另一方面，<code class=\"docutils literal notranslate\"><span class=\"pre\">TestCase</span></code> 在测试后不清空表。相反，它将测试代码包含在数据库事务中，在测试结束后回滚。这保证了测试结束时的回滚能将数据库恢复到初始状态。</p></li>\n</ul>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Warning</p>\n<p>在不支持回滚的数据库上运行的 <code class=\"docutils literal notranslate\"><span class=\"pre\">TestCase</span></code> （例如 MyISAM 存储引擎的 MySQL ），则 <code class=\"docutils literal notranslate\"><span class=\"pre\">TransactionTestCase</span></code> 的所有实例，将在测试结束时回滚，删除测试数据库中的所有数据。</p>\n<p>应用 <a class=\"reference internal\" href=\"/zh-hans/5.2/topics/testing/overview/#test-case-serialized-rollback\"><span class=\"std std-ref\">不会看到他们的数据被重新加载</span></a>；如果你需要这个功能（例如，第三方应用应该启用这个功能），你可以在 <code class=\"docutils literal notranslate\"><span class=\"pre\">TestCase</span></code> 中设置 <code class=\"docutils literal notranslate\"><span class=\"pre\">serialized_rollback</span> <span class=\"pre\">=</span> <span class=\"pre\">True</span></code>。</p>\n</aside>\n</section>\n<section id=\"testcase\">\n<h3><code class=\"docutils literal notranslate\"><span class=\"pre\">TestCase</span></code><a class=\"heading-anchor\" href=\"#testcase\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.test.TestCase\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">TestCase</span></span><a class=\"heading-anchor\" href=\"#django.test.TestCase\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>这是 Django 中最常用的编写测试的类。它继承自 <a class=\"reference internal\" href=\"#django.test.TransactionTestCase\" title=\"django.test.TransactionTestCase\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TransactionTestCase</span></code></a> （以及扩展自 <a class=\"reference internal\" href=\"#django.test.SimpleTestCase\" title=\"django.test.SimpleTestCase\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SimpleTestCase</span></code></a>）。如果你的 Django 应用程序不使用数据库，就使用 <a class=\"reference internal\" href=\"#django.test.SimpleTestCase\" title=\"django.test.SimpleTestCase\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SimpleTestCase</span></code></a>。</p>\n<p>此类：</p>\n<ul class=\"simple\">\n<li><p>在两个嵌套的 <a class=\"reference internal\" href=\"/zh-hans/5.2/topics/db/transactions/#django.db.transaction.atomic\" title=\"django.db.transaction.atomic\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">atomic()</span></code></a> 块中封装测试：一个用于整个类，一个用于每个测试。因此，如果你想测试一些特定的数据库事务行为，可以使用 <a class=\"reference internal\" href=\"#django.test.TransactionTestCase\" title=\"django.test.TransactionTestCase\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TransactionTestCase</span></code></a>。</p></li>\n<li><p>在每次测试结束时检查可延迟的数据库约束。</p></li>\n</ul>\n<p>它还提供了另一种方法：</p>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.TestCase.setUpTestData\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">classmethod</span></span><span class=\"w\"> </span></em><span class=\"sig-prename descclassname\"><span class=\"pre\">TestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">setUpTestData</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.TestCase.setUpTestData\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>上文所述的类级 <code class=\"docutils literal notranslate\"><span class=\"pre\">atomic</span></code> 块允许在类级创建初始数据，整个 <code class=\"docutils literal notranslate\"><span class=\"pre\">TestCase</span></code> 只需一次。与使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">setUp()</span></code> 相比，这种技术允许更快的测试。</p>\n<p>例如：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.test</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">TestCase</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MyTests</span><span class=\"p\">(</span><span class=\"n\">TestCase</span><span class=\"p\">):</span>\n    <span class=\"nd\">@classmethod</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">setUpTestData</span><span class=\"p\">(</span><span class=\"bp\">cls</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Set up data for the whole TestCase</span>\n        <span class=\"bp\">cls</span><span class=\"o\">.</span><span class=\"n\">foo</span> <span class=\"o\">=</span> <span class=\"n\">Foo</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">create</span><span class=\"p\">(</span><span class=\"n\">bar</span><span class=\"o\">=</span><span class=\"s2\">&quot;Test&quot;</span><span class=\"p\">)</span>\n        <span class=\"o\">...</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test1</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Some test using self.foo</span>\n        <span class=\"o\">...</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test2</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Some other test using self.foo</span>\n        <span class=\"o\">...</span>\n</code></pre></div>\n<p>请注意，如果测试是在没有事务支持的数据库上运行（例如，MyISAM 引擎的 MySQL），<code class=\"docutils literal notranslate\"><span class=\"pre\">setUpTestData()</span></code> 将在每次测试前被调用，从而降低了速度优势。</p>\n<p>在 <code class=\"docutils literal notranslate\"><span class=\"pre\">setUpTestData()</span></code> 中分配给类属性的对象必须支持使用 <a class=\"reference external\" href=\"https://docs.python.org/3/library/copy.html#copy.deepcopy\" title=\"(in Python v3.14)\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">copy.deepcopy()</span></code></a> 创建深层副本，以便将它们与每个测试方法执行的更改隔离开来。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.TestCase.captureOnCommitCallbacks\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">classmethod</span></span><span class=\"w\"> </span></em><span class=\"sig-prename descclassname\"><span class=\"pre\">TestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">captureOnCommitCallbacks</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">using</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">DEFAULT_DB_ALIAS</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">execute</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">False</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.TestCase.captureOnCommitCallbacks\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>返回一个为给定的数据库连接捕获 <a class=\"reference internal\" href=\"/zh-hans/5.2/topics/db/transactions/#django.db.transaction.on_commit\" title=\"django.db.transaction.on_commit\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">transaction.on_commit()</span></code></a> 回调的上下文管理器。它返回一个列表，其中包含在退出上下文时，捕获的回调函数。从这个列表中，你可以对回调进行断言，或者调用它们来获得其副作用，模拟一个提交。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">using</span></code> 是数据库连接的别名，用于捕获回调。</p>\n<p>如果 <code class=\"docutils literal notranslate\"><span class=\"pre\">execute</span></code> 是 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>，并且如果没有发生异常，所有的回调将在上下文管理器退出时被调用。这模拟了在包裹的代码块之后的提交。</p>\n<p>例如：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.core</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">mail</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.test</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">TestCase</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">ContactTests</span><span class=\"p\">(</span><span class=\"n\">TestCase</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_post</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"k\">with</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">captureOnCommitCallbacks</span><span class=\"p\">(</span><span class=\"n\">execute</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span> <span class=\"k\">as</span> <span class=\"n\">callbacks</span><span class=\"p\">:</span>\n            <span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">post</span><span class=\"p\">(</span>\n                <span class=\"s2\">&quot;/contact/&quot;</span><span class=\"p\">,</span>\n                <span class=\"p\">{</span><span class=\"s2\">&quot;message&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;I like your site&quot;</span><span class=\"p\">},</span>\n            <span class=\"p\">)</span>\n\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertEqual</span><span class=\"p\">(</span><span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">status_code</span><span class=\"p\">,</span> <span class=\"mi\">200</span><span class=\"p\">)</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertEqual</span><span class=\"p\">(</span><span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"n\">callbacks</span><span class=\"p\">),</span> <span class=\"mi\">1</span><span class=\"p\">)</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertEqual</span><span class=\"p\">(</span><span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"n\">mail</span><span class=\"o\">.</span><span class=\"n\">outbox</span><span class=\"p\">),</span> <span class=\"mi\">1</span><span class=\"p\">)</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertEqual</span><span class=\"p\">(</span><span class=\"n\">mail</span><span class=\"o\">.</span><span class=\"n\">outbox</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"n\">subject</span><span class=\"p\">,</span> <span class=\"s2\">&quot;Contact Form&quot;</span><span class=\"p\">)</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertEqual</span><span class=\"p\">(</span><span class=\"n\">mail</span><span class=\"o\">.</span><span class=\"n\">outbox</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"n\">body</span><span class=\"p\">,</span> <span class=\"s2\">&quot;I like your site&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n</dd></dl>\n\n</section>\n<section id=\"liveservertestcase\">\n<span id=\"live-test-server\"></span><h3><code class=\"docutils literal notranslate\"><span class=\"pre\">LiveServerTestCase</span></code><a class=\"heading-anchor\" href=\"#liveservertestcase\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.test.LiveServerTestCase\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">LiveServerTestCase</span></span><a class=\"heading-anchor\" href=\"#django.test.LiveServerTestCase\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">LiveServerTestCase</span></code> 和 <a class=\"reference internal\" href=\"#django.test.TransactionTestCase\" title=\"django.test.TransactionTestCase\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TransactionTestCase</span></code></a> 的功能基本相同，但多了一个功能：它在设置时在后台启动一个实时的 Django 服务器，并在关闭时将其关闭。这就允许使用 <a class=\"reference internal\" href=\"#test-client\"><span class=\"std std-ref\">Django 虚拟客户端</span></a> 以外的自动化测试客户端，例如，<a class=\"reference external\" href=\"https://www.selenium.dev/\">Selenium</a> 客户端，在浏览器内执行一系列功能测试，并模拟真实用户的操作。</p>\n<p>实时服务器在 <code class=\"docutils literal notranslate\"><span class=\"pre\">localhost</span></code> 上监听，并绑定到 0 号端口，0 号端口使用操作系统分配的一个空闲端口。在测试过程中可以用 <code class=\"docutils literal notranslate\"><span class=\"pre\">self.live_server_url</span></code> 访问服务器的 URL。</p>\n<p>为了演示如何使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">LiveServerTestCase</span></code>，让我们编写一个 Selenium 测试。首先，你需要安装 <a class=\"extlink-pypi reference external\" href=\"https://pypi.org/project/selenium/\">selenium</a> 包：</p>\n<div class=\"console\" data-console><div class=\"console-panel\" data-platform=\"unix\"><p class=\"console-label\" id=\"console-0-unix-label\">Linux / macOS</p><div class=\"code-block\" data-language=\"console\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code><span class=\"gp\">$ </span>python<span class=\"w\"> </span>-m<span class=\"w\"> </span>pip<span class=\"w\"> </span>install<span class=\"w\"> </span><span class=\"s2\">&quot;selenium &gt;= 4.8.0&quot;</span>\n</code></pre></div>\n</div><div class=\"console-panel\" data-platform=\"windows\"><p class=\"console-label\" id=\"console-0-windows-label\">Windows</p><div class=\"code-block\" data-language=\"doscon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Windows</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Windows shell\"><code><span class=\"gp\">...\\&gt;</span> py -m pip install <span class=\"s2\">&quot;selenium &gt;= 4.8.0&quot;</span>\n</code></pre></div></div></div>\n<p>然后，在你的应用程序的测试模块中添加一个基于 <code class=\"docutils literal notranslate\"><span class=\"pre\">LiveServerTestCase</span></code> 的测试（例如：<code class=\"docutils literal notranslate\"><span class=\"pre\">myapp/tests.py</span></code>）。在这个例子中，我们将假设你正在使用 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/contrib/staticfiles/#module-django.contrib.staticfiles\" title=\"django.contrib.staticfiles: An app for handling static files.\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">staticfiles</span></code></a> 应用，并且希望在执行测试时提供类似于我们在开发时使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">DEBUG=True</span></code> 得到的静态文件，即不必使用 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/contrib/staticfiles/#django-admin-collectstatic\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">collectstatic</span></code></a> 收集它们。我们将使用 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/contrib/staticfiles/#django.contrib.staticfiles.testing.StaticLiveServerTestCase\" title=\"django.contrib.staticfiles.testing.StaticLiveServerTestCase\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">StaticLiveServerTestCase</span></code></a> 子类，它提供了这个功能。如果不需要的话，可以用 <code class=\"docutils literal notranslate\"><span class=\"pre\">django.test.LiveServerTestCase</span></code> 代替。</p>\n<p>这个测试的代码可能如下：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.staticfiles.testing</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">StaticLiveServerTestCase</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">selenium.webdriver.common.by</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">By</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">selenium.webdriver.firefox.webdriver</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">WebDriver</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MySeleniumTests</span><span class=\"p\">(</span><span class=\"n\">StaticLiveServerTestCase</span><span class=\"p\">):</span>\n    <span class=\"n\">fixtures</span> <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s2\">&quot;user-data.json&quot;</span><span class=\"p\">]</span>\n\n    <span class=\"nd\">@classmethod</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">setUpClass</span><span class=\"p\">(</span><span class=\"bp\">cls</span><span class=\"p\">):</span>\n        <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">setUpClass</span><span class=\"p\">()</span>\n        <span class=\"bp\">cls</span><span class=\"o\">.</span><span class=\"n\">selenium</span> <span class=\"o\">=</span> <span class=\"n\">WebDriver</span><span class=\"p\">()</span>\n        <span class=\"bp\">cls</span><span class=\"o\">.</span><span class=\"n\">selenium</span><span class=\"o\">.</span><span class=\"n\">implicitly_wait</span><span class=\"p\">(</span><span class=\"mi\">10</span><span class=\"p\">)</span>\n\n    <span class=\"nd\">@classmethod</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">tearDownClass</span><span class=\"p\">(</span><span class=\"bp\">cls</span><span class=\"p\">):</span>\n        <span class=\"bp\">cls</span><span class=\"o\">.</span><span class=\"n\">selenium</span><span class=\"o\">.</span><span class=\"n\">quit</span><span class=\"p\">()</span>\n        <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">tearDownClass</span><span class=\"p\">()</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_login</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">selenium</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"sa\">f</span><span class=\"s2\">&quot;</span><span class=\"si\">{</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">live_server_url</span><span class=\"si\">}</span><span class=\"s2\">/login/&quot;</span><span class=\"p\">)</span>\n        <span class=\"n\">username_input</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">selenium</span><span class=\"o\">.</span><span class=\"n\">find_element</span><span class=\"p\">(</span><span class=\"n\">By</span><span class=\"o\">.</span><span class=\"n\">NAME</span><span class=\"p\">,</span> <span class=\"s2\">&quot;username&quot;</span><span class=\"p\">)</span>\n        <span class=\"n\">username_input</span><span class=\"o\">.</span><span class=\"n\">send_keys</span><span class=\"p\">(</span><span class=\"s2\">&quot;myuser&quot;</span><span class=\"p\">)</span>\n        <span class=\"n\">password_input</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">selenium</span><span class=\"o\">.</span><span class=\"n\">find_element</span><span class=\"p\">(</span><span class=\"n\">By</span><span class=\"o\">.</span><span class=\"n\">NAME</span><span class=\"p\">,</span> <span class=\"s2\">&quot;password&quot;</span><span class=\"p\">)</span>\n        <span class=\"n\">password_input</span><span class=\"o\">.</span><span class=\"n\">send_keys</span><span class=\"p\">(</span><span class=\"s2\">&quot;secret&quot;</span><span class=\"p\">)</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">selenium</span><span class=\"o\">.</span><span class=\"n\">find_element</span><span class=\"p\">(</span><span class=\"n\">By</span><span class=\"o\">.</span><span class=\"n\">XPATH</span><span class=\"p\">,</span> <span class=\"s1\">&#39;//input[@value=&quot;Log in&quot;]&#39;</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">click</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>最后，你可以按以下方式进行测试：</p>\n<div class=\"console\" data-console><div class=\"console-panel\" data-platform=\"unix\"><p class=\"console-label\" id=\"console-1-unix-label\">Linux / macOS</p><div class=\"code-block\" data-language=\"console\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code><span class=\"gp\">$ </span>./manage.py<span class=\"w\"> </span><span class=\"nb\">test</span><span class=\"w\"> </span>myapp.tests.MySeleniumTests.test_login\n</code></pre></div>\n</div><div class=\"console-panel\" data-platform=\"windows\"><p class=\"console-label\" id=\"console-1-windows-label\">Windows</p><div class=\"code-block\" data-language=\"doscon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Windows</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Windows shell\"><code><span class=\"gp\">...\\&gt;</span> manage.py test myapp.tests.MySeleniumTests.test_login\n</code></pre></div></div></div>\n<p>这个例子会自动打开 Firefox，然后进入登录页面，输入凭证并按“登录”按钮。Selenium 提供了其他驱动程序，以防你没有安装 Firefox 或希望使用其他浏览器。上面的例子只是 Selenium 客户端能做的一小部分，更多细节请查看 <a class=\"reference external\" href=\"https://selenium-python.readthedocs.io/api.html\">full reference</a>。</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>当使用内存 SQLite 数据库运行测试时，同一个数据库连接将由两个线程并行共享：运行实时服务器的线程和运行测试用例的线程。要防止两个线程通过这个共享连接同时进行数据库查询，因为这有时可能会随机导致测试失败。所以你需要确保两个线程不会同时访问数据库。特别是，这意味着在某些情况下（例如，刚刚点击一个链接或提交一个表单之后），你可能需要检查 Selenium 是否收到了响应，并且在继续执行进一步的测试之前，检查下一个页面是否被加载。例如，让 Selenium 等待直到在响应中找到 <code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;body&gt;</span></code> HTML 标签（需要 Selenium &gt; 2.13）：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_login</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n    <span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">selenium.webdriver.support.wait</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">WebDriverWait</span>\n\n    <span class=\"n\">timeout</span> <span class=\"o\">=</span> <span class=\"mi\">2</span>\n    <span class=\"o\">...</span>\n    <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">selenium</span><span class=\"o\">.</span><span class=\"n\">find_element</span><span class=\"p\">(</span><span class=\"n\">By</span><span class=\"o\">.</span><span class=\"n\">XPATH</span><span class=\"p\">,</span> <span class=\"s1\">&#39;//input[@value=&quot;Log in&quot;]&#39;</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">click</span><span class=\"p\">()</span>\n    <span class=\"c1\"># Wait until the response is received</span>\n    <span class=\"n\">WebDriverWait</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">selenium</span><span class=\"p\">,</span> <span class=\"n\">timeout</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">until</span><span class=\"p\">(</span>\n        <span class=\"k\">lambda</span> <span class=\"n\">driver</span><span class=\"p\">:</span> <span class=\"n\">driver</span><span class=\"o\">.</span><span class=\"n\">find_element</span><span class=\"p\">(</span><span class=\"n\">By</span><span class=\"o\">.</span><span class=\"n\">TAG_NAME</span><span class=\"p\">,</span> <span class=\"s2\">&quot;body&quot;</span><span class=\"p\">)</span>\n    <span class=\"p\">)</span>\n</code></pre></div>\n<p>这里的棘手之处在于，实际上并没有真正的 &quot;页面加载&quot;，特别是在现代的 Web 应用程序中，在服务器生成初始文档后，页面会动态生成 HTML。因此，仅仅检查响应中是否存在 <code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;body&gt;</span></code> 可能不适用于所有用例。请参考 <a class=\"reference external\" href=\"https://web.archive.org/web/20160129132110/http://code.google.com/p/selenium/wiki/FrequentlyAskedQuestions#Q:_WebDriver_fails_to_find_elements_/_Does_not_block_on_page_loa\">Selenium FAQ</a> 和 <a class=\"reference external\" href=\"https://www.selenium.dev/documentation/webdriver/waits/#explicit-waits\">Selenium documentation</a> 获取更多信息。</p>\n</aside>\n</section>\n</section>\n<section id=\"test-cases-features\">\n<h2>测试用例特性<a class=\"heading-anchor\" href=\"#test-cases-features\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"default-test-client\">\n<h3>默认测试客户端<a class=\"heading-anchor\" href=\"#default-test-client\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.test.SimpleTestCase.client\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">SimpleTestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">client</span></span><a class=\"heading-anchor\" href=\"#django.test.SimpleTestCase.client\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">django.test.*TestCase</span></code> 实例中的每个测试用例都可以访问一个 Django 测试客户端的实例。这个客户端可以用 <code class=\"docutils literal notranslate\"><span class=\"pre\">self.client</span></code> 来访问。这个客户端在每个测试中都会被重新创建，所以你不必担心状态（比如 cookie）会从一个测试转移到另一个测试中。</p>\n<p>这意味着，不必每个测试中实例化一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">Client</span></code>：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">import</span><span class=\"w\"> </span><span class=\"nn\">unittest</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.test</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Client</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">SimpleTest</span><span class=\"p\">(</span><span class=\"n\">unittest</span><span class=\"o\">.</span><span class=\"n\">TestCase</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_details</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"n\">client</span> <span class=\"o\">=</span> <span class=\"n\">Client</span><span class=\"p\">()</span>\n        <span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s2\">&quot;/customer/details/&quot;</span><span class=\"p\">)</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertEqual</span><span class=\"p\">(</span><span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">status_code</span><span class=\"p\">,</span> <span class=\"mi\">200</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_index</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"n\">client</span> <span class=\"o\">=</span> <span class=\"n\">Client</span><span class=\"p\">()</span>\n        <span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s2\">&quot;/customer/index/&quot;</span><span class=\"p\">)</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertEqual</span><span class=\"p\">(</span><span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">status_code</span><span class=\"p\">,</span> <span class=\"mi\">200</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>......你可以引用 <code class=\"docutils literal notranslate\"><span class=\"pre\">self.client</span></code>，像这样：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.test</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">TestCase</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">SimpleTest</span><span class=\"p\">(</span><span class=\"n\">TestCase</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_details</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s2\">&quot;/customer/details/&quot;</span><span class=\"p\">)</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertEqual</span><span class=\"p\">(</span><span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">status_code</span><span class=\"p\">,</span> <span class=\"mi\">200</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_index</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s2\">&quot;/customer/index/&quot;</span><span class=\"p\">)</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertEqual</span><span class=\"p\">(</span><span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">status_code</span><span class=\"p\">,</span> <span class=\"mi\">200</span><span class=\"p\">)</span>\n</code></pre></div>\n</section>\n<section id=\"customizing-the-test-client\">\n<h3>自定义测试客户端<a class=\"heading-anchor\" href=\"#customizing-the-test-client\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.test.SimpleTestCase.client_class\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">SimpleTestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">client_class</span></span><a class=\"heading-anchor\" href=\"#django.test.SimpleTestCase.client_class\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>如果你想使用不同的 <code class=\"docutils literal notranslate\"><span class=\"pre\">Client</span></code> 类（例如，一个具有自定义行为的子类），使用 <a class=\"reference internal\" href=\"#django.test.SimpleTestCase.client_class\" title=\"django.test.SimpleTestCase.client_class\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">client_class</span></code></a> 类属性：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.test</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Client</span><span class=\"p\">,</span> <span class=\"n\">TestCase</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MyTestClient</span><span class=\"p\">(</span><span class=\"n\">Client</span><span class=\"p\">):</span>\n    <span class=\"c1\"># Specialized methods for your environment</span>\n    <span class=\"o\">...</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MyTest</span><span class=\"p\">(</span><span class=\"n\">TestCase</span><span class=\"p\">):</span>\n    <span class=\"n\">client_class</span> <span class=\"o\">=</span> <span class=\"n\">MyTestClient</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_my_stuff</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Here self.client is an instance of MyTestClient...</span>\n        <span class=\"n\">call_some_test_code</span><span class=\"p\">()</span>\n</code></pre></div>\n</section>\n<section id=\"fixture-loading\">\n<span id=\"topics-testing-fixtures\"></span><h3>辅助工具加载<a class=\"heading-anchor\" href=\"#fixture-loading\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.test.TransactionTestCase.fixtures\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">TransactionTestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">fixtures</span></span><a class=\"heading-anchor\" href=\"#django.test.TransactionTestCase.fixtures\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>如果数据库中没有任何数据，那么用于数据库支持的网站的测试用例类就没有什么用处。使用 ORM 创建对象更易于阅读和维护，例如在 <a class=\"reference internal\" href=\"#django.test.TestCase.setUpTestData\" title=\"django.test.TestCase.setUpTestData\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">TestCase.setUpTestData()</span></code></a> 中，但也可以使用 <a class=\"reference internal\" href=\"/zh-hans/5.2/topics/db/fixtures/#fixtures-explanation\"><span class=\"std std-ref\">fixtures</span></a>。</p>\n<p>辅助工具是 Django 知道如何导入数据库的数据集合。例如，如果你的网站有用户账户，你可能会设置一个假用户账户的辅助工具，以便在测试时填充你的数据库。</p>\n<p>创建辅助工具的最直接方法是使用 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/django-admin/#django-admin-dumpdata\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">manage.py</span> <span class=\"pre\">dumpdata</span></code></a> 命令。这假定你已经在你的数据库中拥有一些数据。参见 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/django-admin/#django-admin-dumpdata\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">dumpdata</span> <span class=\"pre\">文档</span></code></a> 了解更多细节。</p>\n<p>一旦你创建了一个辅助工具，并把它放在你的 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">INSTALLED_APPS</span></code></a> 中的 <code class=\"docutils literal notranslate\"><span class=\"pre\">fixtures</span></code> 目录下，你就可以通过在你的 <a class=\"reference internal\" href=\"#django.test.TestCase\" title=\"django.test.TestCase\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">django.test.TestCase</span></code></a> 子类上指定一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">fixtures</span></code> 类属性来在你的单元测试中使用它。</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.test</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">TestCase</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">myapp.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Animal</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">AnimalTestCase</span><span class=\"p\">(</span><span class=\"n\">TestCase</span><span class=\"p\">):</span>\n    <span class=\"n\">fixtures</span> <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s2\">&quot;mammals.json&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;birds&quot;</span><span class=\"p\">]</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">setUp</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Test definitions as before.</span>\n        <span class=\"n\">call_setup_methods</span><span class=\"p\">()</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_fluffy_animals</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"c1\"># A test that uses the fixtures.</span>\n        <span class=\"n\">call_some_test_code</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>具体来说，将发生以下情况：</p>\n<ul class=\"simple\">\n<li><p>During <code class=\"docutils literal notranslate\"><span class=\"pre\">setUpClass()</span></code>, all the named fixtures are installed. In this\nexample, Django will install any JSON fixture named <code class=\"docutils literal notranslate\"><span class=\"pre\">mammals</span></code>, followed by\nany fixture named <code class=\"docutils literal notranslate\"><span class=\"pre\">birds</span></code>. See the <a class=\"reference internal\" href=\"/zh-hans/5.2/topics/db/fixtures/#fixtures-explanation\"><span class=\"std std-ref\">辅助工具</span></a> topic for\nmore details on defining and installing fixtures.</p></li>\n</ul>\n<p>For most unit tests using <a class=\"reference internal\" href=\"#django.test.TestCase\" title=\"django.test.TestCase\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TestCase</span></code></a>, Django doesn't need to do\nanything else, because transactions are used to clean the database after each\ntest for performance reasons. But for <a class=\"reference internal\" href=\"#django.test.TransactionTestCase\" title=\"django.test.TransactionTestCase\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TransactionTestCase</span></code></a>, the\nfollowing actions will take place:</p>\n<ul class=\"simple\">\n<li><p>At the end of each test Django will flush the database, returning the\ndatabase to the state it was in directly after <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/django-admin/#django-admin-migrate\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">migrate</span></code></a> was\ncalled.</p></li>\n<li><p>For each subsequent test, the fixtures will be reloaded before <code class=\"docutils literal notranslate\"><span class=\"pre\">setUp()</span></code>\nis run.</p></li>\n</ul>\n<p>In any case, you can be certain that the outcome of a test will not be\naffected by another test or by the order of test execution.</p>\n<p>默认情况下，辅助工具只被加载到 <code class=\"docutils literal notranslate\"><span class=\"pre\">default</span></code> 数据库中。如果你使用多个数据库并且设置了 <a class=\"reference internal\" href=\"#django.test.TransactionTestCase.databases\" title=\"django.test.TransactionTestCase.databases\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">TransactionTestCase.databases</span></code></a>，辅助工具将被加载到所有指定的数据库中。</p>\n<aside class=\"version-note version-changed\" data-version=\"5.2\">\n<p class=\"version-note-title\">Changed in Django 5.2</p><p>For <a class=\"reference internal\" href=\"#django.test.TransactionTestCase\" title=\"django.test.TransactionTestCase\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TransactionTestCase</span></code></a>, fixtures were made available during\n<code class=\"docutils literal notranslate\"><span class=\"pre\">setUpClass()</span></code>.</p>\n</aside>\n</section>\n<section id=\"urlconf-configuration\">\n<h3>URLconf 配置<a class=\"heading-anchor\" href=\"#urlconf-configuration\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>如果你的应用程序提供了视图，你可能希望包含使用测试客户端来行使这些视图的测试。然而，最终用户可以自由地在他们选择的任何 URL 上部署应用程序中的视图。这意味着你的测试不能依赖于你的视图将在特定的 URL 上可用这一事实。用 <code class=\"docutils literal notranslate\"><span class=\"pre\">&#64;override_settings(ROOT_URLCONF=...)</span></code> 来装饰你的测试类或测试方法的 URLconf 配置。</p>\n</section>\n<section id=\"multi-database-support\">\n<span id=\"testing-multi-db\"></span><h3>多数据库支持<a class=\"heading-anchor\" href=\"#multi-database-support\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.test.TransactionTestCase.databases\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">TransactionTestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">databases</span></span><a class=\"heading-anchor\" href=\"#django.test.TransactionTestCase.databases\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>Django 设置了一个测试数据库，对应于你设置中的 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/settings/#std-setting-DATABASES\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DATABASES</span></code></a> 定义的并且至少有一个测试引用了 <code class=\"docutils literal notranslate\"><span class=\"pre\">databases</span></code> 的每个数据库。</p>\n<p>However, a big part of the time taken to run a Django <code class=\"docutils literal notranslate\"><span class=\"pre\">TestCase</span></code> is consumed\nby the call to <code class=\"docutils literal notranslate\"><span class=\"pre\">flush</span></code> that ensures that you have a clean database at the\nend of each test run. If you have multiple databases, multiple flushes are\nrequired (one for each database), which can be a time consuming activity --\nespecially if your tests don't need to test multi-database activity.</p>\n<p>As an optimization, Django only flushes the <code class=\"docutils literal notranslate\"><span class=\"pre\">default</span></code> database at\nthe end of each test run. If your setup contains multiple databases,\nand you have a test that requires every database to be clean, you can\nuse the <code class=\"docutils literal notranslate\"><span class=\"pre\">databases</span></code> attribute on the test suite to request extra databases\nto be flushed.</p>\n<p>例如：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">TestMyViews</span><span class=\"p\">(</span><span class=\"n\">TransactionTestCase</span><span class=\"p\">):</span>\n    <span class=\"n\">databases</span> <span class=\"o\">=</span> <span class=\"p\">{</span><span class=\"s2\">&quot;default&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;other&quot;</span><span class=\"p\">}</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_index_page_view</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"n\">call_some_test_code</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>This test case class will flush the <code class=\"docutils literal notranslate\"><span class=\"pre\">default</span></code> and <code class=\"docutils literal notranslate\"><span class=\"pre\">other</span></code> test databases\nafter running <code class=\"docutils literal notranslate\"><span class=\"pre\">test_index_page_view</span></code>. You can also use <code class=\"docutils literal notranslate\"><span class=\"pre\">'__all__'</span></code> to\nspecify that all of the test databases must be flushed.</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">databases</span></code> 标志也控制 <a class=\"reference internal\" href=\"#django.test.TransactionTestCase.fixtures\" title=\"django.test.TransactionTestCase.fixtures\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">TransactionTestCase.fixtures</span></code></a> 被加载到哪些数据库。默认情况下，辅助工具只被加载到 <code class=\"docutils literal notranslate\"><span class=\"pre\">default</span></code> 数据库中。</p>\n<p>对不在 <code class=\"docutils literal notranslate\"><span class=\"pre\">databases</span></code> 中的数据库的查询将给出断言错误，以防止测试之间的状态泄露。</p>\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.test.TestCase.databases\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">TestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">databases</span></span><a class=\"heading-anchor\" href=\"#django.test.TestCase.databases\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>默认情况下，在 <code class=\"docutils literal notranslate\"><span class=\"pre\">TestCase</span></code> 期间，仅将 <code class=\"docutils literal notranslate\"><span class=\"pre\">default</span></code> 数据库包装在事务中，并且尝试查询其他数据库将导致断言错误，以防止测试之间的状态泄漏。</p>\n<p>在测试类上使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">databases</span></code> 类属性来请求对非 <code class=\"docutils literal notranslate\"><span class=\"pre\">default</span></code> 数据库进行事务包装。</p>\n<p>例如：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">OtherDBTests</span><span class=\"p\">(</span><span class=\"n\">TestCase</span><span class=\"p\">):</span>\n    <span class=\"n\">databases</span> <span class=\"o\">=</span> <span class=\"p\">{</span><span class=\"s2\">&quot;other&quot;</span><span class=\"p\">}</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_other_db_query</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span> <span class=\"o\">...</span>\n</code></pre></div>\n<p>这个测试只允许对 <code class=\"docutils literal notranslate\"><span class=\"pre\">other</span></code> 数据库进行查询。就像 <a class=\"reference internal\" href=\"#django.test.SimpleTestCase.databases\" title=\"django.test.SimpleTestCase.databases\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">SimpleTestCase.databases</span></code></a> 和 <a class=\"reference internal\" href=\"#django.test.TransactionTestCase.databases\" title=\"django.test.TransactionTestCase.databases\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">TransactionTestCase.databases</span></code></a> 一样，<code class=\"docutils literal notranslate\"><span class=\"pre\">'__all__'</span></code> 常量可以用来指定测试应该允许对所有数据库进行查询。</p>\n</section>\n<section id=\"overriding-settings\">\n<span id=\"id1\"></span><h3>覆盖配置<a class=\"heading-anchor\" href=\"#overriding-settings\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Warning</p>\n<p>使用下面的函数可以临时改变测试中的设置值。不要直接操作 <code class=\"docutils literal notranslate\"><span class=\"pre\">django.conf.settings</span></code>，因为 Django 不会在这种操作后恢复原始值。</p>\n</aside>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.SimpleTestCase.settings\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">SimpleTestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">settings</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.SimpleTestCase.settings\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>为了测试的目的，经常需要临时改变一个设置，并在运行测试代码后恢复到原始值。对于这个用例，Django 提供了一个标准的 Python 上下文管理器（见 <span class=\"target\" id=\"index-13\"></span><a class=\"pep reference external\" href=\"https://peps.python.org/pep-0343/\"><strong>PEP 343</strong></a>），叫做 <a class=\"reference internal\" href=\"#django.test.SimpleTestCase.settings\" title=\"django.test.SimpleTestCase.settings\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">settings()</span></code></a>，可以这样使用：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.test</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">TestCase</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">LoginTestCase</span><span class=\"p\">(</span><span class=\"n\">TestCase</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_login</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"c1\"># First check for the default behavior</span>\n        <span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s2\">&quot;/sekrit/&quot;</span><span class=\"p\">)</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertRedirects</span><span class=\"p\">(</span><span class=\"n\">response</span><span class=\"p\">,</span> <span class=\"s2\">&quot;/accounts/login/?next=/sekrit/&quot;</span><span class=\"p\">)</span>\n\n        <span class=\"c1\"># Then override the LOGIN_URL setting</span>\n        <span class=\"k\">with</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">settings</span><span class=\"p\">(</span><span class=\"n\">LOGIN_URL</span><span class=\"o\">=</span><span class=\"s2\">&quot;/other/login/&quot;</span><span class=\"p\">):</span>\n            <span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s2\">&quot;/sekrit/&quot;</span><span class=\"p\">)</span>\n            <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertRedirects</span><span class=\"p\">(</span><span class=\"n\">response</span><span class=\"p\">,</span> <span class=\"s2\">&quot;/other/login/?next=/sekrit/&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>这个示例将会在 <code class=\"docutils literal notranslate\"><span class=\"pre\">with</span></code> 块中覆盖 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/settings/#std-setting-LOGIN_URL\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">LOGIN_URL</span></code></a> 设置的值，并在之后将其值重置为之前的状态。</p>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.SimpleTestCase.modify_settings\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">SimpleTestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">modify_settings</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.SimpleTestCase.modify_settings\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>重新定义包含一系列值的设置可能会很麻烦。在实践中，添加或删除值通常是足够的。Django 提供了 <a class=\"reference internal\" href=\"#django.test.SimpleTestCase.modify_settings\" title=\"django.test.SimpleTestCase.modify_settings\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">modify_settings()</span></code></a> 上下文管理器，以方便更改设置：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.test</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">TestCase</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MiddlewareTestCase</span><span class=\"p\">(</span><span class=\"n\">TestCase</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_cache_middleware</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"k\">with</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">modify_settings</span><span class=\"p\">(</span>\n            <span class=\"n\">MIDDLEWARE</span><span class=\"o\">=</span><span class=\"p\">{</span>\n                <span class=\"s2\">&quot;append&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;django.middleware.cache.FetchFromCacheMiddleware&quot;</span><span class=\"p\">,</span>\n                <span class=\"s2\">&quot;prepend&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;django.middleware.cache.UpdateCacheMiddleware&quot;</span><span class=\"p\">,</span>\n                <span class=\"s2\">&quot;remove&quot;</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n                    <span class=\"s2\">&quot;django.contrib.sessions.middleware.SessionMiddleware&quot;</span><span class=\"p\">,</span>\n                    <span class=\"s2\">&quot;django.contrib.auth.middleware.AuthenticationMiddleware&quot;</span><span class=\"p\">,</span>\n                    <span class=\"s2\">&quot;django.contrib.messages.middleware.MessageMiddleware&quot;</span><span class=\"p\">,</span>\n                <span class=\"p\">],</span>\n            <span class=\"p\">}</span>\n        <span class=\"p\">):</span>\n            <span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s2\">&quot;/&quot;</span><span class=\"p\">)</span>\n            <span class=\"c1\"># ...</span>\n</code></pre></div>\n<p>对于每个操作，你可以提供一个值的列表或一个字符串。当值已经存在于列表中时，<code class=\"docutils literal notranslate\"><span class=\"pre\">append</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">prepend</span></code> 没有效果；当值不存在时，<code class=\"docutils literal notranslate\"><span class=\"pre\">remove</span></code> 也没有效果。</p>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.test.override_settings\">\n<span class=\"sig-name descname\"><span class=\"pre\">override_settings</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">kwargs</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.override_settings\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>如果你想覆盖一个测试方法的设置，Django 提供了 <a class=\"reference internal\" href=\"#django.test.override_settings\" title=\"django.test.override_settings\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">override_settings()</span></code></a> 装饰器（见 <span class=\"target\" id=\"index-14\"></span><a class=\"pep reference external\" href=\"https://peps.python.org/pep-0318/\"><strong>PEP 318</strong></a>）。它的用法是这样的：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.test</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">TestCase</span><span class=\"p\">,</span> <span class=\"n\">override_settings</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">LoginTestCase</span><span class=\"p\">(</span><span class=\"n\">TestCase</span><span class=\"p\">):</span>\n    <span class=\"nd\">@override_settings</span><span class=\"p\">(</span><span class=\"n\">LOGIN_URL</span><span class=\"o\">=</span><span class=\"s2\">&quot;/other/login/&quot;</span><span class=\"p\">)</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_login</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s2\">&quot;/sekrit/&quot;</span><span class=\"p\">)</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertRedirects</span><span class=\"p\">(</span><span class=\"n\">response</span><span class=\"p\">,</span> <span class=\"s2\">&quot;/other/login/?next=/sekrit/&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>装饰器也可以应用于 <a class=\"reference internal\" href=\"#django.test.TestCase\" title=\"django.test.TestCase\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TestCase</span></code></a> 类：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.test</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">TestCase</span><span class=\"p\">,</span> <span class=\"n\">override_settings</span>\n\n\n<span class=\"nd\">@override_settings</span><span class=\"p\">(</span><span class=\"n\">LOGIN_URL</span><span class=\"o\">=</span><span class=\"s2\">&quot;/other/login/&quot;</span><span class=\"p\">)</span>\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">LoginTestCase</span><span class=\"p\">(</span><span class=\"n\">TestCase</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_login</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s2\">&quot;/sekrit/&quot;</span><span class=\"p\">)</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertRedirects</span><span class=\"p\">(</span><span class=\"n\">response</span><span class=\"p\">,</span> <span class=\"s2\">&quot;/other/login/?next=/sekrit/&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.test.modify_settings\">\n<span class=\"sig-name descname\"><span class=\"pre\">modify_settings</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">*</span></span><span class=\"n\"><span class=\"pre\">args</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">kwargs</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.modify_settings\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>同样，Django 也提供了 <a class=\"reference internal\" href=\"#django.test.modify_settings\" title=\"django.test.modify_settings\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">modify_settings()</span></code></a> 装饰器：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.test</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">TestCase</span><span class=\"p\">,</span> <span class=\"n\">modify_settings</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MiddlewareTestCase</span><span class=\"p\">(</span><span class=\"n\">TestCase</span><span class=\"p\">):</span>\n    <span class=\"nd\">@modify_settings</span><span class=\"p\">(</span>\n        <span class=\"n\">MIDDLEWARE</span><span class=\"o\">=</span><span class=\"p\">{</span>\n            <span class=\"s2\">&quot;append&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;django.middleware.cache.FetchFromCacheMiddleware&quot;</span><span class=\"p\">,</span>\n            <span class=\"s2\">&quot;prepend&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;django.middleware.cache.UpdateCacheMiddleware&quot;</span><span class=\"p\">,</span>\n        <span class=\"p\">}</span>\n    <span class=\"p\">)</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_cache_middleware</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s2\">&quot;/&quot;</span><span class=\"p\">)</span>\n        <span class=\"c1\"># ...</span>\n</code></pre></div>\n<p>此装饰器也可以应用于测试用例类：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.test</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">TestCase</span><span class=\"p\">,</span> <span class=\"n\">modify_settings</span>\n\n\n<span class=\"nd\">@modify_settings</span><span class=\"p\">(</span>\n    <span class=\"n\">MIDDLEWARE</span><span class=\"o\">=</span><span class=\"p\">{</span>\n        <span class=\"s2\">&quot;append&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;django.middleware.cache.FetchFromCacheMiddleware&quot;</span><span class=\"p\">,</span>\n        <span class=\"s2\">&quot;prepend&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;django.middleware.cache.UpdateCacheMiddleware&quot;</span><span class=\"p\">,</span>\n    <span class=\"p\">}</span>\n<span class=\"p\">)</span>\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MiddlewareTestCase</span><span class=\"p\">(</span><span class=\"n\">TestCase</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_cache_middleware</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s2\">&quot;/&quot;</span><span class=\"p\">)</span>\n        <span class=\"c1\"># ...</span>\n</code></pre></div>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>当给定一个类时，这些装饰器直接修改该类并返回它，它们不会创建并返回一个修改后的副本。因此，如果你试图调整上面的例子，将返回值分配给一个不同于 <code class=\"docutils literal notranslate\"><span class=\"pre\">LoginTestCase</span></code> 或 <code class=\"docutils literal notranslate\"><span class=\"pre\">MiddlewareTestCase</span></code> 的名称，你可能会惊讶地发现，原来的测试用例类仍然同样受到装饰器的影响。对于一个给定的类，<a class=\"reference internal\" href=\"#django.test.modify_settings\" title=\"django.test.modify_settings\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">modify_settings()</span></code></a> 总是应用在 <a class=\"reference internal\" href=\"#django.test.override_settings\" title=\"django.test.override_settings\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">override_settings()</span></code></a> 之后。</p>\n</aside>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Warning</p>\n<p>配置文件中包含了一些设置，这些设置只有在 Django 内部初始化时才会被使用。如果你用 <code class=\"docutils literal notranslate\"><span class=\"pre\">override_settings</span></code> 改变它们，当你通过``django.conf.settings`` 模块访问会得到被改变的配置。但是，Django 的内部程序访问它的方式是不同的。实际上，使用 <a class=\"reference internal\" href=\"#django.test.override_settings\" title=\"django.test.override_settings\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">override_settings()</span></code></a> 或者 <a class=\"reference internal\" href=\"#django.test.modify_settings\" title=\"django.test.modify_settings\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">modify_settings()</span></code></a> 来使用这些设置，很可能达不到你预期的效果。</p>\n<p>我们不建议改变 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/settings/#std-setting-DATABASES\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DATABASES</span></code></a> 的设置。改变 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/settings/#std-setting-CACHES\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">CACHES</span></code></a> 的设置是可能的，但如果你使用的是内部缓存，比如 <code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.contrib.session</span></code>，就有点棘手。例如，你必须在使用缓存会话并覆盖 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/settings/#std-setting-CACHES\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">CACHES</span></code></a> 的测试中重新初始化会话后端。</p>\n<p>最后，避免将你的配置别名为模块级常量，因为 <code class=\"docutils literal notranslate\"><span class=\"pre\">override_settings()</span></code> 不会对这些值起作用，它们只在第一次导入模块时才被评估。</p>\n</aside>\n<p>你也可以在配置被覆盖后，通过删除配置来模拟没有配置，比如这样：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"nd\">@override_settings</span><span class=\"p\">()</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_something</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n    <span class=\"k\">del</span> <span class=\"n\">settings</span><span class=\"o\">.</span><span class=\"n\">LOGIN_URL</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n<p>覆盖配置时，请确保处理你的应用代码使用即使保留配置更改也能保持状态的缓存或类似功能的情况。Django 提供了 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/signals/#django.test.signals.setting_changed\" title=\"django.test.signals.setting_changed\"><code class=\"xref py py-data docutils literal notranslate\"><span class=\"pre\">django.test.signals.setting_changed</span></code></a> 信号，让你在设置被改变时，可以注册回调来清理和重置状态。</p>\n<p>Django 自己也使用这个信号来重置各种数据。</p>\n<div class=\"table-scroll\" role=\"region\" tabindex=\"0\" aria-label=\"Table\"><table class=\"docutils align-default\">\n<thead>\n<tr class=\"row-odd\"><th class=\"head\"><p>覆盖配置</p></th>\n<th class=\"head\"><p>数据重置</p></th>\n</tr>\n</thead>\n<tbody>\n<tr class=\"row-even\"><td><p>USE_TZ，TIME_ZONE</p></td>\n<td><p>数据库时区</p></td>\n</tr>\n<tr class=\"row-odd\"><td><p>TEMPLATES</p></td>\n<td><p>模板引擎</p></td>\n</tr>\n<tr class=\"row-even\"><td><p>FORM_RENDERER</p></td>\n<td><p>默认渲染器</p></td>\n</tr>\n<tr class=\"row-odd\"><td><p>SERIALIZATION_MODULES</p></td>\n<td><p>序列化器缓存</p></td>\n</tr>\n<tr class=\"row-even\"><td><p>LOCALE_PATHS，LANGUAGE_CODE</p></td>\n<td><p>默认翻译和加载的翻译</p></td>\n</tr>\n<tr class=\"row-odd\"><td><p>STATIC_ROOT, STATIC_URL, STORAGES</p></td>\n<td><p>存储配置</p></td>\n</tr>\n</tbody>\n</table>\n</div>\n<aside class=\"version-note version-changed\" data-version=\"5.1\">\n<p class=\"version-note-title\">Changed in Django 5.1</p><p>增加了在更改 <code class=\"docutils literal notranslate\"><span class=\"pre\">FORM_RENDERER</span></code> 设置时重置默认渲染器的功能。</p>\n</aside>\n</section>\n<section id=\"isolating-apps\">\n<h3>隔离应用程序<a class=\"heading-anchor\" href=\"#isolating-apps\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.test.utils.isolate_apps\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">utils.</span></span><span class=\"sig-name descname\"><span class=\"pre\">isolate_apps</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">*</span></span><span class=\"n\"><span class=\"pre\">app_labels</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">attr_name</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">kwarg_name</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.utils.isolate_apps\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>将包装上下文中定义的模型注册到它们自己隔离的 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/applications/#django.apps.apps\" title=\"django.apps.apps\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">apps</span></code></a> 注册表中。这个功能在为测试创建模型类时非常有用，因为这些类将在之后被干净地删除，不会出现名称冲突的风险。</p>\n<p>应该将应该包含在隔离注册表中的应用程序标签作为单独的参数传递。你可以将 <code class=\"docutils literal notranslate\"><span class=\"pre\">isolate_apps()</span></code> 用作装饰器或上下文管理器。例如：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">models</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.test</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">SimpleTestCase</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.test.utils</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">isolate_apps</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MyModelTests</span><span class=\"p\">(</span><span class=\"n\">SimpleTestCase</span><span class=\"p\">):</span>\n    <span class=\"nd\">@isolate_apps</span><span class=\"p\">(</span><span class=\"s2\">&quot;app_label&quot;</span><span class=\"p\">)</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_model_definition</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">TestModel</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Model</span><span class=\"p\">):</span>\n            <span class=\"k\">pass</span>\n\n        <span class=\"o\">...</span>\n</code></pre></div>\n<p>… 或者：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">with</span> <span class=\"n\">isolate_apps</span><span class=\"p\">(</span><span class=\"s2\">&quot;app_label&quot;</span><span class=\"p\">):</span>\n\n    <span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">TestModel</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Model</span><span class=\"p\">):</span>\n        <span class=\"k\">pass</span>\n\n    <span class=\"o\">...</span>\n</code></pre></div>\n<p>装饰器形式也可以应用于类。</p>\n<p>可以指定两个可选的关键字参数：</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">attr_name</span></code>：如果用作类装饰器，将被分配给隔离注册表的属性。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">kwarg_name</span></code>：如果用作函数装饰器，传递隔离注册表的关键字参数。</p></li>\n</ul>\n<p>临时的 <code class=\"docutils literal notranslate\"><span class=\"pre\">Apps</span></code> 实例，用于隔离模型注册，可以在作为类装饰器时通过使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">attr_name</span></code> 参数来检索为属性。</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"nd\">@isolate_apps</span><span class=\"p\">(</span><span class=\"s2\">&quot;app_label&quot;</span><span class=\"p\">,</span> <span class=\"n\">attr_name</span><span class=\"o\">=</span><span class=\"s2\">&quot;apps&quot;</span><span class=\"p\">)</span>\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">TestModelDefinition</span><span class=\"p\">(</span><span class=\"n\">SimpleTestCase</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_model_definition</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">TestModel</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Model</span><span class=\"p\">):</span>\n            <span class=\"k\">pass</span>\n\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertIs</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">apps</span><span class=\"o\">.</span><span class=\"n\">get_model</span><span class=\"p\">(</span><span class=\"s2\">&quot;app_label&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;TestModel&quot;</span><span class=\"p\">),</span> <span class=\"n\">TestModel</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>… 或者，当作为方法装饰器使用时，可以使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">kwarg_name</span></code> 参数将其作为测试方法的参数传递。</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">TestModelDefinition</span><span class=\"p\">(</span><span class=\"n\">SimpleTestCase</span><span class=\"p\">):</span>\n    <span class=\"nd\">@isolate_apps</span><span class=\"p\">(</span><span class=\"s2\">&quot;app_label&quot;</span><span class=\"p\">,</span> <span class=\"n\">kwarg_name</span><span class=\"o\">=</span><span class=\"s2\">&quot;apps&quot;</span><span class=\"p\">)</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_model_definition</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">apps</span><span class=\"p\">):</span>\n        <span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">TestModel</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Model</span><span class=\"p\">):</span>\n            <span class=\"k\">pass</span>\n\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertIs</span><span class=\"p\">(</span><span class=\"n\">apps</span><span class=\"o\">.</span><span class=\"n\">get_model</span><span class=\"p\">(</span><span class=\"s2\">&quot;app_label&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;TestModel&quot;</span><span class=\"p\">),</span> <span class=\"n\">TestModel</span><span class=\"p\">)</span>\n</code></pre></div>\n</dd></dl>\n\n</section>\n<section id=\"emptying-the-test-outbox\">\n<span id=\"emptying-test-outbox\"></span><h3>清空测试发件箱<a class=\"heading-anchor\" href=\"#emptying-the-test-outbox\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>如果你使用任何 Django 的自定义 <code class=\"docutils literal notranslate\"><span class=\"pre\">TestCase</span></code> 类，测试运行器将在每个测试用例开始时清除测试邮件发件箱的内容。</p>\n<p>关于测试期间电子邮件服务的更多细节，请参见下面的 <a class=\"reference internal\" href=\"#email-services\">Email services</a>。</p>\n</section>\n<section id=\"assertions\">\n<span id=\"id2\"></span><h3>断言<a class=\"heading-anchor\" href=\"#assertions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>由于 Python 的普通 <a class=\"reference external\" href=\"https://docs.python.org/3/library/unittest.html#unittest.TestCase\" title=\"(in Python v3.14)\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">unittest.TestCase</span></code></a> 类实现了断言方法，比如 <a class=\"reference external\" href=\"https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertTrue\" title=\"(in Python v3.14)\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">assertTrue()</span></code></a> 和 <a class=\"reference external\" href=\"https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertEqual\" title=\"(in Python v3.14)\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">assertEqual()</span></code></a>，Django 的自定义 <a class=\"reference internal\" href=\"#django.test.TestCase\" title=\"django.test.TestCase\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">TestCase</span></code></a> 类提供了一些有用于测试 Web 应用程序的自定义断言方法：</p>\n<p>大多数这些断言方法给出的失败信息可以用 <code class=\"docutils literal notranslate\"><span class=\"pre\">msg_prefix</span></code> 参数自定义。这个字符串将被加在断言产生的任何失败信息的前面。这允许你提供额外的细节，以帮助你确定测试套件中失败的位置和原因。</p>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.SimpleTestCase.assertRaisesMessage\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">SimpleTestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">assertRaisesMessage</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">expected_exception</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">expected_message</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">callable</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">*</span></span><span class=\"n\"><span class=\"pre\">args</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">kwargs</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.SimpleTestCase.assertRaisesMessage\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dt class=\"sig sig-object py\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">SimpleTestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">assertRaisesMessage</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">expected_exception</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">expected_message</span></span></em><span class=\"sig-paren\">)</span></dt>\n<dd><p>断言执行 <code class=\"docutils literal notranslate\"><span class=\"pre\">callable</span></code> 引起 <code class=\"docutils literal notranslate\"><span class=\"pre\">expected_exception</span></code>，并且在异常信息中发现 <code class=\"docutils literal notranslate\"><span class=\"pre\">expected_message</span></code>。任何其他结果都会被报告为失败。它是 <a class=\"reference external\" href=\"https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertRaisesRegex\" title=\"(in Python v3.14)\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">unittest.TestCase.assertRaisesRegex()</span></code></a> 的简单版本，不同的是 <code class=\"docutils literal notranslate\"><span class=\"pre\">expected_message</span></code> 不作为正则表达式处理。</p>\n<p>如果只给了 <code class=\"docutils literal notranslate\"><span class=\"pre\">expected_exception</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">expected_message</span></code> 参数，则返回一个上下文管理器，以便被测试的代码可以内联而不是作为一个函数来写：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">with</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertRaisesMessage</span><span class=\"p\">(</span><span class=\"ne\">ValueError</span><span class=\"p\">,</span> <span class=\"s2\">&quot;invalid literal for int()&quot;</span><span class=\"p\">):</span>\n    <span class=\"nb\">int</span><span class=\"p\">(</span><span class=\"s2\">&quot;a&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.SimpleTestCase.assertWarnsMessage\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">SimpleTestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">assertWarnsMessage</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">expected_warning</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">expected_message</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">callable</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">*</span></span><span class=\"n\"><span class=\"pre\">args</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">kwargs</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.SimpleTestCase.assertWarnsMessage\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dt class=\"sig sig-object py\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">SimpleTestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">assertWarnsMessage</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">expected_warning</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">expected_message</span></span></em><span class=\"sig-paren\">)</span></dt>\n<dd><p>类似于 <a class=\"reference internal\" href=\"#django.test.SimpleTestCase.assertRaisesMessage\" title=\"django.test.SimpleTestCase.assertRaisesMessage\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">SimpleTestCase.assertRaisesMessage()</span></code></a>，但是 <a class=\"reference external\" href=\"https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertWarnsRegex\" title=\"(in Python v3.14)\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">assertWarnsRegex()</span></code></a> 代替 <a class=\"reference external\" href=\"https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertRaisesRegex\" title=\"(in Python v3.14)\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">assertRaisesRegex()</span></code></a>。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.SimpleTestCase.assertFieldOutput\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">SimpleTestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">assertFieldOutput</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">fieldclass</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">valid</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">invalid</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">field_args</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">field_kwargs</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">empty_value</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">''</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.SimpleTestCase.assertFieldOutput\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>断言表单字段在不同的输入情况下表现正确。</p>\n<dl class=\"field-list simple\">\n<dt class=\"field-odd\">参数<span class=\"colon\">:</span></dt>\n<dd class=\"field-odd\"><ul class=\"simple\">\n<li><p><strong>fieldclass</strong> -- 待测试字段的类。</p></li>\n<li><p><strong>valid</strong> -- 一个字典，将有效输入映射到它们的预期干净值。</p></li>\n<li><p><strong>invalid</strong> -- 一个字典，将无效输入映射到一个或多个引发的错误信息</p></li>\n<li><p><strong>field_args</strong> -- 传递给实例化字段的 args。</p></li>\n<li><p><strong>field_kwargs</strong> -- 传递给实例化字段的 kwargs。</p></li>\n<li><p><strong>empty_value</strong> -- <code class=\"docutils literal notranslate\"><span class=\"pre\">empty_values</span></code> 中输入的预期干净输出。</p></li>\n</ul>\n</dd>\n</dl>\n<p>例如，以下代码测试 <code class=\"docutils literal notranslate\"><span class=\"pre\">EmailField</span></code> 接受 <code class=\"docutils literal notranslate\"><span class=\"pre\">a&#64;a.com</span></code> 作为有效的电子邮件地址，但拒绝 <code class=\"docutils literal notranslate\"><span class=\"pre\">aaa</span></code>，并给出合理的错误信息：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertFieldOutput</span><span class=\"p\">(</span>\n    <span class=\"n\">EmailField</span><span class=\"p\">,</span> <span class=\"p\">{</span><span class=\"s2\">&quot;a@a.com&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;a@a.com&quot;</span><span class=\"p\">},</span> <span class=\"p\">{</span><span class=\"s2\">&quot;aaa&quot;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s2\">&quot;Enter a valid email address.&quot;</span><span class=\"p\">]}</span>\n<span class=\"p\">)</span>\n</code></pre></div>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.SimpleTestCase.assertFormError\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">SimpleTestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">assertFormError</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">form</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">field</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">errors</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">msg_prefix</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">''</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.SimpleTestCase.assertFormError\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>断言表单上的字段引发了提供的错误列表。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">form</span></code> 是一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">Form</span></code> 实例。表单必须是 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/forms/api/#ref-forms-api-bound-unbound\"><span class=\"std std-ref\">已绑定</span></a> 的，但不一定要经过验证（<code class=\"docutils literal notranslate\"><span class=\"pre\">assertFormError()</span></code> 会自动在表单上调用 <code class=\"docutils literal notranslate\"><span class=\"pre\">full_clean()</span></code>）。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">field</span></code> 是要检查的表单上的字段名称。要检查表单的 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/forms/api/#django.forms.Form.non_field_errors\" title=\"django.forms.Form.non_field_errors\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">非字段错误</span></code></a>，请使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">field=None</span></code>。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">errors</span></code> 是字段预期具有的所有错误字符串的列表。如果只期望一个错误，也可以传递单个错误字符串，这意味着 <code class=\"docutils literal notranslate\"><span class=\"pre\">errors='错误消息'</span></code> 与 <code class=\"docutils literal notranslate\"><span class=\"pre\">errors=['错误消息']</span></code> 是相同的。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.SimpleTestCase.assertFormSetError\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">SimpleTestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">assertFormSetError</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">formset</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">form_index</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">field</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">errors</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">msg_prefix</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">''</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.SimpleTestCase.assertFormSetError\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>断言 <code class=\"docutils literal notranslate\"><span class=\"pre\">formset</span></code> 在渲染时，会引发所提供的错误列表。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">formset</span></code> 是一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">FormSet</span></code> 实例。表单集必须是已绑定的，但不一定要经过验证（<code class=\"docutils literal notranslate\"><span class=\"pre\">assertFormSetError()</span></code> 会自动在表单集上调用 <code class=\"docutils literal notranslate\"><span class=\"pre\">full_clean()</span></code>）。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">form_index</span></code> 是在 <code class=\"docutils literal notranslate\"><span class=\"pre\">FormSet</span></code> 中的表单编号（从 0 开始）。使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">form_index=None</span></code> 来检查表单集的非表单错误，即在调用 <code class=\"docutils literal notranslate\"><span class=\"pre\">formset.non_form_errors()</span></code> 时获取的错误。在这种情况下，你还必须使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">field=None</span></code>。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">field</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">errors</span></code> 的含义与 <code class=\"docutils literal notranslate\"><span class=\"pre\">assertFormError()</span></code> 的参数相同。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.SimpleTestCase.assertContains\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">SimpleTestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">assertContains</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">response</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">text</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">count</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">status_code</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">200</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">msg_prefix</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">''</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">html</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">False</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.SimpleTestCase.assertContains\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>断言一个生成的 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/request-response/#django.http.HttpResponse\" title=\"django.http.HttpResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">response</span></code></a> 具有给定的 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/request-response/#django.http.HttpResponse.status_code\" title=\"django.http.HttpResponse.status_code\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">status_code</span></code></a>，并且 <code class=\"docutils literal notranslate\"><span class=\"pre\">text</span></code> 出现在它的 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/request-response/#django.http.HttpResponse.content\" title=\"django.http.HttpResponse.content\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">content</span></code></a> 中。如果提供了 <code class=\"docutils literal notranslate\"><span class=\"pre\">count</span></code>，则 <code class=\"docutils literal notranslate\"><span class=\"pre\">text</span></code> 必须在响应中精确出现 <code class=\"docutils literal notranslate\"><span class=\"pre\">count</span></code> 次。</p>\n<p>将 <code class=\"docutils literal notranslate\"><span class=\"pre\">html</span></code> 设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>，将 <code class=\"docutils literal notranslate\"><span class=\"pre\">text</span></code> 作为 HTML 处理。与响应内容的比较将基于 HTML 语义，而不是逐个字符的平等。在大多数情况下，空格会被忽略，属性排序并不重要。详见 <a class=\"reference internal\" href=\"#django.test.SimpleTestCase.assertHTMLEqual\" title=\"django.test.SimpleTestCase.assertHTMLEqual\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">assertHTMLEqual()</span></code></a>。</p>\n<aside class=\"version-note version-changed\" data-version=\"5.1\">\n<p class=\"version-note-title\">Changed in Django 5.1</p><p>在旧版本中，错误消息不包含响应内容。</p>\n</aside>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.SimpleTestCase.assertNotContains\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">SimpleTestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">assertNotContains</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">response</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">text</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">status_code</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">200</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">msg_prefix</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">''</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">html</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">False</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.SimpleTestCase.assertNotContains\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>断言一个生成的 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/request-response/#django.http.HttpResponse\" title=\"django.http.HttpResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">response</span></code></a> 具有给定的 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/request-response/#django.http.HttpResponse.status_code\" title=\"django.http.HttpResponse.status_code\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">status_code</span></code></a>，并且 <code class=\"docutils literal notranslate\"><span class=\"pre\">text</span></code> <em>不</em> 出现在它的 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/request-response/#django.http.HttpResponse.content\" title=\"django.http.HttpResponse.content\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">content</span></code></a> 中。</p>\n<p>将 <code class=\"docutils literal notranslate\"><span class=\"pre\">html</span></code> 设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>，将 <code class=\"docutils literal notranslate\"><span class=\"pre\">text</span></code> 作为 HTML 处理。与响应内容的比较将基于 HTML 语义，而不是逐个字符的平等。在大多数情况下，空格会被忽略，属性排序并不重要。详见 <a class=\"reference internal\" href=\"#django.test.SimpleTestCase.assertHTMLEqual\" title=\"django.test.SimpleTestCase.assertHTMLEqual\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">assertHTMLEqual()</span></code></a>。</p>\n<aside class=\"version-note version-changed\" data-version=\"5.1\">\n<p class=\"version-note-title\">Changed in Django 5.1</p><p>在旧版本中，错误消息不包含响应内容。</p>\n</aside>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.SimpleTestCase.assertTemplateUsed\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">SimpleTestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">assertTemplateUsed</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">response</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">template_name</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">msg_prefix</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">''</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">count</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.SimpleTestCase.assertTemplateUsed\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>断言给定名称的模板被用于渲染响应。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">response</span></code> 必须是由 <a class=\"reference internal\" href=\"#django.test.Response\" title=\"django.test.Response\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">test</span> <span class=\"pre\">client</span></code></a> 返回的响应实例。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">template_name``应当是一个字符串，如</span></code>'admin/index.html'<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">count</span></code> 参数是一个整数，表示模板应该被渲染的次数。默认值是 <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code>，表示模板应该被渲染一次或多次。</p>\n<p>你可以把它作为一个上下文管理器，比如：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">with</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertTemplateUsed</span><span class=\"p\">(</span><span class=\"s2\">&quot;index.html&quot;</span><span class=\"p\">):</span>\n    <span class=\"n\">render_to_string</span><span class=\"p\">(</span><span class=\"s2\">&quot;index.html&quot;</span><span class=\"p\">)</span>\n<span class=\"k\">with</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertTemplateUsed</span><span class=\"p\">(</span><span class=\"n\">template_name</span><span class=\"o\">=</span><span class=\"s2\">&quot;index.html&quot;</span><span class=\"p\">):</span>\n    <span class=\"n\">render_to_string</span><span class=\"p\">(</span><span class=\"s2\">&quot;index.html&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.SimpleTestCase.assertTemplateNotUsed\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">SimpleTestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">assertTemplateNotUsed</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">response</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">template_name</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">msg_prefix</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">''</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.SimpleTestCase.assertTemplateNotUsed\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>断言给定名称的模板在渲染响应时 <em>没有</em> 被使用。</p>\n<p>你可以用 <a class=\"reference internal\" href=\"#django.test.SimpleTestCase.assertTemplateUsed\" title=\"django.test.SimpleTestCase.assertTemplateUsed\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">assertTemplateUsed()</span></code></a> 一样的方式将其作为上下文管理器。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.SimpleTestCase.assertURLEqual\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">SimpleTestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">assertURLEqual</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">url1</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">url2</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">msg_prefix</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">''</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.SimpleTestCase.assertURLEqual\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>断言两个 URL 是相同的，忽略查询字符串参数的顺序，但同名参数除外。例如，<code class=\"docutils literal notranslate\"><span class=\"pre\">/path/?x=1&amp;y=2</span></code> 等于 <code class=\"docutils literal notranslate\"><span class=\"pre\">/path/?y=2&amp;x=1</span></code>，但 <code class=\"docutils literal notranslate\"><span class=\"pre\">/path/?a=1&amp;a=2</span></code> 不等于 <code class=\"docutils literal notranslate\"><span class=\"pre\">/path/?a=2&amp;a=1</span></code>。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.SimpleTestCase.assertRedirects\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">SimpleTestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">assertRedirects</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">response</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">expected_url</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">status_code</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">302</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">target_status_code</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">200</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">msg_prefix</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">''</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">fetch_redirect_response</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">True</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.SimpleTestCase.assertRedirects\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>断言返回的 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/request-response/#django.http.HttpResponse\" title=\"django.http.HttpResponse\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">response</span></code></a> 具有 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/request-response/#django.http.HttpResponse.status_code\" title=\"django.http.HttpResponse.status_code\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">status_code</span></code></a> 重定向状态，重定向到 <code class=\"docutils literal notranslate\"><span class=\"pre\">expected_url</span></code> （包括任何 <code class=\"docutils literal notranslate\"><span class=\"pre\">GET</span></code> 数据），并且最终页面以 <code class=\"docutils literal notranslate\"><span class=\"pre\">target_status_code</span></code> 接收到。</p>\n<p>如果你的请求使用了 <code class=\"docutils literal notranslate\"><span class=\"pre\">follow</span></code> 参数，<code class=\"docutils literal notranslate\"><span class=\"pre\">expected_url</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">target_status_code</span></code> 将是重定向链最后一点的网址和状态码。</p>\n<p>如果 <code class=\"docutils literal notranslate\"><span class=\"pre\">fetch_redirect_response</span></code> 为 <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code>，则最终页面不会被加载。由于测试客户端不能获取外部 URL，所以如果 <code class=\"docutils literal notranslate\"><span class=\"pre\">expected_url</span></code> 不是 Django 应用的一部分，这一点就特别有用。</p>\n<p>在两个 URL 之间进行比较时，可以正确处理协议。如果在我们被重定向到的位置没有指定任何协议，则使用原始请求的协议。如果存在，<code class=\"docutils literal notranslate\"><span class=\"pre\">expected_url</span></code> 中的协议就是用来进行比较的。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.SimpleTestCase.assertHTMLEqual\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">SimpleTestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">assertHTMLEqual</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">html1</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">html2</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">msg</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.SimpleTestCase.assertHTMLEqual\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>断言字符串 <code class=\"docutils literal notranslate\"><span class=\"pre\">html1</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">html2</span></code> 相等。比较是基于 HTML 语义的。比较时考虑到以下因素：</p>\n<ul class=\"simple\">\n<li><p>HTML 标签前后的空白会被忽略。</p></li>\n<li><p>所有类型的空白都被认为是等价的。</p></li>\n<li><p>所有打开的标签都是隐式关闭的，例如当周围的标签关闭或 HTML 文档结束时。</p></li>\n<li><p>空标签相当于其自动闭合版。</p></li>\n<li><p>HTML 元素的属性排序并不重要。</p></li>\n<li><p>没有参数的布尔属性（例如 <code class=\"docutils literal notranslate\"><span class=\"pre\">checked</span></code>）等于名称和值相等的属性（请参见示例）。</p></li>\n<li><p>引用同一字符的文本、字符引用和实体引用是等价的。</p></li>\n</ul>\n<p>下面的例子是有效的测试，并且没有引起任何 <code class=\"docutils literal notranslate\"><span class=\"pre\">AssertionError</span></code>:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertHTMLEqual</span><span class=\"p\">(</span>\n    <span class=\"s2\">&quot;&lt;p&gt;Hello &lt;b&gt;&amp;#x27;world&amp;#x27;!&lt;/p&gt;&quot;</span><span class=\"p\">,</span>\n<span class=\"w\">    </span><span class=\"sd\">&quot;&quot;&quot;&lt;p&gt;</span>\n<span class=\"sd\">        Hello   &lt;b&gt;&amp;#39;world&amp;#39;! &lt;/b&gt;</span>\n<span class=\"sd\">    &lt;/p&gt;&quot;&quot;&quot;</span><span class=\"p\">,</span>\n<span class=\"p\">)</span>\n<span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertHTMLEqual</span><span class=\"p\">(</span>\n    <span class=\"s1\">&#39;&lt;input type=&quot;checkbox&quot; checked=&quot;checked&quot; id=&quot;id_accept_terms&quot; /&gt;&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;&lt;input id=&quot;id_accept_terms&quot; type=&quot;checkbox&quot; checked&gt;&#39;</span><span class=\"p\">,</span>\n<span class=\"p\">)</span>\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">html1</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">html2</span></code> 必须包含 HTML。如果其中一个不能被解析，将产生一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">AssertionError</span></code>。</p>\n<p>错误时的输出可以用 <code class=\"docutils literal notranslate\"><span class=\"pre\">msg</span></code> 参数自定义。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.SimpleTestCase.assertHTMLNotEqual\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">SimpleTestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">assertHTMLNotEqual</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">html1</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">html2</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">msg</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.SimpleTestCase.assertHTMLNotEqual\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>断言字符串 <code class=\"docutils literal notranslate\"><span class=\"pre\">html1</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">html2</span></code> <em>不</em> 相等。比较是基于 HTML 语义的。详见 <a class=\"reference internal\" href=\"#django.test.SimpleTestCase.assertHTMLEqual\" title=\"django.test.SimpleTestCase.assertHTMLEqual\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">assertHTMLEqual()</span></code></a>。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">html1</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">html2</span></code> 必须包含 HTML。如果其中一个不能被解析，将产生一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">AssertionError</span></code>。</p>\n<p>错误时的输出可以用 <code class=\"docutils literal notranslate\"><span class=\"pre\">msg</span></code> 参数自定义。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.SimpleTestCase.assertXMLEqual\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">SimpleTestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">assertXMLEqual</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">xml1</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">xml2</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">msg</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.SimpleTestCase.assertXMLEqual\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>断言字符串 <code class=\"docutils literal notranslate\"><span class=\"pre\">xml1</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">xml2</span></code> 相等。比较是基于 XML 语义的。与 <a class=\"reference internal\" href=\"#django.test.SimpleTestCase.assertHTMLEqual\" title=\"django.test.SimpleTestCase.assertHTMLEqual\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">assertHTMLEqual()</span></code></a> 类似，比较是在解析内容上进行的，因此只考虑语义差异，而不是语法差异。当任何参数中传递了无效的 XML 时，即使两个字符串相同，也总是会引发一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">AssertionError</span></code>。</p>\n<p>忽略 XML 声明、文档类型、处理指令和注释。只有根元素和它的子元素被比较。</p>\n<p>错误时的输出可以用 <code class=\"docutils literal notranslate\"><span class=\"pre\">msg</span></code> 参数自定义。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.SimpleTestCase.assertXMLNotEqual\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">SimpleTestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">assertXMLNotEqual</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">xml1</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">xml2</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">msg</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.SimpleTestCase.assertXMLNotEqual\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>断言字符串 <code class=\"docutils literal notranslate\"><span class=\"pre\">xml1</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">xml2</span></code> <em>不</em> 相等。比较是基于 XML 语义的，参见 <a class=\"reference internal\" href=\"#django.test.SimpleTestCase.assertXMLEqual\" title=\"django.test.SimpleTestCase.assertXMLEqual\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">assertXMLEqual()</span></code></a>。</p>\n<p>错误时的输出可以用 <code class=\"docutils literal notranslate\"><span class=\"pre\">msg</span></code> 参数自定义。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.SimpleTestCase.assertInHTML\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">SimpleTestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">assertInHTML</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">needle</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">haystack</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">count</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">msg_prefix</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">''</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.SimpleTestCase.assertInHTML\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>断言 HTML 片段 <code class=\"docutils literal notranslate\"><span class=\"pre\">needle</span></code> 在 <code class=\"docutils literal notranslate\"><span class=\"pre\">haystack</span></code> 中出现一次。</p>\n<p>如果指定了 <code class=\"docutils literal notranslate\"><span class=\"pre\">count</span></code> 整数参数，则将严格核查 <code class=\"docutils literal notranslate\"><span class=\"pre\">needle</span></code> 的出现次数。</p>\n<p>在大多数情况下，空白是被忽略的，属性排序并不重要。参见 <a class=\"reference internal\" href=\"#django.test.SimpleTestCase.assertHTMLEqual\" title=\"django.test.SimpleTestCase.assertHTMLEqual\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">assertHTMLEqual()</span></code></a> 以了解更多细节。</p>\n<aside class=\"version-note version-changed\" data-version=\"5.1\">\n<p class=\"version-note-title\">Changed in Django 5.1</p><p>在旧版本中，错误消息不包含 <code class=\"docutils literal notranslate\"><span class=\"pre\">haystack</span></code>。</p>\n</aside>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.SimpleTestCase.assertNotInHTML\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">SimpleTestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">assertNotInHTML</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">needle</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">haystack</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">msg_prefix</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">''</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.SimpleTestCase.assertNotInHTML\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><aside class=\"version-note version-added\" data-version=\"5.1\">\n<p class=\"version-note-title\">New in Django 5.1</p></aside>\n<p>断言 HTML 片段 <code class=\"docutils literal notranslate\"><span class=\"pre\">needle</span></code> <em>不</em> 包含在 <code class=\"docutils literal notranslate\"><span class=\"pre\">haystack</span></code> 中。</p>\n<p>在大多数情况下，空白是被忽略的，属性排序并不重要。参见 <a class=\"reference internal\" href=\"#django.test.SimpleTestCase.assertHTMLEqual\" title=\"django.test.SimpleTestCase.assertHTMLEqual\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">assertHTMLEqual()</span></code></a> 以了解更多细节。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.SimpleTestCase.assertJSONEqual\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">SimpleTestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">assertJSONEqual</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">raw</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">expected_data</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">msg</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.SimpleTestCase.assertJSONEqual\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>断言 JSON 片段 <code class=\"docutils literal notranslate\"><span class=\"pre\">raw</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">expected_data</span></code> 相等。通常的 JSON 非显性空格规则适用，因为重量级是委托给 <a class=\"reference external\" href=\"https://docs.python.org/3/library/json.html#module-json\" title=\"(in Python v3.14)\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">json</span></code></a> 库的。</p>\n<p>错误时的输出可以用 <code class=\"docutils literal notranslate\"><span class=\"pre\">msg</span></code> 参数自定义。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.SimpleTestCase.assertJSONNotEqual\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">SimpleTestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">assertJSONNotEqual</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">raw</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">expected_data</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">msg</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.SimpleTestCase.assertJSONNotEqual\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>断言 JSON 片段 <code class=\"docutils literal notranslate\"><span class=\"pre\">raw</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">expected_data</span></code> <em>不</em> 相等。详见 <a class=\"reference internal\" href=\"#django.test.SimpleTestCase.assertJSONEqual\" title=\"django.test.SimpleTestCase.assertJSONEqual\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">assertJSONEqual()</span></code></a>。</p>\n<p>错误时的输出可以用 <code class=\"docutils literal notranslate\"><span class=\"pre\">msg</span></code> 参数自定义。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.TransactionTestCase.assertQuerySetEqual\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">TransactionTestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">assertQuerySetEqual</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">qs</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">values</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">transform</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">ordered</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">True</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">msg</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.TransactionTestCase.assertQuerySetEqual\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>断言一个查询集 <code class=\"docutils literal notranslate\"><span class=\"pre\">qs</span></code> 与一个特定的可迭代对象 <code class=\"docutils literal notranslate\"><span class=\"pre\">values</span></code> 的值匹配。</p>\n<p>如果提供了 <code class=\"docutils literal notranslate\"><span class=\"pre\">transform</span></code>，<code class=\"docutils literal notranslate\"><span class=\"pre\">values</span></code> 将与应用 <code class=\"docutils literal notranslate\"><span class=\"pre\">transform</span></code> 于 <code class=\"docutils literal notranslate\"><span class=\"pre\">qs</span></code> 而产生的列表中每个成员进行比较。</p>\n<p>默认情况下，比较也是依赖于顺序的。如果 <code class=\"docutils literal notranslate\"><span class=\"pre\">qs</span></code> 不提供隐式排序，你可以将 <code class=\"docutils literal notranslate\"><span class=\"pre\">ordered</span></code> 参数设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code>，这将使比较变成 <code class=\"docutils literal notranslate\"><span class=\"pre\">collections.Counter</span></code> 比较。如果顺序是未定义的（如果给定的 <code class=\"docutils literal notranslate\"><span class=\"pre\">qs</span></code> 不是有序的，并且比较的对象是一个以上的有序值），会产生一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">ValueError</span></code>。</p>\n<p>错误时的输出可以用 <code class=\"docutils literal notranslate\"><span class=\"pre\">msg</span></code> 参数自定义。</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.test.TransactionTestCase.assertNumQueries\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">TransactionTestCase.</span></span><span class=\"sig-name descname\"><span class=\"pre\">assertNumQueries</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">num</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">func</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">*</span></span><span class=\"n\"><span class=\"pre\">args</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">kwargs</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.TransactionTestCase.assertNumQueries\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>断言当 <code class=\"docutils literal notranslate\"><span class=\"pre\">func</span></code> 与 <code class=\"docutils literal notranslate\"><span class=\"pre\">*args</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">**kwargs</span></code> 一起调用时，会执行 <code class=\"docutils literal notranslate\"><span class=\"pre\">num</span></code> 次数据库查询。</p>\n<p>如果 <code class=\"docutils literal notranslate\"><span class=\"pre\">kwargs</span></code> 中存在 <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;using&quot;</span></code> 键，则使用该键作为数据库别名，以检查查询次数：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertNumQueries</span><span class=\"p\">(</span><span class=\"mi\">7</span><span class=\"p\">,</span> <span class=\"n\">my_function</span><span class=\"p\">,</span> <span class=\"n\">using</span><span class=\"o\">=</span><span class=\"s2\">&quot;non_default_db&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>如果你想调用一个带有 <code class=\"docutils literal notranslate\"><span class=\"pre\">using</span></code> 参数的函数，你可以通过用 <code class=\"docutils literal notranslate\"><span class=\"pre\">lambda</span></code> 包装调用来增加一个额外的参数：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertNumQueries</span><span class=\"p\">(</span><span class=\"mi\">7</span><span class=\"p\">,</span> <span class=\"k\">lambda</span><span class=\"p\">:</span> <span class=\"n\">my_function</span><span class=\"p\">(</span><span class=\"n\">using</span><span class=\"o\">=</span><span class=\"mi\">7</span><span class=\"p\">))</span>\n</code></pre></div>\n<p>你也可以用它作为上下文管理器:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">with</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertNumQueries</span><span class=\"p\">(</span><span class=\"mi\">2</span><span class=\"p\">):</span>\n    <span class=\"n\">Person</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">create</span><span class=\"p\">(</span><span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s2\">&quot;Aaron&quot;</span><span class=\"p\">)</span>\n    <span class=\"n\">Person</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">create</span><span class=\"p\">(</span><span class=\"n\">name</span><span class=\"o\">=</span><span class=\"s2\">&quot;Daniel&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n</dd></dl>\n\n</section>\n<section id=\"tagging-tests\">\n<span id=\"topics-tagging-tests\"></span><h3>标记测试<a class=\"heading-anchor\" href=\"#tagging-tests\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>你可以给你的测试打上标签，这样你就可以轻松地运行一个特定的子集。例如，你可以标记快速或慢速测试：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.test</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">tag</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">SampleTestCase</span><span class=\"p\">(</span><span class=\"n\">TestCase</span><span class=\"p\">):</span>\n    <span class=\"nd\">@tag</span><span class=\"p\">(</span><span class=\"s2\">&quot;fast&quot;</span><span class=\"p\">)</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_fast</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span> <span class=\"o\">...</span>\n\n    <span class=\"nd\">@tag</span><span class=\"p\">(</span><span class=\"s2\">&quot;slow&quot;</span><span class=\"p\">)</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_slow</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span> <span class=\"o\">...</span>\n\n    <span class=\"nd\">@tag</span><span class=\"p\">(</span><span class=\"s2\">&quot;slow&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;core&quot;</span><span class=\"p\">)</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_slow_but_core</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span> <span class=\"o\">...</span>\n</code></pre></div>\n<p>你还可以给一个测试用例类打上标签：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"nd\">@tag</span><span class=\"p\">(</span><span class=\"s2\">&quot;slow&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;core&quot;</span><span class=\"p\">)</span>\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">SampleTestCase</span><span class=\"p\">(</span><span class=\"n\">TestCase</span><span class=\"p\">):</span> <span class=\"o\">...</span>\n</code></pre></div>\n<p>子类从超类继承标签，方法从其类继承标签。如：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"nd\">@tag</span><span class=\"p\">(</span><span class=\"s2\">&quot;foo&quot;</span><span class=\"p\">)</span>\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">SampleTestCaseChild</span><span class=\"p\">(</span><span class=\"n\">SampleTestCase</span><span class=\"p\">):</span>\n    <span class=\"nd\">@tag</span><span class=\"p\">(</span><span class=\"s2\">&quot;bar&quot;</span><span class=\"p\">)</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span> <span class=\"o\">...</span>\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">SampleTestCaseChild.test</span></code> 将用 <code class=\"docutils literal notranslate\"><span class=\"pre\">'slow'</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">'core'</span></code>、<code class=\"docutils literal notranslate\"><span class=\"pre\">'bar'</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">'foo'</span></code> 来标注。</p>\n<p>然后你可以选择要运行的测试。例如，只运行快速测试：</p>\n<div class=\"console\" data-console><div class=\"console-panel\" data-platform=\"unix\"><p class=\"console-label\" id=\"console-2-unix-label\">Linux / macOS</p><div class=\"code-block\" data-language=\"console\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code><span class=\"gp\">$ </span>./manage.py<span class=\"w\"> </span><span class=\"nb\">test</span><span class=\"w\"> </span>--tag<span class=\"o\">=</span>fast\n</code></pre></div>\n</div><div class=\"console-panel\" data-platform=\"windows\"><p class=\"console-label\" id=\"console-2-windows-label\">Windows</p><div class=\"code-block\" data-language=\"doscon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Windows</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Windows shell\"><code><span class=\"gp\">...\\&gt;</span> manage.py test --tag=fast\n</code></pre></div></div></div>\n<p>或者运行快速测试和核心测试（即使它很慢）：</p>\n<div class=\"console\" data-console><div class=\"console-panel\" data-platform=\"unix\"><p class=\"console-label\" id=\"console-3-unix-label\">Linux / macOS</p><div class=\"code-block\" data-language=\"console\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code><span class=\"gp\">$ </span>./manage.py<span class=\"w\"> </span><span class=\"nb\">test</span><span class=\"w\"> </span>--tag<span class=\"o\">=</span>fast<span class=\"w\"> </span>--tag<span class=\"o\">=</span>core\n</code></pre></div>\n</div><div class=\"console-panel\" data-platform=\"windows\"><p class=\"console-label\" id=\"console-3-windows-label\">Windows</p><div class=\"code-block\" data-language=\"doscon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Windows</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Windows shell\"><code><span class=\"gp\">...\\&gt;</span> manage.py test --tag=fast --tag=core\n</code></pre></div></div></div>\n<p>你也可以通过标签来排除测试。如果要运行不慢的核心测试：</p>\n<div class=\"console\" data-console><div class=\"console-panel\" data-platform=\"unix\"><p class=\"console-label\" id=\"console-4-unix-label\">Linux / macOS</p><div class=\"code-block\" data-language=\"console\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code><span class=\"gp\">$ </span>./manage.py<span class=\"w\"> </span><span class=\"nb\">test</span><span class=\"w\"> </span>--tag<span class=\"o\">=</span>core<span class=\"w\"> </span>--exclude-tag<span class=\"o\">=</span>slow\n</code></pre></div>\n</div><div class=\"console-panel\" data-platform=\"windows\"><p class=\"console-label\" id=\"console-4-windows-label\">Windows</p><div class=\"code-block\" data-language=\"doscon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Windows</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Windows shell\"><code><span class=\"gp\">...\\&gt;</span> manage.py test --tag=core --exclude-tag=slow\n</code></pre></div></div></div>\n<p><code class=\"xref std std-option docutils literal notranslate\"><span class=\"pre\">test</span> <span class=\"pre\">--exclud-tag</span></code> 优先于 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/django-admin/#cmdoption-test-tag\"><code class=\"xref std std-option docutils literal notranslate\"><span class=\"pre\">test</span> <span class=\"pre\">--tag</span></code></a>，所以如果一个测试有两个标签，你选择了其中一个而排除了另一个，测试就不会被运行。</p>\n</section>\n</section>\n<section id=\"testing-asynchronous-code\">\n<span id=\"async-tests\"></span><h2>测试异步代码<a class=\"heading-anchor\" href=\"#testing-asynchronous-code\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>如果你只是想测试异步视图的输出，标准测试客户端将在自己的异步循环中运行它们，而不需要你做任何额外的工作。</p>\n<p>但是，如果你想为 Django 项目编写完全异步的测试，你需要考虑到几个问题。</p>\n<p>首先，你的测试必须是测试类上的 <code class=\"docutils literal notranslate\"><span class=\"pre\">async</span> <span class=\"pre\">def</span></code> 方法（为了给它们一个异步的上下文）。Django 会自动检测到任何 <code class=\"docutils literal notranslate\"><span class=\"pre\">async</span> <span class=\"pre\">def</span></code> 的测试，并将它们封装在自己的事件循环中运行。</p>\n<p>如果你从一个异步函数进行测试，你也必须使用异步测试客户端。这在任何测试中都可以作为 <code class=\"docutils literal notranslate\"><span class=\"pre\">django.test.AsyncClient</span></code> 或 <code class=\"docutils literal notranslate\"><span class=\"pre\">self.async_client</span></code> 使用。</p>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.test.AsyncClient\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">AsyncClient</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">enforce_csrf_checks</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">False</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">raise_request_exception</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">True</span></span></em>, <em class=\"sig-param\"><span class=\"keyword-only-separator o\"><abbr title=\"Keyword-only parameters separator (PEP 3102)\"><span class=\"pre\">*</span></abbr></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">headers</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">query_params</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">defaults</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.AsyncClient\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">AsyncClient</span></code> 具有与同步（普通）测试客户端相同的方法和签名，除了以下异常情况：</p>\n<ul>\n<li><p>在初始化中，<code class=\"docutils literal notranslate\"><span class=\"pre\">defaults</span></code> 中的任意关键字参数都直接添加到 ASGI 作用域中。</p></li>\n<li><p>作为 <code class=\"docutils literal notranslate\"><span class=\"pre\">extra</span></code> 关键字参数传递的头部不应该具有同步客户端所需的 <code class=\"docutils literal notranslate\"><span class=\"pre\">HTTP_</span></code> 前缀（参见 <a class=\"reference internal\" href=\"#django.test.Client.get\" title=\"django.test.Client.get\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">Client.get()</span></code></a>）。例如，以下是如何设置 HTTP <code class=\"docutils literal notranslate\"><span class=\"pre\">Accept</span></code> 头部的方法：</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">c</span> <span class=\"o\">=</span> <span class=\"n\">AsyncClient</span><span class=\"p\">()</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">c</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s2\">&quot;/customers/details/&quot;</span><span class=\"p\">,</span> <span class=\"p\">{</span><span class=\"s2\">&quot;name&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;fred&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;age&quot;</span><span class=\"p\">:</span> <span class=\"mi\">7</span><span class=\"p\">},</span> <span class=\"n\">ACCEPT</span><span class=\"o\">=</span><span class=\"s2\">&quot;application/json&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n</li>\n</ul>\n<aside class=\"version-note version-changed\" data-version=\"5.1\">\n<p class=\"version-note-title\">Changed in Django 5.1</p><p>增加了 <code class=\"docutils literal notranslate\"><span class=\"pre\">query_params</span></code> 参数。</p>\n</aside>\n<p>使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">AsyncClient</span></code> 任何提出请求的方法都必须被等待：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">async</span> <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_my_thing</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n    <span class=\"n\">response</span> <span class=\"o\">=</span> <span class=\"k\">await</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">async_client</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s2\">&quot;/some-url/&quot;</span><span class=\"p\">)</span>\n    <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertEqual</span><span class=\"p\">(</span><span class=\"n\">response</span><span class=\"o\">.</span><span class=\"n\">status_code</span><span class=\"p\">,</span> <span class=\"mi\">200</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>异步客户端也可以调用同步视图；它通过 Django 的 <a class=\"reference internal\" href=\"/zh-hans/5.2/topics/async/\"><span class=\"doc\">异步请求路径</span></a> 运行，它支持这两种方式。任何通过 <code class=\"docutils literal notranslate\"><span class=\"pre\">AsyncClient</span></code> 调用的视图都会得到一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">ASGIRequest</span></code> 对象作为它的 <code class=\"docutils literal notranslate\"><span class=\"pre\">request</span></code>，而不是普通客户端创建的 <code class=\"docutils literal notranslate\"><span class=\"pre\">WSGIRequest</span></code>。</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Warning</p>\n<p>如果你使用的是测试装饰器，它们必须是异步兼容的，以确保它们正确工作。Django 内置的装饰器会正常工作，但第三方的装饰器可能会出现无法执行的情况（它们会“包装”执行流程中错误的部分，而不是你的测试）。</p>\n<p>如果你需要使用这些装饰器，那么你应该用 <a class=\"reference internal\" href=\"/zh-hans/5.2/topics/async/#asgiref.sync.async_to_sync\" title=\"asgiref.sync.async_to_sync\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">async_to_sync()</span></code></a> 来装饰你的测试方法:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">asgiref.sync</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">async_to_sync</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.test</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">TestCase</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MyTests</span><span class=\"p\">(</span><span class=\"n\">TestCase</span><span class=\"p\">):</span>\n    <span class=\"nd\">@mock</span><span class=\"o\">.</span><span class=\"n\">patch</span><span class=\"p\">(</span><span class=\"o\">...</span><span class=\"p\">)</span>\n    <span class=\"nd\">@async_to_sync</span>\n    <span class=\"k\">async</span> <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_my_thing</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span> <span class=\"o\">...</span>\n</code></pre></div>\n</aside>\n</section>\n<section id=\"email-services\">\n<span id=\"topics-testing-email\"></span><h2>邮件服务<a class=\"heading-anchor\" href=\"#email-services\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>如果你的任何 Django 视图使用 <a class=\"reference internal\" href=\"/zh-hans/5.2/topics/email/\"><span class=\"doc\">Django 的邮件功能</span></a> 发送电子邮件，你可能不想每次使用该视图运行测试时都发送电子邮件。出于这个原因，Django 的测试运行器会自动将所有 Django 发送的邮件重定向到一个虚拟的发件箱。这让你可以测试发送邮件的每一个方面——从发送邮件的数量到每封邮件的内容——而不用实际发送邮件。</p>\n<p>测试运行器通过透明的将正常的邮件后端替换为测试后端来实现。（别担心——这对 Django 之外的其他邮件发送器没有影响，比如你机器的邮件服务器，如果你正在运行一个的话。）</p>\n<dl class=\"py data\">\n<dt class=\"sig sig-object py\" id=\"django.core.mail.django.core.mail.outbox\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">django.core.mail.</span></span><span class=\"sig-name descname\"><span class=\"pre\">outbox</span></span><a class=\"heading-anchor\" href=\"#django.core.mail.django.core.mail.outbox\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>在测试运行过程中，每一封发出的邮件都会保存在 <code class=\"docutils literal notranslate\"><span class=\"pre\">django.core.mail.outbox</span></code> 中。这是所有已经发送的 <a class=\"reference internal\" href=\"/zh-hans/5.2/topics/email/#django.core.mail.EmailMessage\" title=\"django.core.mail.EmailMessage\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">EmailMessage</span></code></a> 实例的列表。 <code class=\"docutils literal notranslate\"><span class=\"pre\">outbox</span></code> 属性是一个特殊的属性，只有在使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">locmem</span></code> 邮件后端时才会创建。它通常不作为 <a class=\"reference internal\" href=\"/zh-hans/5.2/topics/email/#module-django.core.mail\" title=\"django.core.mail: Helpers to easily send email.\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.core.mail</span></code></a> 模块的一部分存在，你也不能直接导入它。下面的代码展示了如何正确访问这个属性。</p>\n<p>下面是一个检查 <code class=\"docutils literal notranslate\"><span class=\"pre\">django.core.mail.outbox</span></code> 长度和内容的测试示例：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.core</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">mail</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.test</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">TestCase</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">EmailTest</span><span class=\"p\">(</span><span class=\"n\">TestCase</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_send_email</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Send message.</span>\n        <span class=\"n\">mail</span><span class=\"o\">.</span><span class=\"n\">send_mail</span><span class=\"p\">(</span>\n            <span class=\"s2\">&quot;Subject here&quot;</span><span class=\"p\">,</span>\n            <span class=\"s2\">&quot;Here is the message.&quot;</span><span class=\"p\">,</span>\n            <span class=\"s2\">&quot;from@example.com&quot;</span><span class=\"p\">,</span>\n            <span class=\"p\">[</span><span class=\"s2\">&quot;to@example.com&quot;</span><span class=\"p\">],</span>\n            <span class=\"n\">fail_silently</span><span class=\"o\">=</span><span class=\"kc\">False</span><span class=\"p\">,</span>\n        <span class=\"p\">)</span>\n\n        <span class=\"c1\"># Test that one message has been sent.</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertEqual</span><span class=\"p\">(</span><span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"n\">mail</span><span class=\"o\">.</span><span class=\"n\">outbox</span><span class=\"p\">),</span> <span class=\"mi\">1</span><span class=\"p\">)</span>\n\n        <span class=\"c1\"># Verify that the subject of the first message is correct.</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertEqual</span><span class=\"p\">(</span><span class=\"n\">mail</span><span class=\"o\">.</span><span class=\"n\">outbox</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"n\">subject</span><span class=\"p\">,</span> <span class=\"s2\">&quot;Subject here&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>正如 <a class=\"reference internal\" href=\"#emptying-test-outbox\"><span class=\"std std-ref\">之前</span></a>，在 Django <code class=\"docutils literal notranslate\"><span class=\"pre\">*TestCase</span></code> 中的每个测试开始时，测试发件箱都会被清空。要手动清空发件箱，将空列表分配给 <code class=\"docutils literal notranslate\"><span class=\"pre\">mail.outbox</span></code>：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.core</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">mail</span>\n\n<span class=\"c1\"># Empty the test outbox</span>\n<span class=\"n\">mail</span><span class=\"o\">.</span><span class=\"n\">outbox</span> <span class=\"o\">=</span> <span class=\"p\">[]</span>\n</code></pre></div>\n</section>\n<section id=\"management-commands\">\n<span id=\"topics-testing-management-commands\"></span><h2>管理命令<a class=\"heading-anchor\" href=\"#management-commands\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>管理命令可以用 <a class=\"reference internal\" href=\"/zh-hans/5.2/ref/django-admin/#django.core.management.call_command\" title=\"django.core.management.call_command\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">call_command()</span></code></a> 函数来测试。输出可以重定向到 <code class=\"docutils literal notranslate\"><span class=\"pre\">StringIO</span></code> 实例中：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">io</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">StringIO</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.core.management</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">call_command</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.test</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">TestCase</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">ClosepollTest</span><span class=\"p\">(</span><span class=\"n\">TestCase</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_command_output</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"n\">out</span> <span class=\"o\">=</span> <span class=\"n\">StringIO</span><span class=\"p\">()</span>\n        <span class=\"n\">call_command</span><span class=\"p\">(</span><span class=\"s2\">&quot;closepoll&quot;</span><span class=\"p\">,</span> <span class=\"n\">poll_ids</span><span class=\"o\">=</span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"p\">],</span> <span class=\"n\">stdout</span><span class=\"o\">=</span><span class=\"n\">out</span><span class=\"p\">)</span>\n        <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">assertIn</span><span class=\"p\">(</span><span class=\"s1\">&#39;Successfully closed poll &quot;1&quot;&#39;</span><span class=\"p\">,</span> <span class=\"n\">out</span><span class=\"o\">.</span><span class=\"n\">getvalue</span><span class=\"p\">())</span>\n</code></pre></div>\n</section>\n<section id=\"skipping-tests\">\n<span id=\"id3\"></span><h2>忽略测试<a class=\"heading-anchor\" href=\"#skipping-tests\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>unittest 库提供了 <a class=\"reference external\" href=\"https://docs.python.org/3/library/unittest.html#unittest.skipIf\" title=\"(in Python v3.14)\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">&#64;skipIf</span></code></a> 和 <a class=\"reference external\" href=\"https://docs.python.org/3/library/unittest.html#unittest.skipUnless\" title=\"(in Python v3.14)\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">&#64;skipUnless</span></code></a> 装饰器，允许你跳过测试，如果你事先知道这些测试在某些条件下会失败。</p>\n<p>例如，如果你的测试需要一个特定的可选库才能成功，你可以用 <a class=\"reference external\" href=\"https://docs.python.org/3/library/unittest.html#unittest.skipIf\" title=\"(in Python v3.14)\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">&#64;skipIf</span></code></a> 来装饰测试用例。然后，测试运行器将报告测试没有被执行以及原因，而不是测试失败或完全省略测试。</p>\n<p>为了补充这些测试跳过行为，Django 提供了两个额外的跳过装饰器。这些装饰器不是测试一个通用的布尔值，而是检查数据库的能力，如果数据库不支持一个特定的命名特性，则跳过测试。</p>\n<p>装饰器使用一个字符串标识符来描述数据库特征。这个字符串对应于数据库连接特征类的属性。参见 <a class=\"extlink-source reference external\" href=\"https://github.com/django/django/blob/stable/5.2.x/django/db/backends/base/features.py\">django.db.backends.base.features.BaseDatabaseFeatures 类</a> 以获得可作为跳过测试基础的数据库特征的完整列表。</p>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.test.skipIfDBFeature\">\n<span class=\"sig-name descname\"><span class=\"pre\">skipIfDBFeature</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">*</span></span><span class=\"n\"><span class=\"pre\">feature_name_strings</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.skipIfDBFeature\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>如果支持某个命名的数据库功能，则跳过装饰测试或 <code class=\"docutils literal notranslate\"><span class=\"pre\">TestCase</span></code>。</p>\n<p>例如，如果数据库支持事务，下面的测试将不会被执行（例如，在PostgreSQL 下，它将 <em>不</em> 会运行，但在 MySQL 的 MyISAM 表下却可以）：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MyTests</span><span class=\"p\">(</span><span class=\"n\">TestCase</span><span class=\"p\">):</span>\n    <span class=\"nd\">@skipIfDBFeature</span><span class=\"p\">(</span><span class=\"s2\">&quot;supports_transactions&quot;</span><span class=\"p\">)</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_transaction_behavior</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"c1\"># ... conditional test code</span>\n        <span class=\"k\">pass</span>\n</code></pre></div>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.test.skipUnlessDBFeature\">\n<span class=\"sig-name descname\"><span class=\"pre\">skipUnlessDBFeature</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">*</span></span><span class=\"n\"><span class=\"pre\">feature_name_strings</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.test.skipUnlessDBFeature\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>如果 <em>不</em> 支持某个命名的数据库功能，则跳过装饰测试或 <code class=\"docutils literal notranslate\"><span class=\"pre\">TestCase</span></code>。</p>\n<p>例如，接下来的测试仅在支持事务的数据库下执行(如：可以是PostgreSQL，但不可以是使用MyISAM数据库引擎的MySQL):</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MyTests</span><span class=\"p\">(</span><span class=\"n\">TestCase</span><span class=\"p\">):</span>\n    <span class=\"nd\">@skipUnlessDBFeature</span><span class=\"p\">(</span><span class=\"s2\">&quot;supports_transactions&quot;</span><span class=\"p\">)</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">test_transaction_behavior</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"c1\"># ... conditional test code</span>\n        <span class=\"k\">pass</span>\n</code></pre></div>\n</section>","rootId":"testing-tools","toc":[{"title":"测试客户端","anchor":"the-test-client","children":[{"title":"概述和一个简单的例子","anchor":"overview-and-a-quick-example","children":[]},{"title":"发出请求","anchor":"making-requests","children":[]},{"title":"测试响应","anchor":"testing-responses","children":[]},{"title":"例外","anchor":"exceptions","children":[]},{"title":"持久状态","anchor":"persistent-state","children":[]},{"title":"设置语言","anchor":"setting-the-language","children":[]},{"title":"例如","anchor":"example","children":[]}]},{"title":"提供的测试用例类","anchor":"provided-test-case-classes","children":[{"title":"SimpleTestCase","anchor":"simpletestcase","children":[]},{"title":"TransactionTestCase","anchor":"transactiontestcase","children":[]},{"title":"TestCase","anchor":"testcase","children":[]},{"title":"LiveServerTestCase","anchor":"liveservertestcase","children":[]}]},{"title":"测试用例特性","anchor":"test-cases-features","children":[{"title":"默认测试客户端","anchor":"default-test-client","children":[]},{"title":"自定义测试客户端","anchor":"customizing-the-test-client","children":[]},{"title":"辅助工具加载","anchor":"fixture-loading","children":[]},{"title":"URLconf 配置","anchor":"urlconf-configuration","children":[]},{"title":"多数据库支持","anchor":"multi-database-support","children":[]},{"title":"覆盖配置","anchor":"overriding-settings","children":[]},{"title":"隔离应用程序","anchor":"isolating-apps","children":[]},{"title":"清空测试发件箱","anchor":"emptying-the-test-outbox","children":[]},{"title":"断言","anchor":"assertions","children":[]},{"title":"标记测试","anchor":"tagging-tests","children":[]}]},{"title":"测试异步代码","anchor":"testing-asynchronous-code","children":[]},{"title":"邮件服务","anchor":"email-services","children":[]},{"title":"管理命令","anchor":"management-commands","children":[]},{"title":"忽略测试","anchor":"skipping-tests","children":[]}],"breadcrumbs":[{"docname":"topics/index","title":"使用 Django","url":"/zh-hans/5.2/topics/"},{"docname":"topics/testing/index","title":"Django 中的测试","url":"/zh-hans/5.2/topics/testing/"}],"prev":{"docname":"topics/testing/overview","title":"编写并运行测试","url":"/zh-hans/5.2/topics/testing/overview/"},"next":{"docname":"topics/testing/advanced","title":"进阶测试主题","url":"/zh-hans/5.2/topics/testing/advanced/"},"formats":{"html":"/zh-hans/5.2/topics/testing/tools/","markdown":"/zh-hans/5.2/topics/testing/tools.md","json":"/zh-hans/5.2/topics/testing/tools.json"},"source":"https://github.com/django/django/blob/stable/5.2.x/docs/topics/testing/tools.txt","official":"https://docs.djangoproject.com/zh-hans/5.2/topics/testing/tools/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0"],"inLocales":["en","sv","zh-hans","ga","fr","ja","id","it","pt-br","ko","es","el","pl"]}