pytest-flask

repository·master·Indexed 19 days ago

https://github.com/pytest-dev/pytest-flask

A pytest extension providing tools to simplify the testing and development of Flask applications and extensions. It includes built-in fixtures such as 'client' for test clients, 'live_server' for running the app in a separate process for integration tests, 'config' for application configuration access, and 'accept_*' fixtures for testing content negotiation.

Tokens
4.7K
Snippets
24
Records
29
Agent score
66%

What's inside pytest-flask

  1. Access JSON response data easily

    master

    The client provided by pytest-flask makes it easy to access JSON data in responses via the .json attribute.

    Note: If your application uses a custom response class that already defines a .json attribute or method, pytest-flask will not overwrite it. You can implement custom deserialization by subclassing flask.Response and setting it as app.response_class in your fixture.

    @api.route('/ping')
    def ping():
        return jsonify(ping='pong')
    
    def test_api_ping(client):
        res = client.get(url_for('api.ping'))
        assert res.json == {'ping': 'pong'}
  2. Set up a Flask application fixture for pytest

    master

    To integrate pytest-flask with a Flask application using the application factory pattern, define an app fixture in your conftest.py file. This fixture should return an instance of your Flask application.

    Assuming you have an application factory in myapp.py:

    from flask import Flask
    
    def create_app():
        app = Flask(__name__)
    
        @app.route('/hello')
        def hello():
            return 'Hello, World!'
    
        return app

    Define the fixture in conftest.py as follows:

    import pytest
    from myapp import create_app
    
    @pytest.fixture
    def app():
        app = create_app()
        return app

    Once the fixture is defined, you can run your tests using the standard pytest command.

    import pytest
    from myapp import create_app
    
    @pytest.fixture
    def app():
        app = create_app()
        return app
    
    # Run tests with:
    # $ pytest
  3. Check test coverage

    master

    To identify code sections not covered by the test suite, run pytest using coverage. This process involves running the tests with multiprocessing concurrency, combining the results, and generating an HTML report.

    After running the commands, open htmlcov/index.html in your browser to view the report.

    $ coverage run --concurrency=multiprocessing -m pytest
    $ coverage combine
    $ coverage html
  4. Use pytest-flask fixtures for testing

    master

    pytest-flask provides several built-in fixtures to simplify Flask application testing. Key fixtures include:

    • client: An instance of app.test_client. It automatically pushes a request context, allowing you to call context-bound methods like url_for or session directly within your tests.
    • client_class: Used for class-based tests. When applied via @pytest.mark.usefixtures('client_class'), the client is available as self.client.
    • config: Provides access to the application's app.config object.
    • live_server: Runs the application in a separate process. This is ideal for integration tests involving Selenium or other headless browsers. You can retrieve the server's URL using url_for with _external=True.
    # Using the 'client' fixture
    def test_myview(client):
        assert client.get(url_for('myview')).status_code == 200
    
    # Using 'client_class' for class-based tests
    @pytest.mark.usefixtures('client_class')
    class TestSuite:
        def test_myview(self):
            assert self.client.get(url_for('myview')).status_code == 200
  5. Set up a Flask application fixture

    master

    To use pytest-flask features, define an app fixture in your conftest.py file. This fixture should return an instance of your Flask application. Once defined, the app fixture becomes available to all tests in your suite.

    from myapp import create_app
    import pytest
    
    @pytest.fixture
    def app():
        app = create_app()
        return app
  6. Configure and manage the live_server fixture

    master

    The live_server fixture runs the app in a separate process.

    Manual Startup

    If you need to define routes dynamically during a test, you must manually start the server after configuring the app:

    def test_add_endpoint_to_live_server(live_server):
        @live_server.app.route('/test-endpoint')
        def test_endpoint():
            return 'got it', 200
    
        live_server.start()
        # ... perform requests ...

    Configuration via pytest.ini

    You can control the live server behavior using CLI flags or pytest.ini settings:

    • --no-start-live-server: Prevents the server from starting automatically. Use this to avoid high startup costs if not all tests need it.
    • --live-server-port=<port>: Use a fixed port instead of a random one.
    • --live-server-wait=<seconds>: Set the timeout (default is 5s) before a test is aborted if the server hasn't started.
    • live_server_scope: Set the fixture scope (e.g., function instead of the default session) in your pytest.ini to improve test isolation if your server holds global state.

    Example pytest.ini configuration:

    [pytest]
    addopts = --no-start-live-server --live-server-port=5000
    live_server_scope = function
  7. Test content negotiation with accept_* fixtures

    master

    To test how your API handles different media types (Content Negotiation), use the accept_* fixtures as headers in your client requests. This allows you to verify that your application returns the correct mimetype based on the Accept header.

    Available fixtures:

    • accept_any: Sends */* header.
    • accept_json: Sends application/json header.
    • accept_jsonp: Sends application/json-p header.
    def test_api_endpoint(accept_json, client):
        res = client.get(url_for('api.endpoint'), headers=accept_json)
        assert res.mimetype == 'application/json'
  8. Set up a development environment for pytest-flask

    master

    To prepare your local environment for contributing to pytest-flask, follow these steps:

    1. Fork and Clone: Fork the repository on GitHub, then clone the main repository (not your fork) to your local machine.
    2. Add Remote: Add your fork as a remote named fork to allow pushing your changes.
    3. Install Dependencies: Use tox to create a virtual environment and install pytest-flask in editable mode with development dependencies.
    4. Install Hooks: Install pre-commit hooks to ensure code quality.
    $ git clone https://github.com/pytest-dev/pytest-flask
    $ cd pytest-flask
    $ git remote add fork https://github.com/{username}/pytest-flask
    $ tox -e dev
    $ source venv/bin/activate
    $ pre-commit install