发现功能
def blueprint_site_map(app, blueprint, all_methods=False):
'''
utilizes Flask's built-in rule mapper to generate a
site-map of the application, returning a list of dicts, ex.
{
'endpoint' : repr(Blueprint)
'methods' : list
'rule' : /route
{
'''
reply = []
rules = list(app.url_map.iter_rules())
ignored_methods = set(() if all_methods else ('HEAD', 'OPTIONS'))
rule_methods = [','.join(sorted(rule.methods - ignored_methods)) for rule in rules]
for rule, methods in zip(rules, rule_methods):
if (rule.endpoint != 'static') and (rule.endpoint.startswith(blueprint)):
reply.append(dict(endpoint=rule.endpoint, methods=methods.split(','), rule=rule.rule))
return reply
样本输出
>>> blueprint_site_map(app, 'my_blueprint')
[
{
'endpoint': 'my_blueprint.foo',
'methods': ['GET', 'POST'],
'rule': '/auth/foo'
},
{
'endpoint': 'my_blueprint.bar',
'methods': ['DELETE', 'GET', 'POST'],
'rule': '/auth/bar'
}
]
用法
def test_my_blueprint_is_protected(client):
from flask import current_app as app
obj = blueprint_site_map(app, 'my_blueprint')
for each in obj:
for method in each['methods']:
func = getattr(client, method)
url = each['rule'] # *see note
kwargs = {} # inject headers, etc if needed
response = func(url, **kwargs)
assert response.status_code == 401
应该注意的是,如果您使用任何参数化的 URL 规则,例如允许两者/foo
,/foo/<string:s>
那么您将需要手动模板化或过滤掉这些规则。该blueprint_site_map
函数将包含单独的列表元素/foo
和/foo/<string:s>
,从字面上看会导致测试客户端本身或您的路由逻辑出现问题。
发现功能的设计方式是,您可以根据需要将此约定用于尽可能多的不同蓝图,就您使用蓝图约定的本质而言,这意味着您可以保持单元测试与应用程序一样模块化。
干杯!