When using Google App Engine 1.6.4 testbed with Flask 0.8, and in particular the Flask-Login 0.1 package (source), I encounter a strange problem with command-line unit testing.
Below is an example that demonstrates the problem. Note the commented line (from google.appengine.ext import testbed
). When this line is commented, the tests work as expected.
When this line is uncommented, the @login_required
decorator for Flask-Login
stops recognizing the logged-in user i.e. current_user.is_authenticated()
returns False. It would seem the culprit is importing testbed
.
#!/usr/bin/env python2.7
import unittest
import sys
from flask import Flask, current_app, url_for
from flaskext import login
sys.path.append('/usr/local/google_appengine')
# Go ahead and uncomment this:
# from google.appengine.ext import testbed
app = Flask('test')
app.secret_key = 'abc'
login_manager = login.LoginManager()
login_manager.setup_app(app)
login_manager.login_view = 'index'
class User(login.UserMixin):
def get_id(self):
return "1"
@login_manager.user_loader
def load_user(user_id):
return User()
@app.route('/')
@login.login_required
def index():
pass
@login_manager.unauthorized_handler
def unauthorized():
raise Exception("Unauthorized.")
class MyTest(unittest.TestCase):
def setUp(self):
self.app = app
self.client = app.test_client()
def test_user(self):
with self.app.test_request_context():
logged_in = login.login_user(User())
r = self.client.get('/')
if __name__ == '__main__':
unittest.main()
The specific exception is:
ERROR:test:Exception on / [GET]
Traceback (most recent call last):
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/Flask-0.8-py2.7.egg/flask/app.py", line 1504, in wsgi_app
response = self.full_dispatch_request()
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/Flask-0.8-py2.7.egg/flask/app.py", line 1264, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/Flask-0.8-py2.7.egg/flask/app.py", line 1262, in full_dispatch_request
rv = self.dispatch_request()
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/Flask-0.8-py2.7.egg/flask/app.py", line 1248, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/Flask_Login-0.1-py2.7.egg/flaskext/login.py", line 479, in decorated_view
return current_app.login_manager.unauthorized()
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/Flask_Login-0.1-py2.7.egg/flaskext/login.py", line 250, in unauthorized
return self.unauthorized_callback()
File "./test.py", line 34, in unauthorized
raise Exception("Unauthorized.")
Exception: Unauthorized.
The behaviour I would expect is that importing (and using) testbed
would have no effect on the Flask context stack and, by extension, Flask-Login would continue to work in the unit testing environment even though testbed
has been imported.
I have stared at this for a bit, to no avail, and would be grateful for any insight and suggestions for potential solutions to this problem.
Thank you for reading.
The testbed uses separate stubs for many of the GAE services, including the datastore and user service.
I'm not familiar with flask, but if the login requires a user to exist in the database, it'll fail since the testbed uses a separate database. You'll have to load user data into the testbed database first.
Also if you include the testbed, there's some initialization calls you have to make to set up the stubs before you can use it. https://developers.google.com/appengine/docs/python/tools/localunittesting
class User
in the degenerate example above. As mentioned, the problem is not using testbed
, but that merely importing it breaks Flask-Login
- Brian M. Hunt 2012-04-03 20:32
testbed
that is called. The questions is what. I've debugged from top to bottom in pdb a few times but didn't hit it - the problem seems buried somewhere in Werkzeug. I have used evil monkey patches in the interim. : - Brian M. Hunt 2012-04-04 00:26
flask.g
and other associated variables seem to also be unavailable - Brian M. Hunt 2012-04-03 21:59