2009-06-15 12 views
10

Ich bin nur ein Anfänger in Python und Programmierung im Allgemeinen, und habe einige Fragen über das Unittest-Modul.Unit-Tests für Ausnahmen in Python-Konstruktor

Ich habe eine Klasse, und in der __init__ Methode mache ich einige Behauptungen auf schlechte Argumente zu überprüfen. Ich möchte einen Unittest erstellen, der beim Anlegen neuer Instanzen nach solchen AssertionError sucht.

Im Unittest-Modul kann man (mit assertRaises) für eine bestimmte Ausnahme testen, wenn ein Callable aufgerufen wird, aber offensichtlich gilt das für Methoden der Klasse. Was ist der richtige Weg, um einen solchen Test für den Konstruktor auszuführen?

Ich weiß, dass ich einfach versuchen kann, eine Instanz der Klasse mit schlechten Argumenten zu erstellen, und Unittest meldet einen Testfehler, der aber sofort nach der ersten solchen Ausnahme stoppt, und auch wenn ich mehrere Tests in mehrere umbrechen kann Testfunktionen, es scheint einfach nicht elegant.

Antwort

1

Nun, zu Beginn ist die Überprüfung auf schlechte Argumente keine gute Idee in Python. Python ist aus einem bestimmten Grund dynamisch stark typisiert.

Sie sollten einfach davon ausgehen, dass die Argumente gute Argumente sind. Sie kennen nie die Absicht Ihrer Benutzer in der Klasse, also ist es eine Möglichkeit, die Verwendung Ihrer Klasse in allgemeineren Instanzen einzuschränken, indem Sie nach guten Argumenten suchen.

Stattdessen definieren Sie eine gute API und dokumentieren Sie sie sehr gut, verwenden Sie Docstrings und Text, und lassen Sie Fehler von schlechten Argumenten automatisch an den Benutzer fließen.

Beispiel:

def sum_two_values(value_a, value_b): 
    return value_a + value_b 

in Ordnung, dieses Beispiel ist dumm, aber wenn ich den Wert als ganze Zahl überprüfen und geltend zu machen, wird die Funktion nicht mit Schwimmern, Strings, Liste, aus keinem anderen Grund arbeiten als meine check, also warum Check-in an erster Stelle? Es wird automatisch mit Typen fehlschlagen, die nicht funktionieren würden, so dass Sie sich keine Sorgen machen müssen.

+0

Nun, in meinem speziellen Fall möchte ich behaupten, dass etwas früh falsch gelaufen ist, denn später lade ich einige C-Bibliotheken mit ctypes und muss ihnen Argumente vom Konstruktor übergeben ... –

+0

@asen_asenov: In diesem Fall , wickeln Sie einfach Ihren Ctypes-Aufruf mit der entsprechenden Umwandlung, z ctypes.c_int (param). Dadurch wird sichergestellt, dass der Typ kompatibel ist und bei inkompatiblen Typen automatisch ein Fehler auftritt. – nosklo

7

Nicht mit assertRaises durcheinander bringen. Es ist zu kompliziert.

diese

class Test_Init(unittest.TestCase): 
    def test_something(self): 
     try: 
      x= Something("This Should Fail") 
      self.fail("Didn't raise AssertionError") 
     except AssertionError, e: 
      self.assertEquals("Expected Message", e.message) 
      self.assertEquals(args, e.args) 
Sie

Jede andere Ausnahme wird ein gewöhnlicher Testfehler sein.

Auch nicht mit zu viel Vor-Fehler-Prüfung in einer __init__ Methode zu tun. Wenn jemand ein Objekt des falschen Typs zur Verfügung stellt, wird Ihr Code im normalen Verlauf der Ereignisse fehlschlagen und eine normale Ausnahme mit normalen Mitteln auslösen. Sie müssen Objekte nicht so sehr "vorsortieren".

+2

Können Sie auf "Es ist zu kompliziert" erweitern? Ich habe Probleme mit 'assertRaises (assertionError, ...)' (Assertion wird ausgelöst, aber nicht von 'assertRaises'), und es wäre interessant zu wissen, warum ... – naught101

+0

Mehr ärgerlich, dieser Code doesn Funktioniert wirklich nicht mit AssertionErrors, weil sie keine 'message' Eigenschaft haben (zumindest in Python 3). – naught101

17

Im Unittest-Modul kann man (mit assertRaises) für spezifische Ausnahme testen, wenn eine aufrufbare genannt wird, aber offensichtlich wird, dass auf Methoden der Klasse gilt. Was ist der richtige Weg, um einen solchen Test für den Konstruktor auszuführen?

Der Konstruktor ist selbst ein aufrufbar:

self.assertRaises(AssertionError, MyClass, arg1, arg2) 

aber sagen, dass ich will nosklo der und S.Lott Bedenken über das Tun Typüberprüfung der Argumente Echo. Darüber hinaus sollten Sie keine Assertions verwenden, um Funktionsargumente zu überprüfen: Assertions sind am nützlichsten als Plausibilitätsprüfungen, die nicht ausgelöst werden, wenn nicht intern etwas mit Ihrem Code falsch ist.Assert-Anweisungen werden auch kompiliert, wenn Python im Modus "optimized" -O ausgeführt wird. Wenn eine Funktion eine Überprüfung ihrer Argumente benötigt, sollte dies eine geeignete Ausnahme auslösen.

+1

-1: Behauptungen sind eine gute Möglichkeit, Argumente zu überprüfen. Sehr kurzer Code: assert 0 <= n, "n ist negativ". –

+0

Ich denke, das ist eine Frage der Meinung. – Miles

0

S.Lott Antwort ist falsch: self.fail() selbst eine Ausnahme auslöst, die dann durch die Ausnahme in der folgenden Zeile verursacht werden:

class NetworkConfigTest1(unittest.TestCase): 
    def runTest(self): 
     try: 
      NetworkConfig("192.168.256.0/24") 
      self.fail("Exception expected but not thrown") 
     except Exception, error: 
      printf("Exception caught: %s" % str(error) 
      pass 

Der Ausgang war „Exception erwartet, aber nicht geworfen“, aber die Komponententest wurde nicht als Fehler markiert, obwohl der getestete Code nicht geschrieben wurde!

Eine gültige Weise zu überprüfen, ob eine Methode eine Ausnahme auslöst, wäre die Verwendung:

self.failUnlessRaises([error], [callable], [arguments to callable]) 

In meinem Fall die Klasse-I-Tests bin ist NetworkConfig genannt, und der Konstruktor muss eine Ausnahme aus, wenn Der Netzwerkdeskriptor ist ungültig. Und was funktioniert hat, ist:

class NetworkConfigTest1(unittest.TestCase): 
    def runTest(self): 
     self.failUnlessRaises(Exception, NetworkConfig, "192.168.256.0/24") 

Dies funktioniert wie gewünscht und führt den richtigen Test.

2

Sie wissen nicht, ist dies hilft, aber ein Problem, das ich wurde, ist wie folgt:

self.assertRaises(Exception, MyFunction()) 

Problem ist ich war nicht nur MyFunction vorbei, aber es auch nennen, was zu einer fehlschlagen und Ausnahme erzogen werden. Myfunction erwartet ein Argument, und ich möchte es nichts versagen, wenn übergeben wird mich für eine Weile Frustriert, bis ich es herausgefunden.

self.assertRaises(Exception, MyFunction) 

wie erwartet funktioniert.

Verwandte Themen