2010-11-18 14 views
30

Ho un modello chiamato Thing con un attributo chiamato name e voglio che il nome sia un campo char che è solo di 3 caratteri.come scrivere test django destinato a fallire?

Come si scrive un test per questo?

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

che il test dovrebbe fallire. Come faccio a scrivere correttamente il test in modo che il test passi quando quell'oggetto fallisce?

risposta

58

Se si prevede che Thing (name = '1234') per generare un'eccezione, ci sono due modi per risolvere questo problema.

Uno è quello di utilizzare assertRaises di Django (in realtà da unittest/unittest2):

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

Questo non riesce a meno Thing (name = '1234') solleva un errore di FooException. Un altro modo è quello di catturare l'eccezione prevista e sollevare uno se non accade, in questo modo:

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

Ovviamente, sostituire il FooException con quello che ci si aspetta di ottenere da creare l'oggetto con troppo a lungo una corda. Errore di convalida?

Una terza opzione (a partire da Python 2.7) è quello di utilizzare assertRaises come un gestore di contesto, che rende per una maggiore pulizia, il codice più leggibile:

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

Purtroppo, questo non permette di messaggi di errore di test personalizzati , quindi documenta bene i tuoi test. Vedi https://hg.python.org/cpython/file/2.7/Lib/unittest/case.py#l97 per maggiori dettagli.

+0

Io uso assertRaises abbastanza spesso. –

+0

Lo faccio anch'io, ma ci vuole un po 'di tempo per abituarsi alla sintassi. – GDorn

+1

in Python versione 2.6.5, la firma della funzione è diversa. Copiato dal codice Python: 'def failUnlessRaises (self, excClass, callableObj, * args, ** kwargs)' e poi 'callableObj (* args, ** kwargs)'. Quindi, nell'esempio di questo post, sarebbe 'self.assertRaises (FooException, Thing, name = '1234')'. Non sono sicuro del perché la mia firma della funzione sia diversa, ma è quello che funziona. –

0

Qualcosa del genere dovrebbe funzionare:

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) 

- ma tale prova sembra strano :-)

Si noti inoltre che backend MySQLdb solleverà eccezioni di avviso per informare l'utente di troncare la stringa, quindi potresti volerlo controllare con assertRaises.

0

Attualmente sto usando il decoratore expectedFailure da unittest. Funziona come pubblicizzato: fallisce quando non c'è errore, passa quando c'è un fallimento.

Io uso expectedFailure per verificare che le mie routine di asserzione personalizzate effettivamente funzionino e non solo tutto ciò che è OK.

import unittest 
from django.test import TestCase 

class EmojiTestCase(TestCase): 

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

Ma stampa un messaggio di avviso durante il test. Lo uso con Django e Naso. Che hanno visto anche others.

/usr/lib64/python3.4/unittest/case.py:525: RuntimeWarning: TestResult non ha un metodo addExpectedFailure, la rendicontazione, passa RuntimeWarning)

Sono venuto qui per trovare una migliore soluzione, ma non ne trova. Quindi volevo almeno dire agli altri che quello con cui lavoravo.

Problemi correlati