如何对 django url 进行单元测试?

Posted

技术标签:

【中文标题】如何对 django url 进行单元测试?【英文标题】:How do I unit test django urls? 【发布时间】:2013-09-29 23:46:08 【问题描述】:

除了urls.py 之外,我的应用程序在所有地方都实现了 100% 的测试覆盖率。对于如何为我的 URL 编写有意义的单元测试,您有什么建议吗?

FWIW 这个问题出现在我正在试验测试驱动开发并希望在我编写代码修复它们之前失败的测试。

【问题讨论】:

【参考方案1】:

一种方法是reverse URL 名称并验证

例子

urlpatterns = [
    url(r'^archive/(\d4)/$', archive, name="archive"),
    url(r'^archive-summary/(\d4)/$', archive, name="archive-summary"),
]

现在,在测试中

from django.urls import reverse

url = reverse('archive', args=[1988])
assertEqual(url, '/archive/1988/')

url = reverse('archive-summary', args=[1988])
assertEqual(url, '/archive-summary/1988/')

无论如何,您可能正在测试视图。

现在,要测试 URL 是否连接到正确的视图,您可以使用 resolve

from django.urls import resolve

resolver = resolve('/summary/')
assertEqual(resolver.view_name, 'summary')

现在在变量resolverResolverMatch 类实例)中,您有以下选项

 'app_name',
 'app_names',
 'args',
 'func',
 'kwargs',
 'namespace',
 'namespaces',
 'url_name',
 'view_name'

【讨论】:

仅供参考,我的同事已经接受了这个概念,并在our new unittest testing utils library 中为它创建了一个"assert"。 我正在使用:assertEqual(resolver.func.func_name, 'archive') 来测试解析器是否位于正确的视图上。据我了解resolver.view_name实际上是url规则的名称,而不是视图。 您是否提倡在 Django 测试中使用reverse(...) 作为一般的 url 测试(即视图),或者只是在这种情况下专门用于单元测试 url?我看到它在视图测试中被大量使用,但感觉像是一种反模式。 是什么让你认为这是一个反模式@tedmiston? 因为我可以更改 url 中的 1 个字符来破坏我的 API,但所有测试仍然会通过。我想我们可以用一个简单的 assert equals 对每条路由进行单元测试......我只是以前没见过这样做。【参考方案2】:

只是补充@karthikr 的答案(基于他的)

->你可以断言负责解析的视图是你期望使用resolver.func.cls的视图

例子

from unittest import TestCase
from django.urls import resolve

from foo.api.v1.views import FooView


class TestUrls(TestCase):
    def test_resolution_for_foo(self):
        resolver = resolve('/api/v1/foo')
        self.assertEqual(resolver.func.cls, FooView)

【讨论】:

那么view_name是什么? @AlanH 老实说我不会断言这个名字 虽然它可能感觉很脆弱,但在名称上断言是一种记录在案的方法。只是值得思考。 docs.djangoproject.com/en/3.2/topics/testing/tools【参考方案3】:

对不起,我发现这个地方是第一个在关键词“django url testing”下的地方。

我完全同意我的前辈的观点,但我也确信有更好的方法来测试您的 URL。我们不应该使用“resolver = resolve('url/path')”的主要原因是当视图的名称更固定时,路径会比较流畅。

简单来说,这样更好:

class TestUrls(TestCase):

    def test_foo_url_resolves(self):
        url = reverse('bar:foo')
        self.assertEqual(resolve(url).func.view_class, FooBarView)

'bar:foo' - bar 是命名空间,foo 是视图名称

比这个

class TestUrls(TestCase):
    def test_resolution_for_foo(self):
        resolver = resolve('/api/v1/foo')
        self.assertEqual(resolver.func.cls, FooView)

【讨论】:

以上是关于如何对 django url 进行单元测试?的主要内容,如果未能解决你的问题,请参考以下文章

如何对 Django South“数据迁移”进行单元测试

如何在 django 中对文件上传进行单元测试

如何在 django-rest-framework 中对权限进行单元测试?

如何对 ETL 流程进行测试(单元测试)?

Django 使用 ForeignKey 形成单元测试

如何对第一个Vue.js组件进行单元测试 (上)