测试Flask路线确实存在和不存在

时间:2015-07-29 20:03:00

标签: python unit-testing testing flask

我正在创建大量Flask路线using regular expressions。我想要进行单元测试,检查是否存在正确的路由以及错误的路由404.

这样做的一种方法是启动本地服务器并使用urllib2.urlopen等。但是,我希望能够在Travis上运行这个测试,我假设这不是一个选择。

我可以通过另一种方式在我的应用程序上测试路线吗?

3 个答案:

答案 0 :(得分:11)

在您的单元测试中使用Flask.test_client() object。该方法返回FlaskClient instance(a werkzeug.test.TestClient subclass),使测试路线变得微不足道。

调用TestClient的结果是Response object,以查看它是否为200或404响应测试Response.status_code attribute

with app.test_client() as c:
    response = c.get('/some/path/that/exists')
    self.assertEquals(response.status_code, 200)

with app.test_client() as c:
    response = c.get('/some/path/that/doesnt/exist')
    self.assertEquals(response.status_code, 404)

请参阅Flask文档的Testing Flask Applications chapter

答案 1 :(得分:2)

马尔金的答案肯定会解决您的问题,但有时您没有时间(或将会)模拟您想要测试存在的路线中调用的所有组件。

为什么你需要模拟?那么,调用get('some_route')将首先检查此路由是否存在然后......它将被执行!

如果视图是一个复杂的视图,你需要有固定装置,envs变量和任何其他准备测试路线是否存在,那么你需要再考虑一下你的测试设计。

如何避免这种情况:

您可以列出应用中的所有路线。检查您正在测试的那个是否在列表中。

在下面的示例中,您可以通过实施站点地图来实现这一点。

from flask import Flask, url_for

app = Flask(__name__)

def has_no_empty_params(rule):
    defaults = rule.defaults if rule.defaults is not None else ()
    arguments = rule.arguments if rule.arguments is not None else ()
    return len(defaults) >= len(arguments)


@app.route("/site-map")
def site_map():
    links = []
    for rule in app.url_map.iter_rules():
        # Filter out rules we can't navigate to in a browser
        # and rules that require parameters
        if "GET" in rule.methods and has_no_empty_params(rule):
            url = url_for(rule.endpoint, **(rule.defaults or {}))
            links.append((url, rule.endpoint))
    # links is now a list of url, endpoint tuples

参考:

get a list of all routes defined in the app

Helper to list routes (like Rail's rake routes)

答案 2 :(得分:1)

测试URL而不执行附加视图功能的另一种方法是使用match中的方法MapAdapter

from flask import Flask

app = Flask(__name__)

@app.route('/users')
def list_users():
    return ''

@app.route('/users/<int:id>')
def get_user(id):
    return ''

测试

# Get a new MapAdapter instance. For testing purpose, an empty string is fine
# for the server name.
adapter = app.url_map.bind('')

# This raise werkzeug.exceptions.NotFound.
adapter.match('/unknown')

# This raises werkzeug.exceptions.MethodNotAllowed,
# Although the route exists, the POST method was not defined.
adapter.match('/users', method='POST')

# No exception occurs when there is a match..
adapter.match('/users')
adapter.match('/users/1')

来自Werkzeug文档:

  

如果存在匹配项,您将得到一个元组(端点,参数)。

在某些测试方案中可能有用。