2010-11-18 14 views
30

Ich habe ein Modell mit dem Namen Thing mit einem Attribut namens name, und ich möchte Name ein Char-Feld sein, das nur 3 Zeichen lang ist.Wie schreibe ich einen Django-Test?

Wie schreibe ich einen Test dafür?

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

Dieser Test sollte fehlschlagen. Wie schreibe ich den Test richtig, so dass der Test übergibt, wenn dieses Objekt fehlschlägt?

Antwort

58

Wenn Sie erwarten, dass Thing (name = '1234') eine Ausnahme auslöst, gibt es zwei Möglichkeiten, damit umzugehen.

One ist Djangos assertRaises zu verwenden (eigentlich von Unittest/unittest2):

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

Dies schlägt fehl, wenn Thing (name = '1234') einen FooException Fehler auslöst. Ein anderer Weg ist die erwartete Ausnahme zu fangen und eine erhöhen, wenn es nicht geschieht, wie folgt aus:

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

Offensichtlich die FooException mit der ersetzen Sie von der Erstellung des Objekts mit einer zu langen String erhalten erwarten. Validierungsfehler?

Eine dritte Option (ab Python 2.7) ist assertRaises als Kontext-Manager zu verwenden, die für sauberere, lesbaren Code macht:

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

Leider ist dies nicht für kundenspezifische Testfehlermeldungen erlaubt , also dokumentieren Sie Ihre Tests gut. Weitere Informationen finden Sie unter https://hg.python.org/cpython/file/2.7/Lib/unittest/case.py#l97.

+0

Ich benutze assertRaises ziemlich oft. –

+0

tue ich auch, aber die Syntax braucht etwas gewöhnungsbedürftig. – GDorn

+1

in Python-Version 2.6.5 ist die Funktion Signatur anders. Aus dem Python-Code kopiert: 'def failUlessRaises (self, excClass, callableObj, * args, ** kwargs)' und dann 'callableObj (* args, ** kwargs)'. Im Beispiel dieses Beitrags wäre es also "self.assertRaises (FooException, Thing, name = '1234')". Ich bin nicht sicher, warum meine Funktion Signatur ist anders, aber das ist, was funktioniert. –

0

So etwas sollte funktionieren:

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) 

- aber solche Test sieht seltsam :-)

Beachten Sie auch, dass MySQLdb Backend Warnung Ausnahme erhöhen Sie Kürzen um die Zeichenfolge zu benachrichtigen, so Vielleicht möchten Sie es mit assertRaises überprüfen.

0

Ich verwende derzeit die expectedFailure Dekorateur von unittest. Das funktioniert wie angekündigt: Fehlschläge, wenn kein Fehler vorliegt, passiert bei einem Fehler.

Ich benutze expectedFailure, um zu überprüfen, dass meine benutzerdefinierten Asser-Routinen tatsächlich funktionieren und nicht nur alles in Ordnung bringen.

import unittest 
from django.test import TestCase 

class EmojiTestCase(TestCase): 

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

Beim Drucken wird jedoch eine Warnmeldung ausgegeben. Ich benutze es mit Django und Nase. Welche others haben auch gesehen.

/usr/lib64/python3.4/unittest/case.py:525: RuntimeWarning: Testresult hat keine addExpectedFailure Methode, wie geht die Berichterstattung RuntimeWarning)

ich hierher kam, um eine bessere zu finden Lösung, aber keine gefunden. Also wollte ich zumindest anderen erzählen, dass das kommt, woran ich gearbeitet habe.

Verwandte Themen