Einführung in Python 9. Vorlesung Testen & Profiling
←
→
Transkription von Seiteninhalten
Wenn Ihr Browser die Seite nicht korrekt rendert, bitte, lesen Sie den Inhalt der Seite unten
Wiederholung letztes Mal • CGI-Skripte sind Programme die auf einem Server gestartet werden und als Ergebnis ein HTML Dokument erzeugen HTML- Dokumente Anfrage mit URL CGI- Browser Internet Server Skripte Client HTTP-Paket
Wiederholung letztes Mal • HTML (Hypertext Markup Language) ist DIE Sprache des Internets • HTML-Dokumente bestehen aus Elementen, welche wiederrum Titel der Webseite durch so genannte Tags Überschrift in der Größe 1 repräsentiert werden Überschrift in der Größe 2 Ein Paragraph voller Text Text ohne Paragraph aber mit einem Hyperlink Inhalt
Wiederholung letztes Mal Client Server Login.html Name Name=Wert1 Verarbeiten der login.py Passwort=Wert2 Login-Daten und Passwort erzeugen des HTML- Quelltextes für den login Chatroom Interaktive HTML-Seite Blablabla HTTP-Paket Blubb Speichern des chat.py Bla Nachricht=Wert3 Nachrichtenverlaufs und Updaten der Nachricht Chatroom-Seite des abschicken Clients Dynamisch erzeugte und HTTP-Paket interaktive HTML-Seite
Wiederholung letztes Mal • Zur Kommunikation von Rechnern über das Internet existieren verschiedene Protokolle • Zu jedem dieser Protokolle gibt es Python-Module, welche Klassen und Funktionen bereitstellen um mit diesen zu arbeiten: • Übertragen von Dateien mit FTP • Zugriff auf Webseiten mit HTTP (besser: requests Modul) • E-Mails senden mit SMTP
Debugging – Fehler finden und vermeiden
Debugging – Fehler finden und vermeiden • Im Grunde gibt es drei Arten von Fehlern: • Syntaxfehler sind Grammatikfehler die vom Interpreter erkannt und gemeldet werden, bevor das Skript ausgeführt wird • Laufzeitfehler sind Fehler die erst während der Ausführung eines Skripts auftreten, wobei der Interpreter eine Exception wirft und eventuell die Ausführung des Programms abbricht (z. B. Division durch Null) • Semantikfehler liegen vor, wenn das Skript „erfolgreich“ läuft, aber nicht das leistet was es leisten soll
Debugging – Fehler finden und vermeiden • Im Gegensatz zu Syntax- und Laufzeitfehler kann der Interpreter Semantikfehler nicht erkennen und liefert dementsprechend auch keine Fehlermeldung • Im Allgemeinen kann man solchen Fehlern folgendermaßen begegnen: • Gute und sehr ausführliche Dokumentation des Programmcodes • Kontrollen an kritischen Stellen des Programms einbauen, wenn sie nicht erfüllt sind wird ein Programmabbruch ausgelöst (Exceptions oder Asserts) • Starten des Programms in einem speziellem Testmodus, so dass es seine Arbeitsweise dokumentiert (Logging) • Schritt-für-Schritt Analyse des Programms mit Hilfe eines Debuggers
Einfache Beispiele Semantischer Fehler if x > 19: if x > 19: if x == y: if x == y: print(‘Niemand erwartet die‘) print(‘Niemand erwartet die‘) else: else: print(‘spanische Inquisition!‘) print(‘spanische Inquisition!‘) def primzahl_faktoren(zahl): fak = [1] faktor = 2 while zahl > 1: while zahl % faktor == 0: fak.append(faktor) zahl /= faktor faktor += 1 return(fak) primzahl_faktoren(120) [1,2,2,2,3,5]
Einfache Beispiele Semantischer Fehler if x > 19: if x > 19: ifx == y: if x == y: print(‘Niemand erwartet die‘) print(‘Niemand erwartet die‘) else: else: print(‘spanische Inquisition!‘) print(‘spanische Inquisition!‘) def primzahl_faktoren(zahl): fak = [1] faktor = 2 while zahl > 1: while zahl % faktor == 0: fak.append(faktor) zahl /= faktor faktor += 1 return(fak) primzahl_faktoren(19.5) #Endlos-Schleife
Exceptions revisited • Eine Exception (Ausnahme) ist ein Objekt, welches vom Laufzeitsystem erzeugt wird, wenn das Programm aus bestimmten Gründen abgebrochen werden muss • Wir wissen: Für verschiedene Fehler gibt es unterschiedliche Ausnahmetypen (Indexerror, IOError, TypeError, KeyError, ...) • Wir wissen: Ausnahmen können mit try – except (– finally) abgefangen und verarbeitet werden
Exceptions revisited • Mit der raise-Anweisung kann man gezielt Ausnahmen auslösen (um z. B. Vor- und Nachbedingung zu konstruieren) raise Exceptionname(‘Fehlermeldung‘) def primzahl_faktoren(zahl): if zahl < 0: raise ValueError(‘Zahl muss >= 0 sein!‘) if type(zahl) != int: raise TypeError(‘Zahl muss vom Typ int sein!‘) fak = [1] faktor = 2 while zahl > 1: while zahl % faktor == 0: fak.append(faktor) zahl /= faktor faktor += 1 return(fak)
Exceptions revisited • Es können natürlich auch eigene Exceptions geschrieben werden class primFaktError(ValueError): def __init__(self, arg=(‘Zahl muss >= 0 sein!‘,)): self.args = arg def primzahl_faktoren(zahl): if zahl < 0: raise primFaktError if type(zahl) != int: raise primFaktError(‘Zahl muss vom Typ int sein!‘) fak = [1] faktor = 2 while zahl > 1: while zahl % faktor == 0: fak.append(faktor) zahl /= faktor faktor += 1 return(fak)
Vor- und Nachbedingungen mit assert
Vor- und Nachbedingungen mit assert • Strukturierte Pythonprogramme enthalten meist viele Funktions- Methoden- und Klassendefinitionen und diese sollten jeweils für sich unter allen Bedingungen korrekt arbeiten • Funktionen verarbeiten meist bestimmte Eingabedaten und geben bestimmte Ausgabedaten zurück → An beides sind oft bestimmte Bedingungen geknüpft • Solche Bedingungen lassen sich mit der assert-Funktion überprüfen assert Bedingung logische Aussage
Vor- und Nachbedingungen mit assert • Ist die Bedingung einer assert-Funktion nicht erfüllt, so wird eine AssertionError Ausnahme generiert def primzahl_faktoren(zahl): #Prüfe Vorbedingung assert (type(zahl) == int) and (zahl > 0) fak = [1] faktor = 2 while zahl > 1: while zahl % faktor == 0: fak.append(faktor) zahl /= faktor faktor += 1 #Prüfe Nachbedingung produkt = 1 for i in fak: produkt *= i assert produkt == zahl return(fak)
Debugging und optimierter Modus • Das Testen von Vor- und Nachbedingungen kann algorithmisch sehr zeitintensiv und ressourcenaufwändig sein → Verschlechterung der Laufzeit des Programms • Wird der Pythoninterpreter im optimierten Modus gestartet, so werden alle assert-Anweisungen übersprungen user@pc:~$ python3.6 –O meinSkript.py
Debugging und optimierter Modus • Mit der Variablen __debug__ kann man mehrere Codezeilen vom optimierten Modus ignorieren lassen def primzahl_faktoren(zahl): assert (type(zahl) == int) and (zahl > 0) fak = [1] faktor = 2 while zahl > 1: while zahl % faktor == 0: fak.append(faktor) zahl /= faktor faktor += 1 #Prüfe Nachbedingung if __debug__: produkt = 1 for i in fak: produkt *= i assert produkt == zahl return(fak)
Debugging und optimierter Modus • Man sollte die assert-Funktion niemals zur Validierung von Eingabedaten nutzen (da sich diese Überprüfung im optimierten Modus umgehen lässt) • Man kann Ausversehens leicht assert Bedingungen formulieren die immer wahr sind (damit sind sie nutzlos) assert(1 == 2, ‘Das sollte eine AssertionError Ausnahme erzeugen‘) • Offensichtliche Fälle erkennt der Pythoninterpreter und gibt eine Warnung aus :1: SyntaxWarning: assertion is always true, perhaps remove parentheses?
Logging und Log-Files
Selbstdokumentation • Eine beliebte Form des Fehlerfindens ist die Selbstdokumentierung eines Programms mithilfe der print-Anweisung def quicksort(liste): if len(liste) > 0: print(f'Ich sortiere {liste}‘) print(f'Element zum Spalten {liste[0]}‘) if len(liste) = liste[0]])) >>> quicksort([149, 36, 5, 69, 19, 119]) Ich sortiere [149, 36, 5, 69, 19, 119] Element zum Spalten 149 Ich sortiere [36, 5, 69, 19, 119] Element zum Spalten 36 Ich sortiere [5, 19]
Selbstdokumentation • Eine beliebte Form des Fehlerfindens ist die Selbstdokumentierung eines Programms mithilfe der print-Anweisung def quicksort(liste): if len(liste) > 0: print(f'Ich sortiere {liste}‘) print(f'Element zum Spalten {liste[0]}‘) if len(liste) = liste[0]])) Element zum Spalten 5 Ich sortiere [19] Element zum Spalten 19 Ich sortiere [69, 119] Element zum Spalten 69 Ich sortiere [119] Element zum Spalten 119 [5, 19, 36, 69, 119, 149]
Dokumentation mit Log-Dateien • Eine Alternative zur Dokumentation mittels der print-Funktion ist es den aktuellen Stand eines Programms in eine Textdatei zu schreiben und dieses hinterher zu analysieren • Anstatt eines eigenen File-Handles kann man die Funktionen des Moduls logging verwenden • Mit diesem kann man verschiedene Logger erzeugen und verwalten und auf unterschiedliche Logging-Level schreiben lassen
Dokumentation mit Log-Dateien >>> import logging >>> logging.basicConfig(filename=‘/tmp/logFile.txt‘, level=logging.DEBUG) >>> logging.debug(‘Erster Eintrag‘) >>> x = 19 >>> logging.debug(x) >>> logging.info(‘Zweiter Eintrag‘) logFile.txt DEBUG:root:Erster Eintrag DEBUG:root:19 INFO:root:Zweiter Eintrag
Dokumentation mit Log-Dateien • Es gibt verschiedene Logging-Level um die Dringlichkeit von Einträgen zu definieren • Durch die Einstellung des Logging-Levels können unwichtige Meldungen unterdrückt werden Bedeutsamkeit DEBUG INFO WARNING ERROR CRITICAL
Beispiel Logging-Level logging.basicConfig(filename=‘/tmp/logFile.txt‘, level=logging.DEBUG, filemode=‘w‘) def merge(liste1, liste2): logging.debug(f‘ Starte merge({liste1},{liste2})‘) if len(liste1) == 0: ergebnis = liste2 elif len(liste2) == 0: ergebnis = liste1 else: a, b = liste1[0], liste2[0] if a
Beispiel Logging-Level merge_sort([149, 36, 5, 119, 69, 19, 17, 67, 117, 3, 34, 147]) INFO:root:merge_sort([149, 36, 5, 119, 69, 19, 17, 67, 117, 3, 34, 147]) INFO:root:merge_sort([149, 36, 5, 119, 69, 19]) INFO:root:merge_sort([149, 36, 5]) INFO:root:merge_sort([149]) INFO:root:Ergebnis von merge_sort([149]): [149] INFO:root:merge_sort([36, 5]) INFO:root:merge_sort([36]) INFO:root:Ergebnis von merge_sort([36]): [36] INFO:root:merge_sort([5]) INFO:root:Ergebnis von merge_sort([5]): [5] DEBUG:root: Starte merge([36],[5]) DEBUG:root: Starte merge([36],[]) DEBUG:root:Ergebnis von merge([36],[]): [36] DEBUG:root:Ergebnis von merge([36],[5]): [5, 36] INFO:root:Ergebnis von merge_sort([36, 5]): [5, 36] DEBUG:root: Starte merge([149],[5, 36]) DEBUG:root: Starte merge([149],[36]) DEBUG:root: Starte merge([149],[]) DEBUG:root:Ergebnis von merge([149],[]): [149] DEBUG:root:Ergebnis von merge([149],[36]): [36, 149] DEBUG:root:Ergebnis von merge([149],[5, 36]): [5, 36, 149] INFO:root:Ergebnis von merge_sort([149, 36, 5]): [5, 36, 149] INFO:root:merge_sort([119, 69, 19]) INFO:root:merge_sort([119]) ...
Beispiel Logging-Level logging.basicConfig(filename=‘/tmp/logFile.txt‘, level=logging.INFO, filemode=‘w‘) #Das logging wurde auf das höhere Level INFO gesetzt def merge(liste1, liste2): logging.debug(f‘ Starte merge({liste1},{liste2})‘) if len(liste1) == 0: ergebnis = liste2 elif len(liste2) == 0: ergebnis = liste1 else: a, b = liste1[0], liste2[0] if a
Beispiel Logging-Level merge_sort([149, 36, 5, 119, 69, 19, 17, 67, 117, 3, 34, 147]) INFO:root:merge_sort([149, 36, 5, 119, 69, 19, 17, 67, 117, 3, 34, 147]) INFO:root:merge_sort([149, 36, 5, 119, 69, 19]) INFO:root:merge_sort([149, 36, 5]) INFO:root:merge_sort([149]) INFO:root:Ergebnis von merge_sort([149]): [149] INFO:root:merge_sort([36, 5]) INFO:root:merge_sort([36]) INFO:root:Ergebnis von merge_sort([36]): [36] INFO:root:merge_sort([5]) INFO:root:Ergebnis von merge_sort([5]): [5] INFO:root:Ergebnis von merge_sort([36, 5]): [5, 36] INFO:root:Ergebnis von merge_sort([149, 36, 5]): [5, 36, 149] INFO:root:merge_sort([119, 69, 19]) INFO:root:merge_sort([119]) INFO:root:Ergebnis von merge_sort([119]): [119] INFO:root:merge_sort([69, 19]) INFO:root:merge_sort([69]) INFO:root:Ergebnis von merge_sort([69]): [69] INFO:root:merge_sort([19]) INFO:root:Ergebnis von merge_sort([19]): [19] INFO:root:Ergebnis von merge_sort([69, 19]): [19, 69] INFO:root:Ergebnis von merge_sort([119, 69, 19]): [19, 69, 119] INFO:root:Ergebnis von merge_sort([149, 36, 5, 119, 69, 19]): [5, 19, 36, 69, 119, 149] INFO:root:merge_sort([17, 67, 117, 3, 34, 147]) ...
Logger-Objekte • Für große Projekte eignet es sich mehrere Logger zu verwenden, welchen auch unterschiedliche Logging-Level zugeordnet sein können import logging logging.basicConfig(filename=‘/tmp/logFile.txt‘) log1 = logging.getLogger(‘Modul 1‘) #Erzeugen eines Logger-Objekts log1.setLevel(logging.INFO) log2 = logging.getLogger(‘Modul 2‘) #Erzeugen eines Logger-Objekts log2.setLevel(logging.DEBUG) log1.debug(‘Unwichtige Meldung‘) log1.info(‘Wichtige Meldung‘) log2.debug(‘Wichtige Meldung‘) INFO:Modul 1:Wichtige Meldung DEBUG:Modul 2:Wichtige Meldung
Logging-Meldungen konfigurieren • Beim Aufruf eines Loggers mittels logging.basicConfig() kann man mit Hilfe des optionalen Parameters format das Format der Meldungen ändern • Erwartet wird ein Formatstring, welcher (unter Anderen) aus den folgenden Platzhaltern aufgebaut sein kann: Platzhalter Bedeutung %(asctime)s Zeitpunkt zu dem die Meldung ausgegeben wurde. %(funcname)s Name der Funktion, in der die Meldung abgesetzt wurde. %(levelname)s Logging-Level. %(message)s Text der Meldung. %(module)s Name des Moduls, in dem die Meldung abgesetzt wurde. %(name)s Name des Loggers. %(pathname)s Vollständiger Pfad des Moduls, in dem die Meldung abgesetzt wurde.
Logging-Meldungen konfigurieren >>> import logging >>> fstring = ‘%(asctime)s:::%(name)s:::%(funcName)s:::%(message)s‘ >>> logging.basicConfig(filename=‘/tmp/logFile.txt‘, format=fstring) >>> logging.critical(‘Super wichtige Meldung!‘) >>> def tolle_funktion(): logging.critical(‘Noch eine wichtige Meldung!‘) >>> tolle_funktion() >>> log1 = logging.getLogger(‘Logger-Droide‘) >>> log1.critical(‘Roger Roger‘) 2016-01-24 21:45:16,080:::root::::::Super wichtige Meldung! 2016-01-24 21:46:26,176:::root:::tolle_funktion:::Noch eine wichtige Meldung! 2016-01-24 21:48:16,025:::Logger-Droide::::::Roger Roger!
Der IDLE Debugger
Der IDLE Debugger • Die Python IDLE-Umgebung besitzt einen integrierten Debugger, welchen man folgendermaßen aufruft: • In einem Shellfenster aktiviert man den Debugger über das Menü Debug
Der IDLE Debugger • Die Python IDLE-Umgebung besitzt einen integrierten Debugger, welchen man folgendermaßen aufruft: • In einem Shellfenster aktiviert man den Debugger über das Menü Debug
Der IDLE Debugger • Die Python IDLE-Umgebung besitzt einen integrierten Debugger, welchen man folgendermaßen aufruft: • Startet man nun im Editor-Fenster das Skript mittels Run Modul, so läuft das Programm unter der Kontrolle des Debuggers
Der IDLE Debugger • Die Python IDLE-Umgebung besitzt einen integrierten Debugger, welchen man folgendermaßen aufruft: • Startet man nun im Editor-Fenster das Skript mittels Run Modul, so läuft das Programm unter der Kontrolle des Debuggers
Testen und Tuning
Automatisiertes Testen mit doctest • Das Modul doctest ermöglicht es automatisches Tests mittels so genannter Docstrings auszuführen • Ein Docstring ist ein langer String, welcher meist zu Beginn eines Moduls oder unterhalb der Kopfzeile einer Funktion steht • Er wird nicht als Code sondern als Kommentar interpretiert
Doctest Beispiel def quadratsumme(liste): “““ Summer der Quadrate der Elemente einer Zahlenliste >>> quadratsumme([1,2,3]) 14 >>> quadratsumme([10,10,10]) 300 >>> quadratsumme([]) 0 “““ summe = 0 for x in liste: summe += x**2 return(summe)
Doctest Beispiel • Der Docstring enthält Testaufrufe der Funktion, d. h. man tut so als würde man die Funktion im interaktivem Modus testen • Zeilen die mit dem Python-Prompt „>>>“ starten werden interpretiert, darauf folgende Zeilen ohne Prompt stellen das richtige Ergebnis des Aufrufs dar def quadratsumme(liste): “““ Summer der Quadrate der Elemente einer Zahlenliste >>> quadratsumme([1,2,3]) 14 >>> quadratsumme([10,10,10]) 300 >>> quadratsumme([]) 0 “““ summe = 0 for x in liste: summe += x**2 return(summe)
Doctest Beispiel • Doctests startet man entweder über das Modul doctest import doctest doctest.testmode(verbose=True) Trying: quadratsumme([1,2,3]) Expecting: 14 ok Trying: quadratsumme([10,10,10]) Expecting: 300 ok Trying: quadratsumme([]) Expecting: 0 ok 1 items had no tests: __main__ 1 items passed all tests: 3 tests in __main__.quadratsumme 3 tests in 2 items. 3 passed and 0 failed. Test passed. TestResults(failed=0, attempted=3)
Doctest Beispiel • Oder über die Kommandozeile mit dem Python-Interpreter user@pc:~$ python3.6 –m doctest -v quadratsummen.py Trying: quadratsumme([1,2,3]) Expecting: 14 ok Trying: quadratsumme([10,10,10]) Expecting: 300 ok Trying: quadratsumme([]) Expecting: 0 ok 1 items had no tests: __main__ 1 items passed all tests: 3 tests in __main__.quadratsumme 3 tests in 2 items. 3 passed and 0 failed. Test passed.
Doctest Beispiel • DocStrings können auch über mehrere Zeilen interpretiert werden def sinnlose_Funktion(): “““ >>> # Kommentare werden auch ignoriert >>> x = 19 >>> if(x == 149): ... print(‘Alles richtig gemacht!‘) ... else: ... print(‘Oh nein!‘) ... print(‘Alles schief gelaufen!‘) Oh nein! Alles schief gelaufen! “““ pass
Doctest Beispiel • DocStrings können auch in separaten Textdateien liegen sinnlose_funktion_test.txt >>> # Kommentare werden auch ignoriert >>> x = 19 >>> if(x == 149): ... print(‘Alles richtig gemacht!‘) ... else: ... print(‘Oh nein!‘) ... print(‘Alles schief gelaufen!‘) Oh nein! Alles schief gelaufen! user@pc:~$ python3.6 –m doctest -v sinnlose_funktion_test.txt import doctest doctest.testfile(‘/home/scripts/sinnlose_funktion_test.txt‘, verbose=True)
Automatisiertes Testen mit unittest • Abgeleitet von den Unit Tests aus Java gibt es in Python das Modul unittest zum erstellen von Testklassen und dazugehörigen Testreihen • Innerhalb einer abgeleiteten Testklasse werden (relevante) Tests in Form von Methoden definiert • Somit lassen sich generalisierte, automatische Testroutinen schreiben
Unittest Beispiel def fibonacci(n): if n == 0: ergebnis = 0 elif n == 1: ergebnis = 1 else: ergebnis = fibonacci(n-1) + fibonacci(n-2) return(ergebnis)
Unittest Beispiel import unittest class testFibonacci(unittest.TestCase): def setUp(self): #Geerbte Methode zum initiieren von Testdaten self.testZahlen = [1,2,5,25,35] def testElementarfall(self): self.assertEqual(fibonacci(self.testZahlen[0]), 1) def testEinfacheFall(self): self.assertEqual(fibonacci(self.testZahlen[1]), 1) def testDreiSchwereFälle(self): self.assertEqual(fibonacci(self.testZahlen[2]), 5) self.assertEqual(fibonacci(self.testZahlen[3]), 75025) self.assertEqual(fibonacci(self.testZahlen[4]), 9227465)
Unittest Beispiel • Man kann mit einem TestRunner einzelne Test-Objekte auswerten lassen >>> test1 = testFibonacci(‘testElementarfall‘) >>> testrunner = unittest.TextTestRunner(verbosity=1) >>> testrunner.run(test1) testElementarfall (__main__.testFibonacci) ... ok ---------------------------------------------------------------------- Ran 1 test in 0.001s OK
Unittest Beispiel • Oder mit einer TestSuite gleich mehrere Tests auf einmal >>> suite = unittest.TestSuite() >>> suite.addTests([testFibonacci('testElementarfall‘),\ testFibonacci('testEinfacheFall‘),\ testFibonacci('testDreiSchwereFälle‘)]) >>> testrunner = unittest.TextTestRunner(verbosity=2) >>> testrunner.run(suite) testElementarfall (__main__.testFibonacci) ... ok testEinfacheFall (__main__.testFibonacci) ... ok testDreiSchwereFälle (__main__.testFibonacci) ... ok ---------------------------------------------------------------------- Ran 3 tests in 6.065s OK
Unittest Beispiel import unittest def fibonacci_falsch(n): if n == 0: ergebnis = 0 elif n == 1: ergebnis = 1 else: ergebnis = fibonacci(n-1) + fibonacci(n-1) #Fehler in der Berechnung return(ergebnis) class testFiboFalsch(unittest.TestCase): #Wenn man keine Testdaten initiieren muss, #braucht man die setUp()-Methode auch nicht überschreiben def testFiboBerechnung(self): self.assertEqual(fibonacci_falsch(5), 5)
Unittest Beispiel >>> test2 = testFiboFalsch(‘testFiboBerechnung‘) >>> testrunner = unittest.TextTestRunner(verbosity=1) >>> testrunner.run(test2) ====================================================================== FAIL: testFiboBerechnung (__main__.testFiboFalsch) ---------------------------------------------------------------------- Traceback (most recent call last): File "", line 5, in testFiboBerechnung self.assertEqual(fibonacci_falsch(5), 5) AssertionError: 6 != 5 ---------------------------------------------------------------------- Ran 1 test in 0.001s FAILED (failures=1)
Unittest Prüfmethoden • Neben assertEqual besitzt die Klasse TestCase noch weitere Prüfmethoden, unter Anderem: Methode Bedeutung assertEqual(X, Y) Schlägt fehl wenn X und Y nicht Wertegleich sind. assertAlmostEqual(X, Y, Z) Schlägt fehl wenn X und Y bis auf Z Stellen genau gleich sind. assertDictEqual(X, Y) Schlägt fehl wenn X und Y ungleiche Dictionaries sind. assertTrue(X) Schlägt fehl wenn der Ausdruck X nicht True ist. assertGreater(X, Y) Schlägt fehl wenn X kleiner oder gleich Y ist. assertIn(X, Y) Schlägt fehl wenn X nicht in Y enthalten ist. assertMultiLineEqual(X, Y) Mehrzeilige Strings werden auf Gleichheit geprüft. assertIs(X, Y) Schlägt fehl wenn X nicht identisch mit Y ist. assertNotRegexpMatches(X, Y) Schlägt fehl wenn der Text X nicht auf den regulären Ausdruck Y passt.
Performanz messen mit profile • Übergibt man der run()-Methode des Moduls profiler eine beliebige Pythonanweisung als String, so erhält man einen Laufzeitperformanzbericht über diese Anweisung def sort(liste): unsortiert = liste[:] sortiert = [] while unsortiert: x = min(unsortiert) sortiert.append(x) unsortiert.remove(x) return(sortiert)
Performanz messen mit profile import profile, random liste = [random.randint(0,1000) for i in range(10000)] profile.run(‘sort(liste)‘) 30005 function calls in 1.891 seconds Ordered by: standard name ncalls tottime percall cumtime percall filename:lineno(function) 10000 0.000 0.000 0.000 0.000 :0(append) 1 0.000 0.000 1.891 1.891 :0(exec) 10000 1.266 0.000 1.266 0.000 :0(min) 10000 0.562 0.000 0.562 0.000 :0(remove) 1 0.000 0.000 0.000 0.000 :0(setprofile) 1 0.062 0.062 1.891 1.891 :1(sort) 1 0.000 0.000 1.891 1.891 :1() 0 0.000 0.000 profile:0(profiler) 1 0.000 0.000 1.891 1.891 profile:0(sort(liste))
Performanz messen mit profile import profile, random profile.run('[sort(x) for x in [[random.randint(0,1000) for i in range(10000)] for y in range(100)]]’) 8640192 function calls (8640092 primitive calls) in 150.125 seconds Ordered by: standard name ncalls tottime percall cumtime percall filename:lineno(function) 1000000 1.984 0.000 1.984 0.000 :0(append) 1000000 2.562 0.000 2.562 0.000 :0(bit_length) 1 0.000 0.000 150.125 150.125 :0(exec) 1639986 4.031 0.000 4.031 0.000 :0(getrandbits) 1000000 78.828 0.000 78.828 0.000 :0(min) 1000000 33.062 0.000 33.062 0.000 :0(remove) 1 0.000 0.000 0.000 0.000 :0(setprofile) 100 5.672 0.057 119.547 1.195 :1(sort) 102/2 2.328 0.023 150.109 75.055 :1()
Sie können auch lesen