Как написать тест Django означает провал? - PullRequest
45 голосов
/ 18 ноября 2010

У меня есть модель с именем Thing с атрибутом с именем name, и я хочу, чтобы name было полем символа длиной всего 3 символа.

Как мне написать тест для этого?

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

этот тест не пройден. Как правильно написать тест, чтобы тест проходил при сбое этого объекта?

Ответы [ 3 ]

83 голосов
/ 18 ноября 2010

Если вы ожидаете, что Thing (name = '1234') вызовет исключение, есть два способа справиться с этим.

Один из них - использовать 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 на то, которое вы ожидаете получить от создания объекта со слишком длинной строкой. 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.

3 голосов
/ 28 февраля 2018

В настоящее время я использую декоратор expectedFailure из unittest .Это работает так, как объявлено: Сбой, когда ошибки нет, проходит, когда есть ошибка.

Я использую expectedFailure, чтобы убедиться, что мои пользовательские подпрограммы assert действительно работают, а не просто теряют все в порядке.

import unittest
from django.test import TestCase

class EmojiTestCase(TestCase):

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

Но печатает предупреждение во время тестирования.Я использую это с Джанго и Носом.Которые другие тоже видели.

/ usr / lib64 / python3.4 / unittest / case.py: 525: RuntimeWarning: TestResult не имеет метода addExpectedFailure, сообщая как проходыRuntimeWarning)

Я пришел сюда, чтобы найти лучшее решение, но не нашел ни одного.Поэтому я, по крайней мере, хотел рассказать другим, что придет, с чем я работаю.

0 голосов
/ 18 ноября 2010

Примерно так должно работать:

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 вызовет исключение Warning, чтобы уведомить вас об усечении строки, поэтому вы можете проверить ее с помощью assertRaises.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...