FlaskTester Documentation

This is the documentation for the fixtures and support classes provided by FlaskTester.

Fixtures

The package provides two fixtures:

  • ft_authenticator for app authentication, which depends on environment variables:

    • FLASK_TESTER_ALLOW space-separated list of allowed authentication schemes, defaults to bearer basic param none.

    • FLASK_TESTER_AUTH comma-separated list of login:password credentials, defaults to empty.

    • FLASK_TESTER_USER user login parameter for param password authentication, defaults to USER.

    • FLASK_TESTER_PASS user password parameter for param password authentication, defaults to PASS.

    • FLASK_TESTER_LOGIN user login parameter for fake authentication, defaults to LOGIN.

    • FLASK_TESTER_TPARAM token parameter for tparam token authentication, defaults to AUTH.

    • FLASK_TESTER_BEARER bearer scheme for bearer token authentication, defaults to Bearer.

    • FLASK_TESTER_HEADER header name for for header token authentication, defaults to Auth.

    • FLASK_TESTER_COOKIE cookie name for for cookie token authentication, defaults to auth.

    • FLASK_TESTER_PTYPE default type of parameters, data or json, defaults to data.

    • FLASK_TESTER_LOG_LEVEL log level for module, defaults to NOTSET.

    The fixture has 3 useful methods:

    • setPass to associate a password to a user, set to None to remove credential.

      auth.setPass("susie", "<susie-incredible-password>")
      
    • setToken to associate a token to a user, set to None to remove credential.

      auth.setToken("moe", "<moe's-token-computed-or-obtained-from-somewhere>")
      
    • setCookie to add a cookie to a user, set value to None to remove cookie.

      auth.setCookie("rosalyn", "lang", "en_US")
      
  • ft_client for app testing, which depends on the previous fixture and is configured from two environment variables:

    • FLASK_TESTER_APP tells where to find the application, which may be the:

      • URL of the running application for external tests, eg http://localhost:5000. The application is expected to be already running when the test is started.

      • Package (filename without .py) to be imported for the application.

        • for pkg:name, name is the application in pkg.

        • for pkg only, look for app as app, application, create_app, make_app.

        • in both cases, name is called if callable and not a Flask application.

      If not set, the defaults to app, which is to behave like Flask.

    • FLASK_TESTER_DEFAULT default login for authentication, defaults to None.

    The fixture then provides test methods to issue test requests against a Flask application:

    • request generic request with login, auth, status end content extensions.

      For instance, the following sumits a POST on path /users with one JSON parameter, as user calvin using basic authentication, expecting status code 201 and some integer value (content regex) in the response body:

      res = app.request("POST", "/users", 201, r"\d+", json={"username": "hobbes"},
                        login="calvin", auth="basic")
      assert res.is_json and "uid" in res.json
      uid = res.json["uid"]
      

      The authentication data, here a password, must have been provided to the authenticator.

      Direct parameters from pydantic and dataclass classes are supported and converted to JSON.

    • get post put patch delete methods with the same extensions.

      Submit a GET request to path /stats authenticated as hobbes, expecting response status 200:

      app.get("/stats", 200, login="hobbes")
      
    • setHook allows to add a hook executed on setPass. The typical use case is to load a token when new credentials are provided. As with other methods, None is used for removal.

      def authHook(client: Client, username: str, password: str|None):
          if password:
              res = client.post("/login", 201, login=username, auth="param")
              client.setToken(username, res.json["token"])
          else:
              client.setToken(username, None)
      

    Moreover, setPass, setToken and setCookie are forwarded to the internal authenticator.

Authenticator environment variables can be set from the pytest Python test file by assigning them through os.environ.

The typical use case is to define a local fixture, set the authentication and other data, and then proceed with it:

import os
import pytest
from FlaskTester import ft_client, ft_authenticator
import secret

os.environ.update(FLASK_TESTER_ALLOW="basic param none")

@pytest.fixture
def app(ft_client):
    ft_client.setPass("calvin", secret.PASSES["calvin"])
    ft_client.setCookie("calvin", "lang", "en")
    ft_client.setPass("hobbes", secret.PASSES["hobbes"])
    ft_client.setCookie("hobbes", "lang", "fr")
    yield ft_client

def test_app(app):
    # requires an authentication
    app.get("/authenticated", 401, login=None)
    app.get("/authenticated", 200, "Hello", login="calvin")
    app.get("/authenticated", 200, "Bonjour", login="hobbes")
    # only allowed to calvin
    app.get("/only-admin", 401, login=None)
    app.get("/only-admin", 200, "administrateur", login="calvin")
    app.get("/only-admin", 403, "not in group", login="hobbes")
    # no authentication required, but depends on lang
    app.get("/open", 200, "Hello", login="calvin", auth="none")
    app.get("/open", 200, "Bonjour", login="hobbes", auth="none")
    app.get("/open", 200, "Guten Tag", login=None)

Classes

The implementation of these fixtures is based on five classes, see the API documentation for further details:

  • Authenticator class to store test credentials.

  • RequestFlaskResponse class to turn a requests response into a Flask-looking response, with the following attributes: status_code, data, text, headers, cookies, is_json and json.

  • Client abstract class to run test, with two implementations.

  • FlaskClient implementation class for internal (test_client) tests.

  • RequestClient implementation class for external (real HTTP) tests.

Exceptions

The following exceptions are defined and may be raised:

  • FlaskTesterError root class for exceptions.

  • AuthError authentication-related errors.

See Also, or Not

  • Flask Testing an unmaintained old-style unit test for Flask 1.x, without authentication help.