Issue
I'm trying to migrate to py.test for the ease of use and auto-discovery of tests. When I run my tests with unittest, the test works fine. When I run the test under py.test, I get RuntimeError: working outside of application context
.
Here's the test code (test_app.py):
import unittest
from app import app
class TestAPILocally(unittest.TestCase):
def setUp(self):
self.client = app.test_client()
def testRoot(self):
retval = self.client.get('/').data
self.assertTrue('v1' in retval)
if __name__ == '__main__':
unittest.main()
And here's the stripped down file I'm testing (app.py):
from flask import Flask
from flask.ext.restful import Api, Resource
class APIListAPI(Resource):
def get(self):
return ['v1']
app = Flask(__name__)
api = Api(app)
api.add_resource(APIListAPI, '/')
As you can see, this is very similar to the docs on the flask site: the testing skeleton, and indeed, when I run it with unittest, it succeeds:
$ python tmp1/test_app.py
.
----------------------------------------------------------------------
Ran 1 test in 0.115s
OK
$
But, when I test with py.test, it fails:
$ ./py.test tmp1/test_app.py
=================== test session starts =========================
platform sunos5 -- Python 2.7.5 -- py-1.4.22 -- pytest-2.6.0
collected 1 items
tmp1/test_app.py F
========================= FAILURES ==============================
_________________ TestAPILocally.testRoot _______________________
self = <tmp1.test_app.TestAPILocally testMethod=testRoot>
def testRoot(self):
> retval = self.client.get('/').data
tmp1/test_app.py:10:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
werkzeug/test.py:762: in get
return self.open(*args, **kw)
flask/testing.py:108: in open
follow_redirects=follow_redirects)
werkzeug/test.py:736: in open
response = self.run_wsgi_app(environ, buffered=buffered)
werkzeug/test.py:659: in run_wsgi_app
rv = run_wsgi_app(self.application, environ, buffered=buffered)
werkzeug/test.py:855: in run_wsgi_app
app_iter = app(environ, start_response)
tmp1/flask/app.py:1836: in __call__
return self.wsgi_app(environ, start_response)
tmp1/flask/app.py:1820: in wsgi_app
response = self.make_response(self.handle_exception(e))
flask_restful/__init__.py:256: in error_router
if self._has_fr_route():
flask_restful/__init__.py:237: in _has_fr_route
if self._should_use_fr_error_handler():
flask_restful/__init__.py:218: in _should_use_fr_error_handler
adapter = current_app.create_url_adapter(request)
werkzeug/local.py:338: in __getattr__
return getattr(self._get_current_object(), name)
werkzeug/local.py:297: in _get_current_object
return self.__local()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
def _find_app():
top = _app_ctx_stack.top
if top is None:
> raise RuntimeError('working outside of application context')
E RuntimeError: working outside of application context
flask/globals.py:34: RuntimeError
================ 1 failed in 1.02 seconds ======================
Now, it turns out, I can make this test pass just by doing this:
$ rm tmp1/__init__.py
And make it fail again by doing this:
$ touch tmp1/__init__.py
So, is there some difference between the way that unittest and py.test handles files in modules? It seems very strange that it breaks enough to make Flask complain, as I clearly am in an app context calling app.test_client().get(). Is this expected behavior, or should I file a bug against py.test?
In case it's relevant, the reason I'm executing the tests from the parent directory is because I don't have the ability to add modules to site-packages, so I'm initiating all my code from the parent directory, where I've installed Flask, py.test, etc.
Edit: Solved. It was an installation problem. Adding pythonpath tag, since that was the solution.
Solution
In case it's relevant, the reason I'm executing the tests from the parent directory is because I don't have the ability to add modules to site-packages, so I'm initiating all my code from the parent directory, where I've installed Flask, py.test, etc.
It turns out that this was very relevant. Because my code would eventually be run by a daemon, I wasn't sure I could depend on PYTHONPATH, and I didn't want to change sys.path at the top of each file. So, I was installing the package tarballs, and adding symlinks where necessary to make the packages importable.
It turns out the structure required to make the unittest code find flask was:
./Flask-0.10.1/
./flask -> Flask-0.10.1/flask/
./tmp1/flask -> ../Flask-0.10.1/flask/
The last line was required by unittest, and it was that symlink that broke py.test.
When I just put the packages in their own directory, and set the PYTHONPATH, everything works. If I can't control the environment to use PYTHONPATH for the daemon, I'll bite the bullet, and add the sys.path modication everywhere.
So, bottom line is, it was an installation problem.
Answered By - John Hazen
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.