【问题标题】:Writing good tests for Django applications为 Django 应用程序编写好的测试
【发布时间】:2011-01-12 09:53:38
【问题描述】:

我一生中从未编写过任何测试,但我想开始为我的 Django 项目编写测试。我已经阅读了一些关于测试的文章,并决定尝试为一个非常简单的 Django 应用程序或开始编写一些测试。

该应用有两个视图(一个列表视图和一个详细视图)和一个具有四个字段的模型:

class News(models.Model):
    title = models.CharField(max_length=250)
    content = models.TextField()
    pub_date = models.DateTimeField(default=datetime.datetime.now)
    slug = models.SlugField(unique=True)

我想给你看我的tests.py文件并问:

有意义吗?

我是否在测试正确的东西?

是否有我没有遵循的最佳做法,您可以指点我吗?

我的 tests.py(它包含 11 个测试):

# -*- coding: utf-8 -*-
from django.test import TestCase
from django.test.client import Client
from django.core.urlresolvers import reverse
import datetime
from someproject.myapp.models import News

class viewTest(TestCase):
    def setUp(self):
        self.test_title = u'Test title: bąrekść'
        self.test_content = u'This is a content 156'
        self.test_slug = u'test-title-bareksc'
        self.test_pub_date = datetime.datetime.today()

        self.test_item = News.objects.create(
            title=self.test_title,
            content=self.test_content,
            slug=self.test_slug,
            pub_date=self.test_pub_date,
        )

        client = Client()
        self.response_detail = client.get(self.test_item.get_absolute_url())
        self.response_index = client.get(reverse('the-list-view'))

    def test_detail_status_code(self):
        """
        HTTP status code for the detail view
        """
        self.failUnlessEqual(self.response_detail.status_code, 200)

    def test_list_status_code(self):
        """
        HTTP status code for the list view 
        """
        self.failUnlessEqual(self.response_index.status_code, 200)

    def test_list_numer_of_items(self):
        self.failUnlessEqual(len(self.response_index.context['object_list']), 1)      

    def test_detail_title(self):
        self.failUnlessEqual(self.response_detail.context['object'].title, self.test_title)    

    def test_list_title(self):
        self.failUnlessEqual(self.response_index.context['object_list'][0].title, self.test_title)

    def test_detail_content(self):
        self.failUnlessEqual(self.response_detail.context['object'].content, self.test_content)    

    def test_list_content(self):
        self.failUnlessEqual(self.response_index.context['object_list'][0].content, self.test_content) 

    def test_detail_slug(self):
        self.failUnlessEqual(self.response_detail.context['object'].slug, self.test_slug)    

    def test_list_slug(self):
        self.failUnlessEqual(self.response_index.context['object_list'][0].slug, self.test_slug)

    def test_detail_template(self):
        self.assertContains(self.response_detail, self.test_title)
        self.assertContains(self.response_detail, self.test_content)

    def test_list_template(self):       
        self.assertContains(self.response_index, self.test_title) 

【问题讨论】:

    标签: python django unit-testing django-testing


    【解决方案1】:

    我在测试方面并不完美,但有一些想法:

    基本上你应该测试你自己编写的每一个函数、方法、类等等。

    这意味着您不必测试框架提供的函数、类等。

    也就是说,快速检查一下您的测试功能:

    • test_detail_status_codetest_list_status_code:
      好的,检查您是否正确配置了路由。当您提供自己的 get_absolute_url() 实现时,这一点就更重要了。

    • test_list_numer_of_items:
      好的,如果视图应该返回一定数量的项目。如果数字不重要(即任意),则不需要。

    • test_detail_templatetest_list_template:
      好的,检查模板变量是否设置正确。

    • 所有其他功能:不需要。
      您在这里基本上测试的是 ORM 是否正常工作,列表是否按预期工作以及是否可以访问(或不能访问)对象属性。只要您不改变,例如save() 模型的方法和/或提供您的自定义逻辑,我不会对此进行测试。您应该相信框架开发人员可以正常工作。

    您只需测试您已(覆盖)写入的内容。

    模型类可能是一个特例。正如我所说,如果您提供自定义逻辑,您基本上必须测试它们。但您也应该根据您的要求对其进行测试。例如。可能是不允许字段为null(或者它必须是某种数据类型,如整数)。因此,您应该测试存储对象是否失败,如果它在此字段中有 null 值。
    测试 ORM 是否正确遵循您的规范,但测试该规范是否仍然满足您的要求。可能是您更改了模型并更改了某些设置(偶然或因为您忘记了要求)。
    但是你不必测试例如save() 之类的方法或您是否可以访问属性。

    当然,当您使用有缺陷的第三方代码时……情况可能会有所不同。但是由于 Django 使用测试框架本身来验证一切是否正常,我会假设它正在工作。

    总结一下:
    根据您的要求进行测试,测试您自己的代码。

    这只是我的观点。也许其他人有更好的建议。

    【讨论】:

      【解决方案2】:

      将您的测试分成两种完全不同的类型。

      • 模型测试。将这些与您的模型一起放入您的 models.py 文件中。这些测试将练习模型类中的方法。您可以执行简单的 CRUD(创建、检索、更新、删除)来简单地证明您的模型有效。不要测试每个属性。如果您好奇,请测试字段默认值和save() 规则。

        对于您的示例,创建一个 TestNews 类来创建、获取、更新和删除 News 项目。请务必测试默认日期结果。这堂课应该简短而切题。如果您的应用程序需要,您可以测试各种过滤器处理。您的单元测试代码可以(并且应该)提供过滤News的“正确”方式示例。

      • 用户界面测试。将它们放在单独的tests.py 文件中。这些测试将测试视图函数和模板。

        • 使用您正在创建的“条件”命名 TestCase。 “TestNotLoggedIn”。 “测试登录”。 “TestNoValidThis”。 “TestNotAllowedToDoThat”。您的setUp 将执行登录和建立所需条件所需的任何其他步骤。

        • 用操作和结果命名每个测试方法。 “test_get_noquery_should_list”、“test_post_should_validate_with_errors”、“test_get_query_should_detail”。

      【讨论】:

        最近更新 更多