Django测试,模拟对URL

时间:2016-07-26 12:20:59

标签: python django unit-testing

我的urls.py文件中有一堆url,其中包含login_required装饰器

# Index Page
url(r'^$', login_required(views.IndexPage.as_view()), name='index'),

# Schedule urls
url(r'^schedules/$', login_required(views.ScheduleListView.as_view()),
    name='schedule-list'),
url(r'^schedule/(?P<pk>[\d]+)/$',
    login_required(views.ScheduleDetailView.as_view()),
    name='schedule-detail'),
url(r'^schedule-freeze/(?P<pk>[\d]+)/$',
    login_required(views.freezeSchedule),
    name='schedule-freeze'),
url(r'^schedule-create/$', login_required(views.ScheduleCreate.as_view()),
    name='schedule-create'),
url(r'^schedule-delete/(?P<pk>[\d]+)$',
    login_required(views.ScheduleDelete.as_view()),
    name='schedule-delete'),
url(r'^schedule-update/(?P<pk>[\d]+)/$',
    login_required(views.ScheduleUpdate.as_view()),
    name='schedule-update'),
url(r'^schedule-generate/(?P<pk>[\d]+)/$',
    login_required(views.scheduleGenerate), name='schedule-generate'),

# Client urls
url(r'^clients/$', login_required(views.ClientList.as_view()),
    name='client-list'),
url(r'^client/(?P<slug>[\w-]+)/$',
    login_required(views.ClientDetail.as_view()), name='client-detail'),
url(r'^client-create/$', login_required(views.ClientCreate.as_view()),
    name='client-create'),
url(r'^client-delete/(?P<slug>[\w-]+)/$',
    login_required(views.ClientDelete.as_view()), name='client-delete'),
url(r'^client-update/(?P<slug>[\w-]+)/$',
    login_required(views.ClientUpdate.as_view()), name='client-update'),

# And so on ....

对于每个受限制的视图,我正在尝试编写一个测试,以确保在尝试访问视图时将未经授权的用户重定向到登录页面。如果可能的话,我希望能够在一个代码块中实现这一点,而不是为每个URL编写一个测试。

我尝试过以下内容:

list_urls = [e for e in get_resolver(urls).reverse_dict.keys() if isinstance(e, str)]

for url in list_urls:
    # Fetches the urlpath e.g. 'client-list'
    namedspaced_url = 'reports:' + url
    path = reverse(namedspaced_url)
    response = self.client.get(path)
    self.assertEqual(response.status_code, 302)
    self.assertRedirects(response, reverse('login') + '?next=' + path)

list_urls会返回我的urls.py文件中所有已命名网址的列表,即['schedule-create', 'server-detail', 'schedule-list', 'schedule-update', 'index', ....]

问题

这段代码:reverse(namedspaced_url)

这导致问题的原因是每个网址都有不同的正则表达式模式,即有些网站采取了一些pk的

所以行path = reverse(namedspaced_url)适用于那些指向ListViews的简单URL,但是对于更复杂的URL会失败,例如那些指向需要slug / pk的DetailViews的URL,即path = reverse(namedspaces_url, args=[1945]) < / p>

是否可以暂时覆盖/忽略Django的模式匹配/路由以强制请求通过(无论传递的args如何)

或者我是否必须使用有效的kwargs / args为每个URL手动编写测试以满足正则表达式?

我可以采用另一种完全不同的方法为我的所有login_required()视图编写测试吗?

更新 使用内省我想出了以下怪物来解决我的问题

def test_page_redirects_for_unauthorised_users(self):
    url_dict = get_resolver(urls).reverse_dict
    url_list = [e for e in get_resolver(urls).reverse_dict.keys() if
                isinstance(e, str)]
    for url in url_list:
        patterns = url_dict[url][0][0][1]
        matches = [1 if e == 'pk' else "slug" if e == 'slug' else None for
                   e in patterns]
        path = reverse('reports:' + url, args=matches)
        response = self.client.get(path)
        self.assertEqual(response.status_code, 302)
        self.assertRedirects(response, reverse('login') + '?next=' + path)

2 个答案:

答案 0 :(得分:2)

您尝试测试一些非常复杂的内容,因为您决定使用login_requireddecorate the urlconf

为什么不decorate the class呢?这样你就可以简单地测试每个类,以确保它具有login_required装饰器。这消除了模拟slug和pk正则表达式值的需要。

答案 1 :(得分:1)

在proect_name / project_name / urls.py中 urlpatterns = [ url(r'', login_required(include('app_name.urls')), ]

这会将login_required应用于project_name / app_name / urls.py中的所有网址