Тестирование при возникновении ошибки ValidationError - PullRequest
0 голосов
/ 24 сентября 2018

Я новичок в программировании и Джанго в целом.Я пытаюсь проверить одну из своих функций, чтобы убедиться, что возникла ошибка проверки.Тест подтверждает, что ошибка возникла, но также говорит, что тест не пройден.Как это возможно?

**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 Как импортировать

from __future__ import unicode_literals .... (and others)

filepath = "polls/static/polls/blacklist.yaml"
config = yaml_loader(filepath)
blacklist = [word.lower() for word in config['blacklist']]

def contains_bad_words(user_input_txt):
""" remove punctuation from text
    and make it case-insensitive"""
    user_typ = user_input_txt.encode()
    translate_table = maketrans(string.punctuation, 32 * " ")
    words = user_typ.translate(translate_table).lower().split()
    for bad_word in blacklist:
        for word in words:
            if word == bad_word:
                return True
    return False

@receiver(pre_save)
def check_user_words(sender, instance, **kwargs):
    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))) 

1 Ответ

0 голосов
/ 25 сентября 2018

Нам нужно увидеть больше вашего кода (в частности, create_question() и как check_user_words связан с сигналом), чтобы убедиться, но я думаю, что проблема в том, что вы используете обработчик сигнала post_save для выполнения check_user_words().

Если это так, то причина, по которой ваш тест не пройден, заключается в том, что create_question() вызовет сигнал post_save, и check_user_words() будет выполнен немедленно, то есть перед контекст 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()
...