Terrence Young Terrence Young - 24 days ago 6x
Python Question

404 Response when running FlaskClient test method

I'm baffled by this. I'm using an application factory in a Flask application and under the test configuration my routes always return 404s.

However when I use Flask-Script and load the app from the interpreter everything works as expected, the response comes back as 200.

Navigating to the URL with the browser works fine


def create_app():
app = Flask(__name__)
return app


from flask import Flask
from flask_script import Manager
from app import create_app

app = create_app()
app_context = app.app_context()
manager = Manager(app)

def index():
return '<h1>Hello World!</h1>'

def user(name):
return '<h1>Hello, %s!</h1>' % name

def test():
"""Run the unit tests"""
import unittest
tests = unittest.TestLoader().discover('tests')

if __name__ == '__main__':


#imports committed
def setUp(self):
self.app = create_app('testing')
self.app_context = self.app.app_context()
self.client = self.app.test_client()

def test_app_exists(self):
response = self.client.get('/', follow_redirects=True)
print(response) #404 :(
self.assertTrue("Hello World!" in response.get_data()) #this is just an example of how it fails


You're not using the factory pattern correctly. You should use blueprints to collect routes and register them with the app in the factory. (Or use app.add_url_rule in the factory.) Nothing outside the factory should affect the app.

Right now you create an instance of the app and then use that instance to register routes. Then you create a different instance in your tests, which doesn't have the routes registered. Since that instance doesn't have any registered routes, it returns 404 for requests to those urls.

Instead, register your routes with a blueprint, then register the blueprint with the app in the factory. Use the factory to create an app during tests. Pass the factory to the Flask-Script manager. You should not need to push the app context manually.

bp = Blueprint('myapp', __name__)

def index():
    return 'Hello, World!'

def create_app(config='dev'):
    app = Flask(__name__)
    # config goes here


    return app

class SomeTest(TestCase):
    def setUp(self):
        self.app = create_app(config='test')
        self.client = self.app.test_client()

    def test_index(self):
        rv = self.client.get('/')
        self.assertEqual(rv.data, b'Hello, World!')

manager = Manager(create_app)
manager.add_option('-c', '--config', dest='config', required=False)

if __name__ == '__main__':