【问题标题】:django.test.client got 404 error on existing urldjango.test.client 在现有 url 上得到 404 错误
【发布时间】:2015-03-26 05:17:50
【问题描述】:

我刚开始学习单元测试并遇到了这个问题。

我得到了这样的项目结构(现在是 Django 1.6.2):

./manage.py
./myproject
./myproject/urls.py
./myproject/myapp/
./myproject/myapp/urls.py
./myproject/myapp/views.py
./tests/
./test/test_example.py

在 ./myproject/urls.py 我有:

from django.conf.urls import patterns, include, url
urlpatterns = patterns('',
    url(r'^myapp/', include('myproject.myapp.urls')),
)

在 ./myproject/myapp/urls.py 我有:

from django.conf.urls import patterns, url

urlpatterns = patterns('myproject.myapp.views',
    url(r'^example1/$', 'itemlist'),  
    url(r'^example1/(?P<item_id>\w+)/$', 'item'),
)

我编写了基本测试并将其放入 ./test/test_example.py

import unittest
from django.test import Client

class PagesTestCase(unittest.TestCase): 
    def setUp(self):
        self.client = Client()

    def test_itemlist(self):        
        response = self.client.get('/myapp/example1/')
        self.assertEqual(response.status_code, 200)

    def test_item(self):        
        response = self.client.get('/myapp/example1/100100/')
        self.assertEqual(response.status_code, 200)

我像这样从 shell 运行这个测试:

cd ./tests
python manage.py test

第一个测试运行正常,但第二个测试总是以“404 not found”状态码失败。

两个网址在浏览器中都可以正常工作。

另外,我试过这个:

cd ./
python manage.py shell
>>> from django.test.client import Client
>>> c = Client()
>>> r = c.get('/myapp/example1/100100/')
>>> r.status_code
200

我只是不知道如何正确运行这些测试。似乎没有任何模式作为参数传递给视图对我有用。但是 django.test.client 正确找到了所有固定的 url。

谢谢!

编辑:我刚刚在 myproject/myapp/views.py 中发现 404 触发

有一个代码:

def item(request, item_id):
    try:
        item = Item.objects.get(pk = int(item_id))
    except (ValueError, Item.DoesNotExist):     
        raise Http404

这里是 Item.DoesNotExist 异常。我不知道,为什么找不到那个项目?

【问题讨论】:

  • 您的数据库中有任何项目吗?如果没有,您可能应该插入一个或多个作为测试夹具。 (您的测试数据库与生产数据库是分开的,所以不用担心会丢失任何真实数据。)
  • > 测试数据库与您的生产数据库是分开的啊啊啊!知道了。所以那个 unittest 东西的目的与我认为的略有不同。它不是为了测试生产数据中的错误。傻我:)
  • 对。单元测试用于测试代码中的错误。也就是说,“代码中的错误”可以而且应该包括确保代码在面对不可用或损坏的数据时表现得合理,因此在编写专门测试的单元测试时绝对有一些价值,鉴于数据库中不存在具有指定 ID 的项目,您的视图应该引发 Http404(假设这是您在特定情况下所需/预期的行为)。

标签: python django unit-testing django-unittest


【解决方案1】:

除了使用reverse,如果预期模型在测试数据库中不可用(如其中一个 cmets 中所述),您可以获得 404。您还应该使用 Django 的 TestCase 而不是 python 的 unittest,因为前者继承自后者,但使得与数据库的交互更容易(除其他外)。

设置测试数据的示例:

from django.test import TestCase
from django.urls import reverse

# Or whatever your object is.
from .models import Item


class ItemViewsTestCase(TestCase):
    """Tests for Item views."""
    @classmethod
    def setUpTestData(cls):
        """Set up test data available for all tests in this class."""
        cls.item = Item.objects.create(name='Testing')

    def test_item_list_view(self):
        # Note, self.client we get for free from Django's TestCase.
        response = self.client.get(reverse('itemlist'))
        self.assertEqual(response.status_code, 200)

    def test_item_detail_view(self):
        # This url pattern expects an Item.id so use the item we set up.
        url = reverse('item', args=[self.item.id])
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)

【讨论】:

    【解决方案2】:

    改用reverse()函数来构建URL,即:

    ./myproject/myapp/urls.py 文件中,为每个 URL 模式指定一个名称参数,例如:

    from django.conf.urls import patterns, url
    
    urlpatterns = patterns('myproject.myapp.views',
        url(r'^example1/$', 'itemlist', name='example-one'),  
        url(r'^example1/(?P<item_id>\w+)/$', 'item', name='example-two'),
    )
    

    我们将使用 name 参数的值来构建 URL。

    然后在./test/test_example.py:

    from django.core.urlresolvers import reverse
    
    class PagesTestCase(unittest.TestCase): 
        ...
        def test_itemlist(self):
            url = reverse('example-one')
            response = self.client.get(url)
            self.assertEqual(response.status_code, 200)
    
        def test_item(self):
            url = reverse('example-two')    
            response = self.client.get(url)
            self.assertEqual(response.status_code, 200)
    

    这应该可以解决问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-01-16
      • 2021-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-23
      • 2017-08-11
      • 2021-02-15
      相关资源
      最近更新 更多