[pre-commit.ci lite] apply automatic fixes
This commit is contained in:
parent
b3ae3117f9
commit
3d83d8138c
102 changed files with 26790 additions and 26749 deletions
|
|
@ -5,7 +5,7 @@
|
|||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Working with the Shell — Flask Documentation (3.2.x)</title>
|
||||
<title>Testing Flask Applications — Flask Documentation (3.2.x)</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=6625fa76" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/flask.css?v=b87c8d14" />
|
||||
<script src="_static/documentation_options.js?v=56528222"></script>
|
||||
|
|
@ -15,8 +15,8 @@
|
|||
<link rel="icon" href="_static/shortcut-icon.png"/>
|
||||
<link rel="index" title="Index" href="genindex.html" />
|
||||
<link rel="search" title="Search" href="search.html" />
|
||||
<link rel="next" title="Patterns for Flask" href="patterns/index.html" />
|
||||
<link rel="prev" title="Development Server" href="server.html" />
|
||||
<link rel="next" title="Handling Application Errors" href="errorhandling.html" />
|
||||
<link rel="prev" title="Templates" href="templating.html" />
|
||||
</head><body>
|
||||
<div class="related" role="navigation" aria-label="Related">
|
||||
<h3>Navigation</h3>
|
||||
|
|
@ -28,109 +28,283 @@
|
|||
<a href="py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="patterns/index.html" title="Patterns for Flask"
|
||||
<a href="errorhandling.html" title="Handling Application Errors"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="server.html" title="Development Server"
|
||||
<a href="templating.html" title="Templates"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li class="nav-item nav-item-0"><a href="index.html">Flask Documentation (3.2.x)</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Working with the Shell</a></li>
|
||||
<li class="nav-item nav-item-this"><a href="">Testing Flask Applications</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<section id="working-with-the-shell">
|
||||
<h1>Working with the Shell<a class="headerlink" href="#working-with-the-shell" title="Link to this heading">¶</a></h1>
|
||||
<details class="changelog">
|
||||
<summary>Changelog</summary><div class="versionadded">
|
||||
<p><span class="versionmodified added">Added in version 0.3.</span></p>
|
||||
|
||||
<section id="testing-flask-applications">
|
||||
<h1>Testing Flask Applications<a class="headerlink" href="#testing-flask-applications" title="Link to this heading">¶</a></h1>
|
||||
<p>Flask provides utilities for testing an application. This documentation
|
||||
goes over techniques for working with different parts of the application
|
||||
in tests.</p>
|
||||
<p>We will use the <a class="reference external" href="https://docs.pytest.org/">pytest</a> framework to set up and run our tests.</p>
|
||||
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ pip install pytest
|
||||
</pre></div>
|
||||
</div>
|
||||
</details><p>One of the reasons everybody loves Python is the interactive shell. It
|
||||
basically allows you to execute Python commands in real time and
|
||||
immediately get results back. Flask itself does not come with an
|
||||
interactive shell, because it does not require any specific setup upfront,
|
||||
just import your application and start playing around.</p>
|
||||
<p>There are however some handy helpers to make playing around in the shell a
|
||||
more pleasant experience. The main issue with interactive console
|
||||
sessions is that you’re not triggering a request like a browser does which
|
||||
means that <a class="reference internal" href="api.html#flask.g" title="flask.g"><code class="xref py py-data docutils literal notranslate"><span class="pre">g</span></code></a>, <a class="reference internal" href="api.html#flask.request" title="flask.request"><code class="xref py py-data docutils literal notranslate"><span class="pre">request</span></code></a> and others are not
|
||||
available. But the code you want to test might depend on them, so what
|
||||
can you do?</p>
|
||||
<p>This is where some helper functions come in handy. Keep in mind however
|
||||
that these functions are not only there for interactive shell usage, but
|
||||
also for unit testing and other situations that require a faked request
|
||||
context.</p>
|
||||
<p>Generally it’s recommended that you read <a class="reference internal" href="reqcontext.html"><span class="doc">The Request Context</span></a> first.</p>
|
||||
<section id="command-line-interface">
|
||||
<h2>Command Line Interface<a class="headerlink" href="#command-line-interface" title="Link to this heading">¶</a></h2>
|
||||
<p>Starting with Flask 0.11 the recommended way to work with the shell is the
|
||||
<code class="docutils literal notranslate"><span class="pre">flask</span> <span class="pre">shell</span></code> command which does a lot of this automatically for you.
|
||||
For instance the shell is automatically initialized with a loaded
|
||||
application context.</p>
|
||||
<p>For more information see <a class="reference internal" href="cli.html"><span class="doc">Command Line Interface</span></a>.</p>
|
||||
<p>The <a class="reference internal" href="tutorial/index.html"><span class="doc">tutorial</span></a> goes over how to write tests for
|
||||
100% coverage of the sample Flaskr blog application. See
|
||||
<a class="reference internal" href="tutorial/tests.html"><span class="doc">the tutorial on tests</span></a> for a detailed
|
||||
explanation of specific tests for an application.</p>
|
||||
<section id="identifying-tests">
|
||||
<h2>Identifying Tests<a class="headerlink" href="#identifying-tests" title="Link to this heading">¶</a></h2>
|
||||
<p>Tests are typically located in the <code class="docutils literal notranslate"><span class="pre">tests</span></code> folder. Tests are functions
|
||||
that start with <code class="docutils literal notranslate"><span class="pre">test_</span></code>, in Python modules that start with <code class="docutils literal notranslate"><span class="pre">test_</span></code>.
|
||||
Tests can also be further grouped in classes that start with <code class="docutils literal notranslate"><span class="pre">Test</span></code>.</p>
|
||||
<p>It can be difficult to know what to test. Generally, try to test the
|
||||
code that you write, not the code of libraries that you use, since they
|
||||
are already tested. Try to extract complex behaviors as separate
|
||||
functions to test individually.</p>
|
||||
</section>
|
||||
<section id="creating-a-request-context">
|
||||
<h2>Creating a Request Context<a class="headerlink" href="#creating-a-request-context" title="Link to this heading">¶</a></h2>
|
||||
<p>The easiest way to create a proper request context from the shell is by
|
||||
using the <a class="reference internal" href="api.html#flask.Flask.test_request_context" title="flask.Flask.test_request_context"><code class="xref py py-attr docutils literal notranslate"><span class="pre">test_request_context</span></code></a> method which creates
|
||||
us a <a class="reference internal" href="api.html#flask.ctx.RequestContext" title="flask.ctx.RequestContext"><code class="xref py py-class docutils literal notranslate"><span class="pre">RequestContext</span></code></a>:</p>
|
||||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">ctx</span> <span class="o">=</span> <span class="n">app</span><span class="o">.</span><span class="n">test_request_context</span><span class="p">()</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Normally you would use the <code class="docutils literal notranslate"><span class="pre">with</span></code> statement to make this request object
|
||||
active, but in the shell it’s easier to use the
|
||||
<code class="xref py py-meth docutils literal notranslate"><span class="pre">push()</span></code> and
|
||||
<a class="reference internal" href="api.html#flask.ctx.RequestContext.pop" title="flask.ctx.RequestContext.pop"><code class="xref py py-meth docutils literal notranslate"><span class="pre">pop()</span></code></a> methods by hand:</p>
|
||||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">ctx</span><span class="o">.</span><span class="n">push</span><span class="p">()</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>From that point onwards you can work with the request object until you
|
||||
call <code class="code docutils literal notranslate"><span class="pre">pop</span></code>:</p>
|
||||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">ctx</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
|
||||
<section id="fixtures">
|
||||
<h2>Fixtures<a class="headerlink" href="#fixtures" title="Link to this heading">¶</a></h2>
|
||||
<p>Pytest <em>fixtures</em> allow writing pieces of code that are reusable across
|
||||
tests. A simple fixture returns a value, but a fixture can also do
|
||||
setup, yield a value, then do teardown. Fixtures for the application,
|
||||
test client, and CLI runner are shown below, they can be placed in
|
||||
<code class="docutils literal notranslate"><span class="pre">tests/conftest.py</span></code>.</p>
|
||||
<p>If you’re using an
|
||||
<a class="reference internal" href="patterns/appfactories.html"><span class="doc">application factory</span></a>, define an <code class="docutils literal notranslate"><span class="pre">app</span></code>
|
||||
fixture to create and configure an app instance. You can add code before
|
||||
and after the <code class="docutils literal notranslate"><span class="pre">yield</span></code> to set up and tear down other resources, such as
|
||||
creating and clearing a database.</p>
|
||||
<p>If you’re not using a factory, you already have an app object you can
|
||||
import and configure directly. You can still use an <code class="docutils literal notranslate"><span class="pre">app</span></code> fixture to
|
||||
set up and tear down resources.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">pytest</span>
|
||||
<span class="kn">from</span><span class="w"> </span><span class="nn">my_project</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_app</span>
|
||||
|
||||
<span class="nd">@pytest</span><span class="o">.</span><span class="n">fixture</span><span class="p">()</span>
|
||||
<span class="k">def</span><span class="w"> </span><span class="nf">app</span><span class="p">():</span>
|
||||
<span class="n">app</span> <span class="o">=</span> <span class="n">create_app</span><span class="p">()</span>
|
||||
<span class="n">app</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">update</span><span class="p">({</span>
|
||||
<span class="s2">"TESTING"</span><span class="p">:</span> <span class="kc">True</span><span class="p">,</span>
|
||||
<span class="p">})</span>
|
||||
|
||||
<span class="c1"># other setup can go here</span>
|
||||
|
||||
<span class="k">yield</span> <span class="n">app</span>
|
||||
|
||||
<span class="c1"># clean up / reset resources here</span>
|
||||
|
||||
|
||||
<span class="nd">@pytest</span><span class="o">.</span><span class="n">fixture</span><span class="p">()</span>
|
||||
<span class="k">def</span><span class="w"> </span><span class="nf">client</span><span class="p">(</span><span class="n">app</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="n">app</span><span class="o">.</span><span class="n">test_client</span><span class="p">()</span>
|
||||
|
||||
|
||||
<span class="nd">@pytest</span><span class="o">.</span><span class="n">fixture</span><span class="p">()</span>
|
||||
<span class="k">def</span><span class="w"> </span><span class="nf">runner</span><span class="p">(</span><span class="n">app</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="n">app</span><span class="o">.</span><span class="n">test_cli_runner</span><span class="p">()</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="firing-before-after-request">
|
||||
<h2>Firing Before/After Request<a class="headerlink" href="#firing-before-after-request" title="Link to this heading">¶</a></h2>
|
||||
<p>By just creating a request context, you still don’t have run the code that
|
||||
is normally run before a request. This might result in your database
|
||||
being unavailable if you are connecting to the database in a
|
||||
before-request callback or the current user not being stored on the
|
||||
<a class="reference internal" href="api.html#flask.g" title="flask.g"><code class="xref py py-data docutils literal notranslate"><span class="pre">g</span></code></a> object etc.</p>
|
||||
<p>This however can easily be done yourself. Just call
|
||||
<a class="reference internal" href="api.html#flask.Flask.preprocess_request" title="flask.Flask.preprocess_request"><code class="xref py py-meth docutils literal notranslate"><span class="pre">preprocess_request()</span></code></a>:</p>
|
||||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">ctx</span> <span class="o">=</span> <span class="n">app</span><span class="o">.</span><span class="n">test_request_context</span><span class="p">()</span>
|
||||
<span class="gp">>>> </span><span class="n">ctx</span><span class="o">.</span><span class="n">push</span><span class="p">()</span>
|
||||
<span class="gp">>>> </span><span class="n">app</span><span class="o">.</span><span class="n">preprocess_request</span><span class="p">()</span>
|
||||
<section id="sending-requests-with-the-test-client">
|
||||
<h2>Sending Requests with the Test Client<a class="headerlink" href="#sending-requests-with-the-test-client" title="Link to this heading">¶</a></h2>
|
||||
<p>The test client makes requests to the application without running a live
|
||||
server. Flask’s client extends
|
||||
<a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/test/" title="(in Werkzeug v3.1.x)"><span class="xref std std-doc">Werkzeug’s client</span></a>, see those docs for additional
|
||||
information.</p>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">client</span></code> has methods that match the common HTTP request methods,
|
||||
such as <code class="docutils literal notranslate"><span class="pre">client.get()</span></code> and <code class="docutils literal notranslate"><span class="pre">client.post()</span></code>. They take many arguments
|
||||
for building the request; you can find the full documentation in
|
||||
<a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/test/#werkzeug.test.EnvironBuilder" title="(in Werkzeug v3.1.x)"><code class="xref py py-class docutils literal notranslate"><span class="pre">EnvironBuilder</span></code></a>. Typically you’ll use <code class="docutils literal notranslate"><span class="pre">path</span></code>,
|
||||
<code class="docutils literal notranslate"><span class="pre">query_string</span></code>, <code class="docutils literal notranslate"><span class="pre">headers</span></code>, and <code class="docutils literal notranslate"><span class="pre">data</span></code> or <code class="docutils literal notranslate"><span class="pre">json</span></code>.</p>
|
||||
<p>To make a request, call the method the request should use with the path
|
||||
to the route to test. A <a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/test/#werkzeug.test.TestResponse" title="(in Werkzeug v3.1.x)"><code class="xref py py-class docutils literal notranslate"><span class="pre">TestResponse</span></code></a> is returned
|
||||
to examine the response data. It has all the usual properties of a
|
||||
response object. You’ll usually look at <code class="docutils literal notranslate"><span class="pre">response.data</span></code>, which is the
|
||||
bytes returned by the view. If you want to use text, Werkzeug 2.1
|
||||
provides <code class="docutils literal notranslate"><span class="pre">response.text</span></code>, or use <code class="docutils literal notranslate"><span class="pre">response.get_data(as_text=True)</span></code>.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">test_request_example</span><span class="p">(</span><span class="n">client</span><span class="p">):</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">"/posts"</span><span class="p">)</span>
|
||||
<span class="k">assert</span> <span class="sa">b</span><span class="s2">"<h2>Hello, World!</h2>"</span> <span class="ow">in</span> <span class="n">response</span><span class="o">.</span><span class="n">data</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Keep in mind that the <a class="reference internal" href="api.html#flask.Flask.preprocess_request" title="flask.Flask.preprocess_request"><code class="xref py py-meth docutils literal notranslate"><span class="pre">preprocess_request()</span></code></a> function
|
||||
might return a response object, in that case just ignore it.</p>
|
||||
<p>To shutdown a request, you need to trick a bit before the after request
|
||||
functions (triggered by <a class="reference internal" href="api.html#flask.Flask.process_response" title="flask.Flask.process_response"><code class="xref py py-meth docutils literal notranslate"><span class="pre">process_response()</span></code></a>) operate on
|
||||
a response object:</p>
|
||||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">app</span><span class="o">.</span><span class="n">process_response</span><span class="p">(</span><span class="n">app</span><span class="o">.</span><span class="n">response_class</span><span class="p">())</span>
|
||||
<span class="go"><Response 0 bytes [200 OK]></span>
|
||||
<span class="gp">>>> </span><span class="n">ctx</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
|
||||
<p>Pass a dict <code class="docutils literal notranslate"><span class="pre">query_string={"key":</span> <span class="pre">"value",</span> <span class="pre">...}</span></code> to set arguments in
|
||||
the query string (after the <code class="docutils literal notranslate"><span class="pre">?</span></code> in the URL). Pass a dict
|
||||
<code class="docutils literal notranslate"><span class="pre">headers={}</span></code> to set request headers.</p>
|
||||
<p>To send a request body in a POST or PUT request, pass a value to
|
||||
<code class="docutils literal notranslate"><span class="pre">data</span></code>. If raw bytes are passed, that exact body is used. Usually,
|
||||
you’ll pass a dict to set form data.</p>
|
||||
<section id="form-data">
|
||||
<h3>Form Data<a class="headerlink" href="#form-data" title="Link to this heading">¶</a></h3>
|
||||
<p>To send form data, pass a dict to <code class="docutils literal notranslate"><span class="pre">data</span></code>. The <code class="docutils literal notranslate"><span class="pre">Content-Type</span></code> header
|
||||
will be set to <code class="docutils literal notranslate"><span class="pre">multipart/form-data</span></code> or
|
||||
<code class="docutils literal notranslate"><span class="pre">application/x-www-form-urlencoded</span></code> automatically.</p>
|
||||
<p>If a value is a file object opened for reading bytes (<code class="docutils literal notranslate"><span class="pre">"rb"</span></code> mode), it
|
||||
will be treated as an uploaded file. To change the detected filename and
|
||||
content type, pass a <code class="docutils literal notranslate"><span class="pre">(file,</span> <span class="pre">filename,</span> <span class="pre">content_type)</span></code> tuple. File
|
||||
objects will be closed after making the request, so they do not need to
|
||||
use the usual <code class="docutils literal notranslate"><span class="pre">with</span> <span class="pre">open()</span> <span class="pre">as</span> <span class="pre">f:</span></code> pattern.</p>
|
||||
<p>It can be useful to store files in a <code class="docutils literal notranslate"><span class="pre">tests/resources</span></code> folder, then
|
||||
use <code class="docutils literal notranslate"><span class="pre">pathlib.Path</span></code> to get files relative to the current test file.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">pathlib</span><span class="w"> </span><span class="kn">import</span> <span class="n">Path</span>
|
||||
|
||||
<span class="c1"># get the resources folder in the tests folder</span>
|
||||
<span class="n">resources</span> <span class="o">=</span> <span class="n">Path</span><span class="p">(</span><span class="vm">__file__</span><span class="p">)</span><span class="o">.</span><span class="n">parent</span> <span class="o">/</span> <span class="s2">"resources"</span>
|
||||
|
||||
<span class="k">def</span><span class="w"> </span><span class="nf">test_edit_user</span><span class="p">(</span><span class="n">client</span><span class="p">):</span>
|
||||
<span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="s2">"/user/2/edit"</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="p">{</span>
|
||||
<span class="s2">"name"</span><span class="p">:</span> <span class="s2">"Flask"</span><span class="p">,</span>
|
||||
<span class="s2">"theme"</span><span class="p">:</span> <span class="s2">"dark"</span><span class="p">,</span>
|
||||
<span class="s2">"picture"</span><span class="p">:</span> <span class="p">(</span><span class="n">resources</span> <span class="o">/</span> <span class="s2">"picture.png"</span><span class="p">)</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="s2">"rb"</span><span class="p">),</span>
|
||||
<span class="p">})</span>
|
||||
<span class="k">assert</span> <span class="n">response</span><span class="o">.</span><span class="n">status_code</span> <span class="o">==</span> <span class="mi">200</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The functions registered as <a class="reference internal" href="api.html#flask.Flask.teardown_request" title="flask.Flask.teardown_request"><code class="xref py py-meth docutils literal notranslate"><span class="pre">teardown_request()</span></code></a> are
|
||||
automatically called when the context is popped. So this is the perfect
|
||||
place to automatically tear down resources that were needed by the request
|
||||
context (such as database connections).</p>
|
||||
</section>
|
||||
<section id="further-improving-the-shell-experience">
|
||||
<h2>Further Improving the Shell Experience<a class="headerlink" href="#further-improving-the-shell-experience" title="Link to this heading">¶</a></h2>
|
||||
<p>If you like the idea of experimenting in a shell, create yourself a module
|
||||
with stuff you want to star import into your interactive session. There
|
||||
you could also define some more helper methods for common things such as
|
||||
initializing the database, dropping tables etc.</p>
|
||||
<p>Just put them into a module (like <code class="code docutils literal notranslate"><span class="pre">shelltools</span></code>) and import from there:</p>
|
||||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span><span class="w"> </span><span class="nn">shelltools</span><span class="w"> </span><span class="kn">import</span> <span class="o">*</span>
|
||||
<section id="json-data">
|
||||
<h3>JSON Data<a class="headerlink" href="#json-data" title="Link to this heading">¶</a></h3>
|
||||
<p>To send JSON data, pass an object to <code class="docutils literal notranslate"><span class="pre">json</span></code>. The <code class="docutils literal notranslate"><span class="pre">Content-Type</span></code>
|
||||
header will be set to <code class="docutils literal notranslate"><span class="pre">application/json</span></code> automatically.</p>
|
||||
<p>Similarly, if the response contains JSON data, the <code class="docutils literal notranslate"><span class="pre">response.json</span></code>
|
||||
attribute will contain the deserialized object.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">test_json_data</span><span class="p">(</span><span class="n">client</span><span class="p">):</span>
|
||||
<span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="s2">"/graphql"</span><span class="p">,</span> <span class="n">json</span><span class="o">=</span><span class="p">{</span>
|
||||
<span class="s2">"query"</span><span class="p">:</span> <span class="s2">"""</span>
|
||||
<span class="s2"> query User($id: String!) {</span>
|
||||
<span class="s2"> user(id: $id) {</span>
|
||||
<span class="s2"> name</span>
|
||||
<span class="s2"> theme</span>
|
||||
<span class="s2"> picture_url</span>
|
||||
<span class="s2"> }</span>
|
||||
<span class="s2"> }</span>
|
||||
<span class="s2"> """</span><span class="p">,</span>
|
||||
<span class="n">variables</span><span class="o">=</span><span class="p">{</span><span class="s2">"id"</span><span class="p">:</span> <span class="mi">2</span><span class="p">},</span>
|
||||
<span class="p">})</span>
|
||||
<span class="k">assert</span> <span class="n">response</span><span class="o">.</span><span class="n">json</span><span class="p">[</span><span class="s2">"data"</span><span class="p">][</span><span class="s2">"user"</span><span class="p">][</span><span class="s2">"name"</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"Flask"</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
<section id="following-redirects">
|
||||
<h2>Following Redirects<a class="headerlink" href="#following-redirects" title="Link to this heading">¶</a></h2>
|
||||
<p>By default, the client does not make additional requests if the response
|
||||
is a redirect. By passing <code class="docutils literal notranslate"><span class="pre">follow_redirects=True</span></code> to a request method,
|
||||
the client will continue to make requests until a non-redirect response
|
||||
is returned.</p>
|
||||
<p><a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/test/#werkzeug.test.TestResponse.history" title="(in Werkzeug v3.1.x)"><code class="xref py py-attr docutils literal notranslate"><span class="pre">TestResponse.history</span></code></a> is
|
||||
a tuple of the responses that led up to the final response. Each
|
||||
response has a <a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/test/#werkzeug.test.TestResponse.request" title="(in Werkzeug v3.1.x)"><code class="xref py py-attr docutils literal notranslate"><span class="pre">request</span></code></a> attribute
|
||||
which records the request that produced that response.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">test_logout_redirect</span><span class="p">(</span><span class="n">client</span><span class="p">):</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">"/logout"</span><span class="p">,</span> <span class="n">follow_redirects</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
||||
<span class="c1"># Check that there was one redirect response.</span>
|
||||
<span class="k">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">history</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span>
|
||||
<span class="c1"># Check that the second request was to the index page.</span>
|
||||
<span class="k">assert</span> <span class="n">response</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">path</span> <span class="o">==</span> <span class="s2">"/index"</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="accessing-and-modifying-the-session">
|
||||
<h2>Accessing and Modifying the Session<a class="headerlink" href="#accessing-and-modifying-the-session" title="Link to this heading">¶</a></h2>
|
||||
<p>To access Flask’s context variables, mainly
|
||||
<a class="reference internal" href="api.html#flask.session" title="flask.session"><code class="xref py py-data docutils literal notranslate"><span class="pre">session</span></code></a>, use the client in a <code class="docutils literal notranslate"><span class="pre">with</span></code> statement.
|
||||
The app and request context will remain active <em>after</em> making a request,
|
||||
until the <code class="docutils literal notranslate"><span class="pre">with</span></code> block ends.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">flask</span><span class="w"> </span><span class="kn">import</span> <span class="n">session</span>
|
||||
|
||||
<span class="k">def</span><span class="w"> </span><span class="nf">test_access_session</span><span class="p">(</span><span class="n">client</span><span class="p">):</span>
|
||||
<span class="k">with</span> <span class="n">client</span><span class="p">:</span>
|
||||
<span class="n">client</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="s2">"/auth/login"</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="p">{</span><span class="s2">"username"</span><span class="p">:</span> <span class="s2">"flask"</span><span class="p">})</span>
|
||||
<span class="c1"># session is still accessible</span>
|
||||
<span class="k">assert</span> <span class="n">session</span><span class="p">[</span><span class="s2">"user_id"</span><span class="p">]</span> <span class="o">==</span> <span class="mi">1</span>
|
||||
|
||||
<span class="c1"># session is no longer accessible</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>If you want to access or set a value in the session <em>before</em> making a
|
||||
request, use the client’s
|
||||
<a class="reference internal" href="api.html#flask.testing.FlaskClient.session_transaction" title="flask.testing.FlaskClient.session_transaction"><code class="xref py py-meth docutils literal notranslate"><span class="pre">session_transaction()</span></code></a> method in a
|
||||
<code class="docutils literal notranslate"><span class="pre">with</span></code> statement. It returns a session object, and will save the
|
||||
session once the block ends.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">flask</span><span class="w"> </span><span class="kn">import</span> <span class="n">session</span>
|
||||
|
||||
<span class="k">def</span><span class="w"> </span><span class="nf">test_modify_session</span><span class="p">(</span><span class="n">client</span><span class="p">):</span>
|
||||
<span class="k">with</span> <span class="n">client</span><span class="o">.</span><span class="n">session_transaction</span><span class="p">()</span> <span class="k">as</span> <span class="n">session</span><span class="p">:</span>
|
||||
<span class="c1"># set a user id without going through the login route</span>
|
||||
<span class="n">session</span><span class="p">[</span><span class="s2">"user_id"</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span>
|
||||
|
||||
<span class="c1"># session is saved now</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">"/users/me"</span><span class="p">)</span>
|
||||
<span class="k">assert</span> <span class="n">response</span><span class="o">.</span><span class="n">json</span><span class="p">[</span><span class="s2">"username"</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"flask"</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="running-commands-with-the-cli-runner">
|
||||
<span id="testing-cli"></span><h2>Running Commands with the CLI Runner<a class="headerlink" href="#running-commands-with-the-cli-runner" title="Link to this heading">¶</a></h2>
|
||||
<p>Flask provides <a class="reference internal" href="api.html#flask.Flask.test_cli_runner" title="flask.Flask.test_cli_runner"><code class="xref py py-meth docutils literal notranslate"><span class="pre">test_cli_runner()</span></code></a> to create a
|
||||
<a class="reference internal" href="api.html#flask.testing.FlaskCliRunner" title="flask.testing.FlaskCliRunner"><code class="xref py py-class docutils literal notranslate"><span class="pre">FlaskCliRunner</span></code></a>, which runs CLI commands in
|
||||
isolation and captures the output in a <a class="reference external" href="https://click.palletsprojects.com/en/stable/api/#click.testing.Result" title="(in Click v8.1.x)"><code class="xref py py-class docutils literal notranslate"><span class="pre">Result</span></code></a>
|
||||
object. Flask’s runner extends <a class="reference external" href="https://click.palletsprojects.com/en/stable/testing/" title="(in Click v8.1.x)"><span class="xref std std-doc">Click’s runner</span></a>,
|
||||
see those docs for additional information.</p>
|
||||
<p>Use the runner’s <a class="reference internal" href="api.html#flask.testing.FlaskCliRunner.invoke" title="flask.testing.FlaskCliRunner.invoke"><code class="xref py py-meth docutils literal notranslate"><span class="pre">invoke()</span></code></a> method to
|
||||
call commands in the same way they would be called with the <code class="docutils literal notranslate"><span class="pre">flask</span></code>
|
||||
command from the command line.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">click</span>
|
||||
|
||||
<span class="nd">@app</span><span class="o">.</span><span class="n">cli</span><span class="o">.</span><span class="n">command</span><span class="p">(</span><span class="s2">"hello"</span><span class="p">)</span>
|
||||
<span class="nd">@click</span><span class="o">.</span><span class="n">option</span><span class="p">(</span><span class="s2">"--name"</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="s2">"World"</span><span class="p">)</span>
|
||||
<span class="k">def</span><span class="w"> </span><span class="nf">hello_command</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
|
||||
<span class="n">click</span><span class="o">.</span><span class="n">echo</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Hello, </span><span class="si">{</span><span class="n">name</span><span class="si">}</span><span class="s2">!"</span><span class="p">)</span>
|
||||
|
||||
<span class="k">def</span><span class="w"> </span><span class="nf">test_hello_command</span><span class="p">(</span><span class="n">runner</span><span class="p">):</span>
|
||||
<span class="n">result</span> <span class="o">=</span> <span class="n">runner</span><span class="o">.</span><span class="n">invoke</span><span class="p">(</span><span class="n">args</span><span class="o">=</span><span class="s2">"hello"</span><span class="p">)</span>
|
||||
<span class="k">assert</span> <span class="s2">"World"</span> <span class="ow">in</span> <span class="n">result</span><span class="o">.</span><span class="n">output</span>
|
||||
|
||||
<span class="n">result</span> <span class="o">=</span> <span class="n">runner</span><span class="o">.</span><span class="n">invoke</span><span class="p">(</span><span class="n">args</span><span class="o">=</span><span class="p">[</span><span class="s2">"hello"</span><span class="p">,</span> <span class="s2">"--name"</span><span class="p">,</span> <span class="s2">"Flask"</span><span class="p">])</span>
|
||||
<span class="k">assert</span> <span class="s2">"Flask"</span> <span class="ow">in</span> <span class="n">result</span><span class="o">.</span><span class="n">output</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="tests-that-depend-on-an-active-context">
|
||||
<h2>Tests that depend on an Active Context<a class="headerlink" href="#tests-that-depend-on-an-active-context" title="Link to this heading">¶</a></h2>
|
||||
<p>You may have functions that are called from views or commands, that
|
||||
expect an active <a class="reference internal" href="appcontext.html"><span class="doc">application context</span></a> or
|
||||
<a class="reference internal" href="reqcontext.html"><span class="doc">request context</span></a> because they access <code class="docutils literal notranslate"><span class="pre">request</span></code>,
|
||||
<code class="docutils literal notranslate"><span class="pre">session</span></code>, or <code class="docutils literal notranslate"><span class="pre">current_app</span></code>. Rather than testing them by making a
|
||||
request or invoking the command, you can create and activate a context
|
||||
directly.</p>
|
||||
<p>Use <code class="docutils literal notranslate"><span class="pre">with</span> <span class="pre">app.app_context()</span></code> to push an application context. For
|
||||
example, database extensions usually require an active app context to
|
||||
make queries.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">test_db_post_model</span><span class="p">(</span><span class="n">app</span><span class="p">):</span>
|
||||
<span class="k">with</span> <span class="n">app</span><span class="o">.</span><span class="n">app_context</span><span class="p">():</span>
|
||||
<span class="n">post</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">Post</span><span class="p">)</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Use <code class="docutils literal notranslate"><span class="pre">with</span> <span class="pre">app.test_request_context()</span></code> to push a request context. It
|
||||
takes the same arguments as the test client’s request methods.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">test_validate_user_edit</span><span class="p">(</span><span class="n">app</span><span class="p">):</span>
|
||||
<span class="k">with</span> <span class="n">app</span><span class="o">.</span><span class="n">test_request_context</span><span class="p">(</span>
|
||||
<span class="s2">"/user/2/edit"</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="s2">"POST"</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="p">{</span><span class="s2">"name"</span><span class="p">:</span> <span class="s2">""</span><span class="p">}</span>
|
||||
<span class="p">):</span>
|
||||
<span class="c1"># call a function that accesses `request`</span>
|
||||
<span class="n">messages</span> <span class="o">=</span> <span class="n">validate_edit_user</span><span class="p">()</span>
|
||||
|
||||
<span class="k">assert</span> <span class="n">messages</span><span class="p">[</span><span class="s2">"name"</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"Name cannot be empty."</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Creating a test request context doesn’t run any of the Flask dispatching
|
||||
code, so <code class="docutils literal notranslate"><span class="pre">before_request</span></code> functions are not called. If you need to
|
||||
call these, usually it’s better to make a full request instead. However,
|
||||
it’s possible to call them manually.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">test_auth_token</span><span class="p">(</span><span class="n">app</span><span class="p">):</span>
|
||||
<span class="k">with</span> <span class="n">app</span><span class="o">.</span><span class="n">test_request_context</span><span class="p">(</span><span class="s2">"/user/2/edit"</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="p">{</span><span class="s2">"X-Auth-Token"</span><span class="p">:</span> <span class="s2">"1"</span><span class="p">}):</span>
|
||||
<span class="n">app</span><span class="o">.</span><span class="n">preprocess_request</span><span class="p">()</span>
|
||||
<span class="k">assert</span> <span class="n">g</span><span class="o">.</span><span class="n">user</span><span class="o">.</span><span class="n">name</span> <span class="o">==</span> <span class="s2">"Flask"</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -144,20 +318,27 @@ initializing the database, dropping tables etc.</p>
|
|||
<span id="sidebar-top"></span>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="Main">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
|
||||
|
||||
|
||||
|
||||
<p class="logo"><a href="index.html">
|
||||
<img class="logo" src="_static/flask-vertical.png" alt="Logo of Flask"/>
|
||||
</a></p>
|
||||
|
||||
|
||||
|
||||
<h3>Contents</h3>
|
||||
<ul>
|
||||
<li><a class="reference internal" href="#">Working with the Shell</a><ul>
|
||||
<li><a class="reference internal" href="#command-line-interface">Command Line Interface</a></li>
|
||||
<li><a class="reference internal" href="#creating-a-request-context">Creating a Request Context</a></li>
|
||||
<li><a class="reference internal" href="#firing-before-after-request">Firing Before/After Request</a></li>
|
||||
<li><a class="reference internal" href="#further-improving-the-shell-experience">Further Improving the Shell Experience</a></li>
|
||||
<li><a class="reference internal" href="#">Testing Flask Applications</a><ul>
|
||||
<li><a class="reference internal" href="#identifying-tests">Identifying Tests</a></li>
|
||||
<li><a class="reference internal" href="#fixtures">Fixtures</a></li>
|
||||
<li><a class="reference internal" href="#sending-requests-with-the-test-client">Sending Requests with the Test Client</a><ul>
|
||||
<li><a class="reference internal" href="#form-data">Form Data</a></li>
|
||||
<li><a class="reference internal" href="#json-data">JSON Data</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#following-redirects">Following Redirects</a></li>
|
||||
<li><a class="reference internal" href="#accessing-and-modifying-the-session">Accessing and Modifying the Session</a></li>
|
||||
<li><a class="reference internal" href="#running-commands-with-the-cli-runner">Running Commands with the CLI Runner</a></li>
|
||||
<li><a class="reference internal" href="#tests-that-depend-on-an-active-context">Tests that depend on an Active Context</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
@ -165,8 +346,8 @@ initializing the database, dropping tables etc.</p>
|
|||
<ul>
|
||||
<li><a href="index.html">Overview</a>
|
||||
<ul>
|
||||
<li>Previous: <a href="server.html" title="previous chapter">Development Server</a>
|
||||
<li>Next: <a href="patterns/index.html" title="next chapter">Patterns for Flask</a>
|
||||
<li>Previous: <a href="templating.html" title="previous chapter">Templates</a>
|
||||
<li>Next: <a href="errorhandling.html" title="next chapter">Handling Application Errors</a>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
@ -189,4 +370,4 @@ initializing the database, dropping tables etc.</p>
|
|||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue