Running Single Flask Unittest Passes, but running all tests gives an AssertionError
I have a Flask application that uses the Flask-Restful library. I have my application structure configured like this:
server
application.py
- app
users.py
- tests
test_users.py
- common
tests.py
My app setup is defined in application.py
. I am using 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 user.py, I have 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 the github page for the complete code.
I have set up the unit test class in common/tests.py
by following this snippet .
I am running my tests with Nose. When I run any one test, it passes. When I run all tests using
$ nosetests
I am getting the following error:
AssertionError: View function mapping is overwriting an existing endpoint function: users
I think the error is caused by a test trying to register another Flask-Restful resource after they are already 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 trip.py.)
I thought that running one TestCase would not result in an error because I call _pre_setup()
in the base case once for TestCase where the test application is created, but I still get the error if, for example, I run the test:
$ nosetests app.tests.test_users:UsersTest
I am still getting AssertionError
.
Any thoughts?
Edit: Here are my test files.
Basic test file with 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 am importing TestCase from flask.ext.testing and unittest, obviously not at the same time the testing is actually being done. When I import from flask.ext.testcase, the single test fails. The import from unittest goes through one pass:
$ nosetests app.tests.test_users:UsersTest.test_get_all_users
In both cases, all tests run, or just the UsersTest test case, the tests fail. The actual test file test_users.py is very long. I'll put it as a gist . I removed all the extra code and left only two tests. If you want to see the complete test file, it's on my github repo .
source to share
It revealed:
I need to move a line api = Api(prefix='/api/v0')
to a function create_app
and move functions add_resource
to create_app
:
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 object is api
no longer global, but I don't think I need it elsewhere.
source to share