【问题标题】:Running Single Flask Unittest Passes but Running All Tests Gives AssertionError运行单个 Flask 单元测试通过但运行所有测试给出 AssertionError
【发布时间】:2023-03-21 11:03:02
【问题描述】:

我有使用 Flask-Restful 库的 Flask 应用程序。我的应用程序结构设置如下:

server
 application.py
- app
   users.py
  - tests
     test_users.py
- common
   tests.py

我的应用程序设置在application.py 中定义。我正在使用工厂模式。

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

在 users.py 中,我有我的资源子类:

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')

请查看我的github 页面以获取完整代码。

我在common/tests.py 之后设置了我的单元测试类snippet

我使用 Nose 运行我的测试。当我运行任何单个测试时,它都会通过。当我使用

运行所有测试时
$ nosetests

我收到以下错误:

AssertionError: View function mapping is overwriting an existing endpoint function: users

我认为该错误是由测试运行程序在注册另一个 Flask-Restful 资源后尝试注册的。在 users.py 中,我有两个 Resource 子类:UsersListAPIUsersAPI。 (如果你看到 github 页面,我在 trips.py 中也有相同的设置。)

我认为运行单个 TestCase 不会引发错误,因为我在基本情况下为 TestCase 调用了一次 _pre_setup(),其中创建了测试应用程序,但我仍然会收到错误,例如,我运行测试:

$ nosetests app.tests.test_users:UsersTest

我仍然收到AssertionError

有什么想法吗?

编辑:这是我的测试文件。

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()

注意我是从flask.ext.testing 和unittest 中导入TestCase,显然在实际运行测试时不会同时导入。当我从 flask.ext.testcase 导入时,单个测试失败。从 unittest 导入单个测试通过:

$ nosetests app.tests.test_users:UsersTest.test_get_all_users

在这两种情况下,运行所有测试或仅运行 UsersTest 测试用例,测试都会失败。实际的测试文件 test_users.py 很长。我会将其作为gist 提供。我已经删除了所有多余的代码,只留下了两个测试。如果您想查看完整的测试文件,请访问我的 github repo

【问题讨论】:

  • 你能发布你的测试文件吗?你在 TestCase 的 setup/create_app 方法中做了什么?
  • 我尝试运行两个测试“nosetests --tests=app.tests.test_users:UsersTest.test_get_user_by_username,app.tests.test_users:UsersTest.test_get_all_users”。第一个测试通过,第二个测试失败,出现同样的 AssertionError。我真的认为测试运行程序以某种方式试图实例化测试应用程序的另一个副本。
  • 我发现了这个:github.com/mitsuhiko/flask/issues/1046,这和我的问题非常相似。然而,在这种情况下,问题是 views.py 文件被导入了两次,导致对 api.add_resource() 的调用两次。就我而言,我将 add_resource 调用包装在 create_app 中调用的函数中。
  • 如果我使用 unittest.TestCase 并一次运行两个测试,第一个测试通过(没有 AssertionError),第二个抛出错误。如果我使用flask.ext.testing.TestCase,第一个测试将失败,因为由于某种原因它尝试创建应用程序两次。

标签: python flask nosetests flask-restful


【解决方案1】:

想通了:

我必须将api = Api(prefix='/api/v0') 行移到create_app 函数中,并将add_resource 函数也移到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

api 对象不再是全局对象,但我认为我不需要其他地方。

【讨论】:

    猜你喜欢
    • 2017-10-12
    • 2013-07-29
    • 1970-01-01
    • 2011-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-08
    • 1970-01-01
    相关资源
    最近更新 更多