77 votes

comment écrire un test django destiné à échouer ?

J'ai un modèle appelé Thing avec un attribut appelé name et je veux que le nom soit un champ char qui est sólo 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 puis-je écrire correctement le test pour que le test passe quand cet objet échoue ?

150voto

GDorn Points 1944

Si vous vous attendez à ce que Thing(name='1234') lève une exception, il y a deux façons d'y remédier.

L'une d'entre elles consiste à utiliser la fonction assertRaises de Django (qui provient en fait de unittest/unittest2) :

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

Cette méthode échoue sauf si Thing(name='1234') soulève une erreur FooException. Une autre façon est d'attraper l'exception attendue et d'en lever une si elle ne se produit pas, comme ceci :

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

Évidemment, remplacez l'exception FooException par celle que vous vous attendez à obtenir en créant l'objet avec une chaîne trop longue. ValidationError ?

Une troisième option (à partir de Python 2.7) consiste à utiliser assertRaises comme gestionnaire de contexte, ce qui permet d'obtenir un code plus propre et plus lisible :

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

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

7voto

Dans mon projet précédent, j'ai dû faire quelque chose comme le développement piloté par les tests, donc j'ai écrit un scénario de test qui doit attraper certains types d'erreurs. S'il n'obtient pas l'erreur, c'est que j'ai fait une erreur. Ici je partage mon code.

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))

Vous pouvez voir que j'ai essayé de créer un utilisateur avec un email et un mot de passe, mais le modèle d'utilisateur par défaut de Django nécessite les arguments "username" et "password" pour créer un utilisateur. Donc ici mon testcase doit lever "TypeError". Et c'est ce que j'ai essayé de faire ici.

6voto

Chris Points 14

J'utilise actuellement le expectedFailure du décorateur de unittest . Cela fonctionne comme annoncé : Échec quand il n'y a pas d'erreur, réussite quand il y a un échec.

J'utilise expectedFailure pour vérifier que mes routines d'assertion personnalisées fonctionnent réellement et ne se contentent pas de tamponner tout ce qui est OK.

import unittest
from django.test import TestCase

class EmojiTestCase(TestCase):

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

Mais il affiche un message d'avertissement pendant le test. Je l'utilise avec Django et Nose. Lequel autres ont vu, eux aussi.

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

Je suis venu ici pour trouver une meilleure solution, mais je n'en ai trouvé aucune. Je voulais donc au moins dire aux autres qui viennent ce avec quoi j'ai travaillé.

-6voto

Tomasz Zielinski Points 9300

Quelque chose comme ceci devrait fonctionner :

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)

-- mais un tel test semble bizarre :-)

Notez également que le backend MySQLdb lèvera une exception d'avertissement pour vous avertir de la troncature de la chaîne de caractères, vous pouvez donc la vérifier avec assertRaises .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X