6

我有很多简单的 Django 视图,如下所示:

@team_leader_required
def view_all_teams(request):
    teams = Team.objects.all()

    template_vars = {'toolbar': 'teams',
                     'teams': teams}
    return render(request, "all_teams.html", template_vars)

我最终编写了很多形式的单元测试:

def test_view_all_teams_renders(self):
    user = self.create_team_leader()
    self.log_in(user)

    response = self.client.get(reverse('all_teams'))
    self.assertHttp200(response)

尽管我有创建用户的便捷方法(例如.create_team_leader)和各种便捷断言(例如.assertHttp200),但我的测试中仍然有很多重复。

(我的测试很简单,因为我看不到任何其他有用的东西可以断言这些视图 -TestCase.assertTemplateUsed如果重命名模板会中断,即使视图是正确的。)

很容易错过测试,这让我在重命名模板时没有信心。有什么办法可以自动生成测试用例?类似(伪代码):

for every view in urls:
    if view doesn't take extra arguments:
        test that view returns 200 when a logged in superuser does a GET

编辑

这是我的 urls.py 中的一个代表性片段:

urlpatterns = patterns('',
    url(r'^teams/$', 'teams.views.view_all_teams', name='all_teams'),
    url(r'^teams/major/$', 'teams.views.view_major_teams', name='major_teams'),
    url(r'^teams/minor/$', 'teams.views.view_minor_teams', name='minor_teams'),
    url(r'^teams/(?P<team_id>\d+)/$', 'teams.views.view_team', name='view_team'),
    url(r'^teams/(?P<team_id>\d+)/edit$', 'teams.views.edit_team', name='edit_team'),
    url(r'^teams/(?P<team_id>\d+)/delete$', 'teams.views.delete_team', name='delete_team'),

我想自动测试此列表中的前三个视图。

4

1 回答 1

3
from django.core import urlresolvers
from django.test import TestCase


class SimpleTest(TestCase):
    def test_simple_views(self):
        url_names = [
            'all_teams',
            'major_teams',
            'minor_teams',
            'view_team',
            'edit_team',
        ]

        user = self.create_team_leader()
        self.log_in(user)

        for url_name in url_names:
            try:
                url = urlresolvers.reverse(url_name, args=(), kwargs={})
            except urlresolvers.NoReverseMatch:
                #print('Pass {}'.format(url_name))
                continue

            #print('Try {}'.format(url_name))
            response = self.client.get(url)
            self.assertHttp200(response)

如果所有 url 模式都有他们的名字,你可以使用下面的代码来定义url_names

url_names = [p.name for p in teams.urls.urlpatterns]

已知的问题

  • 如果视图功能失败,您将不知道哪个视图失败。
  • 失败视图旁边的视图将不会被测试。

处理上述问题的另一个版本。

import unittest

from django.core import urlresolvers
from django.test import TestCase

from teams.urls import urlpatterns


class SimpleTest(TestCase):
    ...

    def setUp(self):
        user = self.create_team_leader()
        self.log_in(user)

    url_names = [p.name for p in urlpatterns]
    vs = vars()
    def make_test_function(idx, url_name, url):
        def  t(self):
            response = self.client.get(url)
            self.assertHttp200(response)
        t.__name__ = 'test_' + idx
        t.__doc__ = 'simple get test for ' + url_name
        return t

    for i, url_name in enumerate(url_names):
        i = str(i)
        try:
            url = urlresolvers.reverse(url_name, args=(), kwargs={})
            vs['test_' + i] = make_test_function(i, url_name, url)
        except urlresolvers.NoReverseMatch as e:
            vs['test_' + i] = unittest.skip(url_name + ' requires parameter(s) or view not found')(lambda: 0)

    del url_names, vs, make_test_function,
于 2013-06-19T15:34:12.687 回答