flaskpytest

Simple Flask example with pytest and application factory does not work


I am new to flask and I have set up a simple flask example and two tests using pytest(see here). When I let run only one test it works, but if I run both tests it does not work.
Anyone knows why? I think I am missing here some basics of how flask works.

code structure:

from flask import Flask

def create_app():
    app = Flask(__name__)

    with app.app_context():
        from app import views

    return app
from flask import current_app as app

@app.route('/')
def index():
    return 'Index Page'

@app.route('/hello')
def hello():
    return 'Hello World!'
import pytest
from app import create_app

@pytest.fixture
def client():
    app = create_app()

    yield app.test_client()
from app import create_app

def test_index(client):
    response = client.get("/")
    assert response.data == b"Index Page"

def test_hello(client):
    response = client.get("/hello")
    assert response.data == b"Hello World!"

Solution

  • The problem is with your registration of the routes in app/views.py when you register them with current_app as app. I'm not sure how you would apply the application factory pattern without using blueprints as the pattern description in the documentation implies they are mandatory for the pattern:

    If you are already using packages and blueprints for your application [...]

    So I adjusted your code to use a blueprint instead:

    app/main/__init__.py:

    from flask import Blueprint
    
    bp = Blueprint('main', __name__)
    
    from app.main import views
    

    app/views.py -> app/main/views.py:

    from app.main import bp
    
    
    @bp.route('/')
    def index():
        return 'Index Page'
    
    
    @bp.route('/hello')
    def hello():
        return 'Hello World!'
    

    app/__init__.py:

    from flask import Flask
    
    
    def create_app():
        app = Flask(__name__)
    
        # register routes with app instead of current_app:
        from app.main import bp as main_bp
        app.register_blueprint(main_bp)
    
        return app
    

    Then your tests work as intended:

    $ python -m pytest tests
    ============================== test session starts ==============================
    platform darwin -- Python 3.6.5, pytest-6.1.0, py-1.9.0, pluggy-0.13.1
    rootdir: /Users/oschlueter/github/simple-flask-example-with-pytest
    collected 2 items                                                               
    
    tests/test_app.py ..                                                      [100%]
    
    =============================== 2 passed in 0.02s ===============================