I have Flask application that uses the Flask-Restful library. I have a my app structure set up like so:
server
application.py
- app
users.py
- tests
test_users.py
- common
tests.py
My application set up is defined in application.py. I'm using the Factory pattern.
api = Api(prefix='/api/v0')
def create_app(config_filemane):
flask_app = Flask(__name__)
flask_app.config.from_object(config_filemane)
db.init_app(flask_app)
from app.users import add_user_resources
add_user_resources()
api.init_app(flask_app)
return flask_app
In users.py, I have my Resource subclasses:
class UserListAPI(Resource):
def __init__(self):
super(UserListAPI, self).__init__()
def get(self):
def post(self):
class UserAPI(Resource):
def __init__(self):
super(UserAPI, self).__init__()
def get(self, id):
def put(self, id):
def delete(self, id):
def add_user_resources():
api.add_resource(UserListAPI, '/users', endpoint='users')
api.add_resource(UserAPI, '/users/<id>', endpoint='user')
Please see my github page for the full code.
I set up my unit test class in common/tests.py following this snippet.
I run my tests using Nose. When I run any single test, it passes. When I run all tests using
$ nosetests
I get the following error:
AssertionError: View function mapping is overwriting an existing endpoint function: users
I think the error is being caused by the test runner trying to register another Flask-Restful resource after they have already been registered. In users.py, I have two Resource subclasses: UsersListAPI and UsersAPI. (If you see the github page, I also have the same setup in trips.py.)
I thought that running a single TestCase would not raise the error, because I'm calling _pre_setup() in the base case once for the TestCase, where the test app is created but I still get the error if, for instance, I run the test:
$ nosetests app.tests.test_users:UsersTest
I still get the AssertionError.
Any thoughts?
Edit: Here are my test files.
The base test file at common/tests.py:
from flask.ext.testing import TestCase
from unittest import TestCase
from application import create_app
class BaseTestCase(TestCase):
def __call__(self, result=None):
self._pre_setup()
super(BaseTestCase, self).__call__(result)
self._post_teardown()
def _pre_setup(self):
self.app = create_app('settings_test')
self.client = self.app.test_client()
self._ctx = self.app.test_request_context()
self._ctx.push()
def _post_teardown(self):
self._ctx.pop()
Note I'm importing TestCase from both flask.ext.testing and unittest, obviously not both at the same time when actually running the tests. When I import from flask.ext.testcase, the single test fails. Importing from unittest the single test passes:
$ nosetests app.tests.test_users:UsersTest.test_get_all_users
In both cases, running all tests or just the UsersTest test case, the tests fail. The actual test file, test_users.py is very long. I'll provide it as a gist. I've removed all superfluous code and left only two tests. If you would like to see the full test file, it is at my github repo.
Figured it out:
I have to move the line api = Api(prefix='/api/v0') into the function create_app and moved the add_resource functions into create_app as well:
def create_app(config_filemane):
flask_app = Flask(__name__)
...
api = Api(prefix='/api/v0')
api.add_resource(UserListAPI, '/users', endpoint='users')
api.add_resource(UserAPI, '/users/<id>', endpoint='user')
...
return flask_app
The api object is no longer global but I don't think I'll need to elsewhere.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With