Django 在引发ValidationError时进行测试

Django 在引发ValidationError时进行测试,django,python-2.7,testing,validationerror,Django,Python 2.7,Testing,Validationerror,一般来说,我对编程和Django都是新手。我正在尝试测试我的一个函数,以确保出现验证错误。测试确认出现错误,但也表示测试失败。这怎么可能 **models.py** def check_user_words(sender, instance, **kwargs): for field in instance._meta.get_fields(): #field_name = getattr(instance, field.attname) if (isin

一般来说,我对编程和Django都是新手。我正在尝试测试我的一个函数,以确保出现验证错误。测试确认出现错误,但也表示测试失败。这怎么可能

**models.py**
def check_user_words(sender, instance, **kwargs):
    for field in instance._meta.get_fields():
        #field_name = getattr(instance, field.attname)
        if (isinstance(field, models.CharField) and
            contains_bad_words(getattr(instance, field.attname))):
            raise ValidationError("We don't use words like '{}' around here!".format(getattr(instance, field.attname)))

#tests.py
from __future__ import unicode_literals
import datetime
from django.test import TestCase
from django.utils import timezone
from django.test import TestCase
from django.urls import reverse
from .models import Question, Choice, contains_bad_words, check_user_words
from django.core.exceptions import ValidationError


def create_question(question_text, days):
    time = timezone.now() + datetime.timedelta(days=days)
    return Question.objects.create(question_text=question_text, pub_date=time)


class ContainsBadWordsTests(TestCase):
    def test_check_user_words(self):
    question = create_question(question_text="What a minute bucko", days=1)
    with self.assertRaises(ValidationError):
        check_user_words(question)
        question.full_clean()

#after running python manage.py test polls
......
raise ValidationError("We don't use words like '{}' around here!".format(getattr(instance, field.attname)))
ValidationError: [u"We don't use words like 'What a minute bucko' around here!"]
models.py如何导入
我们需要了解更多专门创建问题的代码,以及check\u user\u words是如何连接到信号的,但我认为问题在于您正在使用post\u save信号处理程序来执行check\u user\u words

如果是这种情况,那么测试失败的原因是create_question将触发post_save信号,并且check_user_单词将立即执行-即,在with self.assertRaises上下文之前,因此测试失败

如果是这种情况,请尝试以下方法:

def test_check_user_words(self):
    with self.assertRaises(ValidationError):
        create_question(question_text="What a minute bucko", days=1)
这个测试现在应该通过了,因为验证错误将在您尝试创建问题时立即抛出

但是请注意,在信号中执行此操作将导致在试图保存对象时出现未捕获的异常。根据您的用例,您最好使用模型本身的clean方法来执行此操作,因为这将导致在模型表单等上报告适当的错误:

def clean(self):
    for field in instance._meta.get_fields():    
        if (isinstance(field, models.CharField) and contains_bad_words(getattr(instance, field.attname))):
            raise ValidationError("We don't use words like '{}' around here!".format(getattr(instance, field.attname)))
然后放下你的信号处理器。然后,您可以使用以下方法进行测试:

q = create_question(question_text="What a minute bucko", days=1)
with self.assertRaises(ValidationError):
    q.clean()

实际测试失败的原因是什么?您可能会检查所引用的ValidationError类型是否与我所显示的相同,以下是全部内容:在0.061s中运行了11个测试失败错误=1销毁别名“default”的测试数据库…因此测试将引发异常,我不明白为什么测试会失败。请告诉我们您是如何在测试中导入ValidationError的。您的直觉是正确的!谢谢你!唯一的问题是它是一个前保存,而不是后保存。我在上面添加了更多的models.py代码。如果我的意图是预保存,而我真正测试的是check_user_words函数是否引发异常,那么使用上面的建议是否仍然正确?是的,预保存也是如此。该代码将在您尝试创建问题时立即执行,因此我上面发布的代码仍将用于验证验证是否发生。也就是说,我对答案进行了编辑,以建议一种不使用信号的替代方法。非常感谢!!如果我想在保存前使用pre_save signal检查和验证某些条件,那么适当的方法是什么?在models.py中定义了我的两个类之后,我有以下代码:pre\u save.connectcheck\u user\u words,sender=Questionpre\u save.connectcheck\u user\u words,sender=Choice
q = create_question(question_text="What a minute bucko", days=1)
with self.assertRaises(ValidationError):
    q.clean()