<p>The <aclass="reference internal"href="tutorial/index.html"><spanclass="doc">tutorial</span></a> goes over how to write tests for
100% coverage of the sample Flaskr blog application. See
<aclass="reference internal"href="tutorial/tests.html"><spanclass="doc">the tutorial on tests</span></a> for a detailed
explanation of specific tests for an application.</p>
<sectionid="identifying-tests">
<h2>Identifying Tests<aclass="headerlink"href="#identifying-tests"title="Link to this heading">¶</a></h2>
<p>Tests are typically located in the <codeclass="docutils literal notranslate"><spanclass="pre">tests</span></code> folder. Tests are functions
that start with <codeclass="docutils literal notranslate"><spanclass="pre">test_</span></code>, in Python modules that start with <codeclass="docutils literal notranslate"><spanclass="pre">test_</span></code>.
Tests can also be further grouped in classes that start with <codeclass="docutils literal notranslate"><spanclass="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
<h2>Sending Requests with the Test Client<aclass="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
<aclass="reference external"href="https://werkzeug.palletsprojects.com/en/stable/test/"title="(in Werkzeug v3.1.x)"><spanclass="xref std std-doc">Werkzeug’s client</span></a>, see those docs for additional
information.</p>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">client</span></code> has methods that match the common HTTP request methods,
such as <codeclass="docutils literal notranslate"><spanclass="pre">client.get()</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">client.post()</span></code>. They take many arguments
for building the request; you can find the full documentation in
<aclass="reference external"href="https://werkzeug.palletsprojects.com/en/stable/test/#werkzeug.test.EnvironBuilder"title="(in Werkzeug v3.1.x)"><codeclass="xref py py-class docutils literal notranslate"><spanclass="pre">EnvironBuilder</span></code></a>. Typically you’ll use <codeclass="docutils literal notranslate"><spanclass="pre">path</span></code>,
<codeclass="docutils literal notranslate"><spanclass="pre">query_string</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">headers</span></code>, and <codeclass="docutils literal notranslate"><spanclass="pre">data</span></code> or <codeclass="docutils literal notranslate"><spanclass="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 <aclass="reference external"href="https://werkzeug.palletsprojects.com/en/stable/test/#werkzeug.test.TestResponse"title="(in Werkzeug v3.1.x)"><codeclass="xref py py-class docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">response.data</span></code>, which is the
bytes returned by the view. If you want to use text, Werkzeug 2.1
provides <codeclass="docutils literal notranslate"><spanclass="pre">response.text</span></code>, or use <codeclass="docutils literal notranslate"><spanclass="pre">response.get_data(as_text=True)</span></code>.</p>
<p>Pass a dict <codeclass="docutils literal notranslate"><spanclass="pre">query_string={"key":</span><spanclass="pre">"value",</span><spanclass="pre">...}</span></code> to set arguments in
the query string (after the <codeclass="docutils literal notranslate"><spanclass="pre">?</span></code> in the URL). Pass a dict
<codeclass="docutils literal notranslate"><spanclass="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
<codeclass="docutils literal notranslate"><spanclass="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>
<sectionid="form-data">
<h3>Form Data<aclass="headerlink"href="#form-data"title="Link to this heading">¶</a></h3>
<p>To send form data, pass a dict to <codeclass="docutils literal notranslate"><spanclass="pre">data</span></code>. The <codeclass="docutils literal notranslate"><spanclass="pre">Content-Type</span></code> header
will be set to <codeclass="docutils literal notranslate"><spanclass="pre">multipart/form-data</span></code> or
<p>If a value is a file object opened for reading bytes (<codeclass="docutils literal notranslate"><spanclass="pre">"rb"</span></code> mode), it
will be treated as an uploaded file. To change the detected filename and
content type, pass a <codeclass="docutils literal notranslate"><spanclass="pre">(file,</span><spanclass="pre">filename,</span><spanclass="pre">content_type)</span></code> tuple. File
objects will be closed after making the request, so they do not need to
use the usual <codeclass="docutils literal notranslate"><spanclass="pre">with</span><spanclass="pre">open()</span><spanclass="pre">as</span><spanclass="pre">f:</span></code> pattern.</p>
<p>It can be useful to store files in a <codeclass="docutils literal notranslate"><spanclass="pre">tests/resources</span></code> folder, then
use <codeclass="docutils literal notranslate"><spanclass="pre">pathlib.Path</span></code> to get files relative to the current test file.</p>
<h3>JSON Data<aclass="headerlink"href="#json-data"title="Link to this heading">¶</a></h3>
<p>To send JSON data, pass an object to <codeclass="docutils literal notranslate"><spanclass="pre">json</span></code>. The <codeclass="docutils literal notranslate"><spanclass="pre">Content-Type</span></code>
header will be set to <codeclass="docutils literal notranslate"><spanclass="pre">application/json</span></code> automatically.</p>
<p>Similarly, if the response contains JSON data, the <codeclass="docutils literal notranslate"><spanclass="pre">response.json</span></code>
attribute will contain the deserialized object.</p>
<h2>Accessing and Modifying the Session<aclass="headerlink"href="#accessing-and-modifying-the-session"title="Link to this heading">¶</a></h2>
<p>To access Flask’s context variables, mainly
<aclass="reference internal"href="api.html#flask.session"title="flask.session"><codeclass="xref py py-data docutils literal notranslate"><spanclass="pre">session</span></code></a>, use the client in a <codeclass="docutils literal notranslate"><spanclass="pre">with</span></code> statement.
The app and request context will remain active <em>after</em> making a request,
until the <codeclass="docutils literal notranslate"><spanclass="pre">with</span></code> block ends.</p>
<p>If you want to access or set a value in the session <em>before</em> making a
request, use the client’s
<aclass="reference internal"href="api.html#flask.testing.FlaskClient.session_transaction"title="flask.testing.FlaskClient.session_transaction"><codeclass="xref py py-meth docutils literal notranslate"><spanclass="pre">session_transaction()</span></code></a> method in a
<codeclass="docutils literal notranslate"><spanclass="pre">with</span></code> statement. It returns a session object, and will save the
<spanid="testing-cli"></span><h2>Running Commands with the CLI Runner<aclass="headerlink"href="#running-commands-with-the-cli-runner"title="Link to this heading">¶</a></h2>
<p>Flask provides <aclass="reference internal"href="api.html#flask.Flask.test_cli_runner"title="flask.Flask.test_cli_runner"><codeclass="xref py py-meth docutils literal notranslate"><spanclass="pre">test_cli_runner()</span></code></a> to create a
<aclass="reference internal"href="api.html#flask.testing.FlaskCliRunner"title="flask.testing.FlaskCliRunner"><codeclass="xref py py-class docutils literal notranslate"><spanclass="pre">FlaskCliRunner</span></code></a>, which runs CLI commands in
isolation and captures the output in a <aclass="reference external"href="https://click.palletsprojects.com/en/stable/api/#click.testing.Result"title="(in Click v8.1.x)"><codeclass="xref py py-class docutils literal notranslate"><spanclass="pre">Result</span></code></a>
<h2>Tests that depend on an Active Context<aclass="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 <aclass="reference internal"href="appcontext.html"><spanclass="doc">application context</span></a> or
<aclass="reference internal"href="reqcontext.html"><spanclass="doc">request context</span></a> because they access <codeclass="docutils literal notranslate"><spanclass="pre">request</span></code>,
<codeclass="docutils literal notranslate"><spanclass="pre">session</span></code>, or <codeclass="docutils literal notranslate"><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="pre">with</span><spanclass="pre">app.app_context()</span></code> to push an application context. For
example, database extensions usually require an active app context to
<p>Use <codeclass="docutils literal notranslate"><spanclass="pre">with</span><spanclass="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>
<spanclass="k">assert</span><spanclass="n">messages</span><spanclass="p">[</span><spanclass="s2">"name"</span><spanclass="p">][</span><spanclass="mi">0</span><spanclass="p">]</span><spanclass="o">==</span><spanclass="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 <codeclass="docutils literal notranslate"><spanclass="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,