web-dev-qa-db-fra.com

comment écrire Django test destiné à échouer?

J'ai un modèle appelé Thing avec un attribut appelé name, et je veux que le nom soit un champ char de seulement 3 caractères de long.

Comment puis-je écrire un test pour cela?

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

ce test devrait échouer. Comment écrire correctement le test pour que le test passe lorsque cet objet échoue?

54
Alexander Bird

Si vous vous attendez à ce que Thing (nom = '1234') lève une exception, il existe deux façons de résoudre ce problème.

L'une consiste à utiliser les assertRaises de Django (en fait de unittest/unittest2):

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

Cela échoue à moins que Thing (nom = '1234') ne déclenche une erreur FooException. Une autre façon consiste à intercepter l'exception attendue et à en lever une si cela ne se produit pas, comme ceci:

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

Évidemment, remplacez la FooException par celle que vous attendez de la création de l'objet avec une chaîne trop longue. Erreur de validation?

Une troisième option (à partir de Python 2.7) consiste à utiliser assertRaises comme gestionnaire de contexte, ce qui rend le code plus propre et plus lisible:

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

Malheureusement, cela ne permet pas de messages d'échec de test personnalisés, alors documentez bien vos tests. Voir https://hg.python.org/cpython/file/2.7/Lib/unittest/case.py#l97 pour plus de détails.

85
GDorn

J'utilise actuellement le décorateur expectedFailure de nittest . Cela fonctionne comme annoncé: échoue lorsqu'il n'y a pas d'erreur, passe en cas d'échec.

J'utilise expectedFailure pour vérifier que mes routines d'assertion personnalisées fonctionnent réellement et pas seulement que tout soit OK.

import unittest
from Django.test import TestCase

class EmojiTestCase(TestCase):

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

Mais imprime un message d'avertissement pendant le test. Je l'utilise avec Django et Nose. Ce que autres ont vu aussi).

/usr/lib64/python3.4/unittest/case.py:525: RuntimeWarning: TestResult n'a pas de méthode addExpectedFailure, signalant comme passant RuntimeWarning)

Je suis venu ici pour trouver une meilleure solution, mais je n'en ai trouvé aucune. J'ai donc au moins voulu dire aux autres qui venaient avec qui je travaillais.

3
Chris