我有一个名为Thing
的模型,其中包含一个名为name
的属性,我希望name为一个char字段,其仅 3个字符。
我该如何为此编写测试?
class TestCase1(TestCase):
def test1(self):
thing = Thing(name='1234')
该测试应该失败。如何在该对象失败时正确编写测试以使测试传递?
答案 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
进行检查。