如何批量测试Django HTML模板返回200,解决URLResolver无name属性报错
问题根因
- 你的Django项目根路由里使用了
include()导入子路由(比如你报错里的account.urls),此时urlpatterns列表里会同时存在两种对象:URLPattern:对应单个直接定义的路由,存在name属性URLResolver:对应子路由集合,本身没有name属性,需要递归遍历它的内置url_patterns才能拿到子路由里的单个URLPattern对象
- 你直接遍历根
urlpatterns取name属性,碰到URLResolver对象时就会触发属性不存在的报错;直接把URLResolver对象传给reverse方法也会因为参数类型错误抛出异常
修复代码
你需要先写一个递归函数提取项目中所有带name属性的路由,再批量测试,示例代码如下:
from django.test import SimpleTestCase, Client from django.urls import reverse, URLPattern, URLResolver from foo.urls import urlpatterns class TemplateLoadTest(SimpleTestCase): # 递归提取所有路由名称 def get_all_url_names(self, patterns, parent_namespace=None): url_names = [] for entry in patterns: if isinstance(entry, URLPattern): if entry.name: # 处理带命名空间的路由 if parent_namespace: full_name = f"{parent_namespace}:{entry.name}" else: full_name = entry.name url_names.append(full_name) elif isinstance(entry, URLResolver): # 递归遍历子路由 child_namespace = entry.namespace if parent_namespace and child_namespace: full_namespace = f"{parent_namespace}:{child_namespace}" else: full_namespace = child_namespace or parent_namespace url_names.extend(self.get_all_url_names(entry.url_patterns, full_namespace)) return url_names def test_all_templates_load(self): client = Client() # 如果页面需要登录权限,先执行登录 # client.login(username="test", password="test123") all_url_names = self.get_all_url_names(urlpatterns) for url_name in all_url_names: try: # 无参数的路由直接反向解析 url_path = reverse(url_name) response = client.get(url_path) self.assertEqual(response.status_code, 200, f"路由{url_name}({url_path})访问异常") print(f"{url_path} Status Code: {response.status_code}") except: # 跳过带路径参数无法直接解析的路由,你也可以自行构造参数传入reverse测试 print(f"跳过需参数的路由:{url_name}")
补充说明
- 上述代码默认跳过需要传路径参数的路由,如果你需要测试这类路由,可以在异常捕获分支补充合法参数,例如
reverse(url_name, kwargs={"id":1}) - 如果你的页面需要登录后才能访问,取消
client.login行的注释,填入测试账号的用户名密码即可 - 如果你要测试的路由存在仅支持POST请求的情况,需要自行调整请求方法,或者过滤掉这类接口
内容的提问来源于stack exchange,提问作者Cade
相关产品推荐
相关产品推荐

