简体   繁体   English

烧瓶单元测试-如何为每个测试重置app.url_map?

[英]Flask unit testing - How to reset app.url_map for each test?

I'm writing a series of unit tests for a Flask app. 我正在为Flask应用程序编写一系列单元测试。 The setup for each test is as follows: 每个测试的设置如下:

  • Create a Flask app in testing mode ( app.testing = True ). 在测试模式下创建Flask应用( app.testing = True )。
  • Mount a test endpoint (route) on a blueprint within the test app. 将测试端点(路由)安装在测试应用程序内的蓝图上。
  • (Then, exercise some tests on the endpoint...) (然后,在端点上进行一些测试...)

The problem is that the app instance used in my tests accumulates the routes added from the previous tests instead of starting from a clean slate. 问题在于,我的测试中使用的应用程序实例会累积从先前测试中添加的路由,而不是从干净的表盘开始。 It's as if app.url_map is never reset even though I create a new app each time... 好像app.url_map永远不会重置,即使我每次都创建一个新应用...

Here's the code of my setup function, which runs before each test (I am using pytest): 这是我的设置函数的代码,该代码在每次测试之前运行(我正在使用pytest):

def setup(flask_app):
    app = flask_app

    # Mount a test endpoint on the API blueprint.
    bp = app.blueprints["api"]
    bp.add_url_rule('/foo', view_func=test_view, methods=['GET', ])

    print(app.url_map)

flask_app is a pytest fixture that creates a new test app, something like this: flask_app是一个pytest固定装置,可创建一个新的测试应用程序,如下所示:

@pytest.fixture()
def flask_app():
    from my_app import create_app
    app = create_app('testing')
    # Configure a bunch of things on app...
    return app

If I write three tests, my setup function is called three times and logs the following for app.url_map : 如果我编写了三个测试,则setup函数将被调用三次,并将以下内容记录为app.url_map

# 1st test — My new '/api/foo' rule doesn't even show yet...
# For that, I'd need to re-register the blueprint after adding the URL to it.

Map([<Rule '/' (HEAD, OPTIONS, GET) -> main.index>,
<Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>])


# 2nd test — Rule '/api/foo' added once

Map([<Rule '/' (HEAD, OPTIONS, GET) -> main.index>,
<Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>,
<Rule '/api/foo' (HEAD, OPTIONS, GET) -> api.test_view>])


# 3rd test — Rule '/api/foo' added twice

Map([<Rule '/' (HEAD, OPTIONS, GET) -> main.index>,
<Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>,
<Rule '/api/foo' (HEAD, OPTIONS, GET) -> api.test_view>],
<Rule '/api/foo' (HEAD, OPTIONS, GET) -> api.test_view>]

In my actual code (a bit more complicated), I get the following error: 在我的实际代码(稍微复杂一点)中,出现以下错误:

AssertionError: View function mapping is overwriting an existing endpoint function:
lib/flask/app.py:1068: AssertionError

Which makes sense, since I'm trying to add the same view multiple times... Why don't I get a fresh app instance every time I run a new test? 这是有道理的,因为我试图多次添加同一视图...为什么每次运行新测试时都没有得到一个新的应用程序实例?

I'm not even sure if this is Flask issue or a pytest issue... :( 我什至不确定这是Flask问题还是pytest问题... :(

I could solve a similar problem by moving all stuff you instantiate for the setup into the setup (even the import of the libraries you are using there). 我可以通过将您为安装实例化的所有内容移动到安装中(甚至导入您正在使用的库)来解决类似的问题。 Of course, this can be done in a more elegant way by having a create_app() method like you do for your whole flask application. 当然,可以像在整个烧瓶应用程序中一样使用create_app()方法,以一种更为优雅的方式完成此操作。 The important point to take away here is to take the instance that keeps the state (here the endpoints) out of the global scope and move it into the create_app() method. 这里要注意的重要一点是,将使状态(此处是端点)不在全局范围内的实例,然后将其移入create_app()方法。

Tell me if you need more information on this. 告诉我您是否需要更多信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM