I'm currently working on unit testing a Flask application using pytest. However, when I attempt to test my routes (seemingly any of my routes), I consistently receive a 404 Not Found error, despite the route being defined and working as expected outside of the testing environment. I've checked the route registration and application factory setup but haven't found the cause of the issue.
Environment:
Flask 2.x pytest Python 3.x
config.py;
class Config:
SQLALCHEMY_TRACK_MODIFICATIONS = False
class DevelopmentConfig(Config):
SQLALCHEMY_DATABASE_URI = 'sqlite:////path/to/development.db'
DEBUG = True
class TestingConfig(Config):
TESTING = True
SQLALCHEMY_DATABASE_URI = 'sqlite:///:memory:'
SQLALCHEMY_TRACK_MODIFICATIONS = False
app.py (simplified for brevity):
def create_app(config_class=DevelopmentConfig):
app = Flask(__name__)
app.config.from_object(config_class) # Load the configuration from the provided class
app.config['SQLALCHEMY_DATABASE_URI'] = config_class.SQLALCHEMY_DATABASE_URI
app.config['SECRET_KEY'] = 'your_secret_key'
# Initialize extensions with the app
db.init_app(app)
migrate.init_app(app, db)
return app
app = create_app()
@app.route('/login', methods=['GET', 'POST'])
def login():
# Route implementation
return render_template('login.html')
test_app.py:
import pytest
from apis.stockpulse.app import create_app
from apis.stockpulse.config import TestingConfig
@pytest.fixture
def client():
app = create_app(TestingConfig)
with app.test_client() as client:
with app.app_context():
yield client
def test_login_get(client):
response = client.get('/login')
assert response.status_code == 200 # Fails with 404
Problem:
When running the test for the /login route, pytest returns a 404 status code, even though the route is correctly defined. I've attempted to debug by printing out all registered routes using app.url_map in the fixture, and it appears that only the default static route is registered.
Attempts to Solve:
Verified the route is correctly defined and works outside of testing. Ensured the TestingConfig is correctly applied, with TESTING = True. Checked for correct application context in tests. Attempted to explicitly print registered routes, which only showed the static route.
I'm at a loss for what's causing this issue. Could it be related to how I'm initializing the app for testing or perhaps something to do with the application context not properly encapsulating the route definitions? Any insights or suggestions would be greatly appreciated.
appdefined in app.py andappcreated within theclientfixture are two differentFlaskinstances, and the instance from the fixture doesn't have the route applied via the@app.routedecorator.The solution is to use the same
appobject from app.py in your tests. That obviously means that you would need to change the way the application is configured so that it usesTestConfig. Unfortunately, the way I used to configure Flask when I was working with it is too complex to describe in this answer, and I don't have an alternative good solution on hand.Therefore, take the following code sample rather as a crude fix and NOT as a solid example for production code: