怎么写django测试意味着失败?

时间:2010-11-18 18:22:20

标签: django testing tdd

我有一个名为Thing的模型,其中包含一个名为name的属性,我希望name为一个char字段,其 3个字符。

我该如何为此编写测试?

class TestCase1(TestCase):
    def test1(self):
        thing = Thing(name='1234')

该测试应该失败。如何在该对象失败时正确编写测试以使测试传递

4 个答案:

答案 0 :(得分:80)

如果你期望Thing(name ='1234')引发异常,有两种方法可以解决这个问题。

一个是使用Django的assertRaises(实际来自unittest / unittest2):

def mytest(self):
    self.assertRaises(FooException, Thing, name='1234')

除非Thing(name ='1234')引发FooException错误,否则失败。另一种方法是捕获预期的异常并在没有发生的情况下引发异常,如下所示:

def mytest(self):
    try:
        thing = Thing(name='1234')
        self.fail("your message here")
    except FooException:
        pass

显然,将FooException替换为您希望从创建具有太长字符串的对象获得的FooException。 ValidationError?

第三个选项(从Python 2.7开始)是使用assertRaises作为上下文管理器,这使代码更清晰,更易读:

def mytest(self):
    with self.assertRaises(FooException):
        thing = Thing(name='1234')

可悲的是,这不允许自定义测试失败消息,因此请妥善记录您的测试。有关详细信息,请参阅https://hg.python.org/cpython/file/2.7/Lib/unittest/case.py#l97

答案 1 :(得分:3)

我目前正在使用unittest中的expectedFailure装饰器。这与宣传的一样:在没有错误时失败,在失败时通过。

我使用expectedFailure来验证我的自定义断言例程是否真的有效,而不仅仅是rubberstamp一切正常。

import unittest
from django.test import TestCase

class EmojiTestCase(TestCase):

    @unittest.expectedFailure
    def testCustomAssert(self):
        self.assertHappyFace(':(') # must fail.

但在测试过程中会打印一条警告信息。我和Django和Nose一起使用它。其中others也见过。

  

/usr/lib64/python3.4/unittest/case.py:525:RuntimeWarning:TestResult没有addExpectedFailure方法,报告为通过     RuntimeWarning)

我来这里寻找更好的解决方案,但没有找到。因此,我至少想告诉别人,我一直在与之合作。

答案 2 :(得分:3)

在我之前的项目中,我不得不做一些类似测试驱动开发的事情,所以我写了一些必须捕获某些类型错误的测试用例。如果它没有得到错误,那么我就搞砸了一些事情。在这里我分享我的代码。

from django.test import TestCase
from django.contrib.auth.models import User

class ModelTest(TestCase):

def test_create_user_with_email(self):

    with self.assertRaises(TypeError):
        email = "ah@gmail.com"
        password = 'testpass1'

        user = User.objects.create_user(
            email = email,
            password = password,)

        self.assertEqual(user.email, email)
        self.assertTrue(user.check_password(password))

您可以看到我尝试使用电子邮件和密码创建用户,但默认的 Django 用户模型需要“用户名”和“密码”参数来创建用户。所以在这里我的测试用例必须引发“TypeError”。这就是我在这里尝试做的。

答案 3 :(得分:-1)

这样的事情应该有效:

thing = Thing.objects.create(name='1234')  
# not sure if you need here .get() or if. create() truncates the field on its own
self.assertEqual(thing.name, '123') # or: self.assertEqual(len(thing.name), 3)

- 但这样的测试看起来很奇怪: - )

另请注意,MySQLdb后端会引发警告异常以通知您截断字符串,因此您可能希望使用assertRaises进行检查。