Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Running Single Flask Unittest Passes but Running All Tests Gives AssertionError

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.

like image 963
ericso Avatar asked Dec 15 '25 02:12

ericso


1 Answers

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.

like image 145
ericso Avatar answered Dec 16 '25 18:12

ericso



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!