我是NOT名测试新手,但我对Django中测试不同层的建议感到困惑.

一些人建议(他们是对的)在模型中避免Doctests,因为它们不可维护...

其他人说不要使用fixtures,因为它们不如helper functions灵活.

也有两组人为使用Mock件物品而战.第一组赞成使用模拟并隔离系统的睡觉,而另一组则倾向于使用Stop Mocking and start testing.

我上面提到的大部分都是关于测试模型的.Functional testing是另一回事(使用test.Client()vs webTest vs等等)

是否有ANY种可维护、可扩展和正确的方法来测试不同的层??

UPDATE

我知道PyCon 2012有Carl Meyer's talk个..

推荐答案

UPDATE 08-07-2012

我可以告诉您我的单元测试实践,这些实践对我自己的目的非常有效,我会给您我的理由:

1.-仅对测试所需但不会改变的信息使用Fixtures,例如,每次测试都需要一个用户,使用basefixture 创建用户.

2.-使用工厂创建你的对象,我个人喜欢FactoryBoy(这来自FactoryGirl,它是一个ruby库).我创建了一个名为Factorys的单独文件.我保存所有这些对象的每个应用程序的py.这样我就不需要测试文件和我需要的所有对象,这使得它更可读,更易于维护.这种方法很酷的一点是,如果您想基于工厂中的某个对象测试其他对象,可以创建一个可以修改的基本对象.而且它不依赖于django,所以当我开始使用mongodb并需要测试它们时,迁移这些对象时,一切都很顺利.现在,在阅读了有关工厂的信息后,人们通常会说:"那我为什么要使用固定装置呢?".因为这些固定装置永远不应该改变,所以工厂里所有额外的东西都是无用的,django对固定装置的支持非常好.

3.-我给外部服务打了Mock个电话,因为这些电话使我的测试非常慢,而且它们依赖于与我的代码对错无关的事情.例如,如果我在测试中发推文,我会测试它是否正确地发推文,复制响应并模拟该对象,以便它每次都返回准确的响应,而不进行实际调用.有时候,当事情出了问题时,进行测试是很好的,而嘲笑对这一点很好.

4.-我使用一台集成服务器(这里我推荐jenkins台),每当我推送到我的暂存服务器时,它都会运行测试,如果失败,它会向我发送一封邮箱.这真是太棒了,因为我经常在上一次的改变中 destruct 了其他东西,忘记了运行测试.它还提供了其他功能,比如覆盖率报告、pylint/jslint/pep8验证,还有很多插件,可以在其中设置不同的统计数据.

关于测试前端的问题,django提供了大约helper functions个基本方法来处理这个问题.

这是我个人使用的,你可以发GET,帖子,登录用户等等,这对我来说已经足够了.我不倾向于使用像Selenium这样的完整前端测试引擎,因为我觉得测试业务层以外的任何其他东西太过分了.我相信有些会有所不同,这总是取决于你在做什么.

除了我的观点之外,django 1.4还为浏览器框架提供了一个非常方便的integration.

我将设置一个示例应用程序,在其中我可以应用这种做法,这样就更容易理解了.让我们创建一个非常基本的博客应用程序:

structure

blogger/
    __init__.py
    models.py
    fixtures/base.json
    factories.py
    tests.py

models.py

 from django.db import models

 class Blog(models.Model):
     user = models.ForeignKey(User)
     text = models.TextField()
     created_on = models.DateTimeField(default=datetime.now())

fixtures/base.json

[
{
    "pk": 1,
    "model": "auth.user",
    "fields": {
        "username": "fragilistic_test",
        "first_name": "demo",
        "last_name": "user",
        "is_active": true,
        "is_superuser": true,
        "is_staff": true,
        "last_login": "2011-08-16 15:59:56",
        "groups": [],
        "user_permissions": [],
        "password": "IAmCrypted!",
        "email": "test@email.com",
        "date_joined": "1923-08-16 13:26:03"
    }
}
]

factories.py

import factory
from blog.models import User, Blog

class BlogFactory(factory.Factory):
    FACTORY_FOR = Blog

    user__id = 1
    text = "My test text blog of fun"

tests.py

class BlogTest(TestCase):
    fixtures = ['base']  # loads fixture

    def setUp(self):
        self.blog = BlogFactory()
        self.blog2 = BlogFactory(text="Another test based on the last one")

    def test_blog_text(self):
        self.assertEqual(Blog.objects.filter(user__id=1).count(), 2)

    def test_post_blog(self):
        # Lets suppose we did some views
        self.client.login(username='user', password='IAmCrypted!')
        response = self.client.post('/blogs', {'text': "test text", user='1'})

        self.assertEqual(response.status, 200)
        self.assertEqual(Blog.objects.filter(text='test text').count(), 1)

    def test_mocker(self):
        # We will mock the datetime so the blog post was created on the date
        # we want it to
        mocker = Mock()
        co = mocker.replace('datetime.datetime')
        co.now()
        mocker.result(datetime.datetime(2012, 6, 12))

        with mocker:
            res = Blog.objects.create(user__id=1, text='test')

        self.assertEqual(res.created_on, datetime.datetime(2012, 6, 12))

    def tearDown(self):
        # Django takes care of this but to be strict I'll add it
        Blog.objects.all().delete()

请注意,出于示例的目的,我使用了一些特定的技术(顺便说一句,这些技术还没有经过测试).

我必须坚持,这可能不是标准的最佳实践(我怀疑它是否存在),但它对我非常有效.

Django相关问答推荐

Django相关对象引用模板

django.template.response.ContentNotRenderedError: 必须渲染响应内容才能迭代

访问默认的 django-allauth 登录和注册页面时出现 TemplateSyntaxError

JSP模板继承

从python中的URL获取查询字符串的最佳方法?

在 Django REST Framework 中找不到资源时如何返回 404

django excel xlwt

Django:创建索引:非唯一,多列

Django:获取上次用户访问日期

如何在 Django Rest Framework SimpleRouter 上使斜杠可选

在python中查找对对象的所有引用

在 django 中是否有生成 settings.SECRET_KEY 的功能?

如何在 django 元素中开始做 TDD?

Python - 覆盖 __init__ 的最干净方法,其中在 super() 调用之后必须使用可选的 kwarg?

如何在不发送信号的情况下保存模型?

Celery - 在一台服务器上运行不同的工作人员

Django查询否定

Django 自定义用户邮箱帐户验证

django - 使用 get_or_create 自动创建用户时设置用户权限

使用 .order_by() 和 .latest() 的 Django 查询