Eine Einführung in Unit Testing in Python

Sie haben gerade einen Code geschrieben und fragen sich, was Sie tun sollen. Wirst du eine Pull-Anfrage einreichen und deine Teamkollegen den Code überprüfen lassen? Oder testen Sie den Code manuell?

Sie sollten beide Dinge tun, aber mit einem zusätzlichen Schritt: Sie müssen Ihren Code einem Komponententest unterziehen, um sicherzustellen, dass der Code wie beabsichtigt funktioniert.

Unit-Tests können bestanden oder nicht bestanden werden, und das macht sie zu einer großartigen Technik, um Ihren Code zu überprüfen. In diesem Tutorial werde ich zeigen, wie man Unit-Tests in Python schreibt, und Sie werden sehen, wie einfach es ist, sie in Ihrem eigenen Projekt zum Laufen zu bringen.

Beginnen

Das Testen können Sie am besten verstehen, wenn Sie es praktisch durchführen. Zu diesem Zweck schreibe ich in eine Datei mit dem Namen name_function.py eine einfache Funktion, die einen Vor- und Nachnamen verwendet und einen vollständigen Namen zurückgibt:

#Generate a formatted full name def formatted_name(first_name, last_name): full_name = first_name + ' ' + last_name return full_name.title()

Die Funktion formatted_name () verwendet den Vor- und Nachnamen und kombiniert sie mit einem Leerzeichen dazwischen, um einen vollständigen Namen zu bilden. Dann wird der erste Buchstabe jedes Wortes groß geschrieben. Um zu überprüfen, ob dieser Code funktioniert, müssen Sie Code schreiben, der diese Funktion verwendet. In names.py werde ich einen einfachen Code schreiben, mit dem Benutzer ihren Vor- und Nachnamen eingeben können:

from name_function import formatted_name print("Please enter the first and last names or enter x to E[x]it.") while True: first_name = input("Please enter the first name: ") if first_name == "x": print("Good bye.") break last_name = input("Please enter the last name: ") if last_name == "x": print("Good bye.") break result = formatted_name(first_name, last_name) print("Formatted name is: " + result + ".")

Dieser Code importiert formatierten_Namen () aus name_function.py und ermöglicht beim Ausführen dem Benutzer die Eingabe einer Reihe von Vor- und Nachnamen sowie die Anzeige der formatierten vollständigen Namen.

Unit Test und Testfälle

In Pythons Standardbibliothek gibt es ein Modul namens unittest, das Tools zum Testen Ihres Codes enthält. Beim Unit-Test wird überprüft, ob alle spezifischen Teile des Verhaltens Ihrer Funktion korrekt sind, wodurch die Integration mit anderen Teilen erheblich vereinfacht wird.

Der Testfall ist eine Sammlung von Komponententests, die zusammen beweisen, dass eine Funktion wie beabsichtigt funktioniert, und zwar in einer Reihe von Situationen, in denen sich diese Funktion möglicherweise befindet und von denen erwartet wird, dass sie funktioniert. Der Testfall sollte alle möglichen Arten von Eingaben berücksichtigen, die eine Funktion von Benutzern erhalten könnte, und daher Tests enthalten, um jede dieser Situationen darzustellen.

Einen Test bestehen

Hier ist ein typisches Szenario für das Schreiben von Tests:

Zuerst müssen Sie eine Testdatei erstellen. Importieren Sie dann das unittest-Modul, definieren Sie die Testklasse, die von unittest.TestCase erbt, und schreiben Sie zuletzt eine Reihe von Methoden, um alle Fälle des Verhaltens Ihrer Funktion zu testen.

Es gibt eine zeilenweise Erklärung unter dem folgenden Code:

import unittest from name_function import formatted_name class NamesTestCase(unittest.TestCase): def test_first_last_name(self): result = formatted_name("pete", "seeger") self.assertEqual(result, "Pete Seeger")

Zuerst müssen Sie eine unittest und die Funktion, die Sie testen möchten, formatierter_name () importieren. Anschließend erstellen Sie eine Klasse, z. B. NamesTestCase, die Tests für Ihre Funktion formatierter_name () enthält. Diese Klasse erbt von der Klasse unittest.TestCase.

NamesTestCase enthält eine einzelne Methode, die einen Teil von formatated_name () testet. Sie können diese Methode test_first_last_name () aufrufen.

Denken Sie daran, dass jede Methode, die mit "test_" beginnt, automatisch ausgeführt wird, wenn Sie test_name_function.py ausführen.

Innerhalb der Testmethode test_first_last_name () rufen Sie die Funktion auf, die Sie testen möchten, und speichern einen Rückgabewert. In diesem Beispiel rufen wir formatted_name () mit den Argumenten "pete" und "seeger" auf und speichern das Ergebnis in der resultierenden Variablen.

In der letzten Zeile verwenden wir die assert-Methode. Die Assert-Methode überprüft, ob ein Ergebnis, das Sie erhalten haben, mit dem erwarteten Ergebnis übereinstimmt. In diesem Fall wissen wir, dass die Funktion formatted_name () den vollständigen Namen mit großgeschriebenen Anfangsbuchstaben zurückgibt. Daher erwarten wir das Ergebnis „Pete Seeger“. Um dies zu überprüfen, wird die assertEqual () -Methode des Unittest verwendet.

self.assertEqual(result, “Pete Seeger”)

Diese Zeile bedeutet im Grunde: Vergleichen Sie den Wert in der resultierenden Variablen mit "Pete Seeger" und wenn sie gleich sind, ist es in Ordnung, aber wenn sie es nicht wissen lassen.

Wenn Sie test_name_function.py ausführen, wird erwartet, dass Sie ein OK erhalten, was bedeutet, dass der Test bestanden wurde.

Ran 1 test in 0.001s OK

Test fehlgeschlagen

Um Ihnen zu zeigen, wie ein fehlgeschlagener Test aussieht, werde ich eine formatierte_Name () -Funktion ändern, indem ich ein neues Argument für den zweiten Vornamen einbinde.

Also werde ich die Funktion so umschreiben, dass sie so aussieht:

#Generate a formatted full name including a middle name def formatted_name(first_name, last_name, middle_name): full_name = first_name + ' ' + middle_name + ' ' + last_name return full_name.title()

Diese Version von formatted_name () funktioniert für Personen mit Zweitnamen. Wenn Sie sie jedoch testen, werden Sie feststellen, dass die Funktion für Personen ohne Zweitnamen fehlerhaft ist.

Wenn Sie also test_name_function.py ausführen, erhalten Sie die Ausgabe, die ungefähr so ​​aussieht:

Error Traceback (most recent call last): File “test_name_function.py”, line 7, in test_first_last_name result = formatted_name(“pete”, “seeger”) TypeError: formatted_name() missing 1 required positional argument: ‘middle_name’ Ran 1 test in 0.002s FAILED (errors=1)

In der Ausgabe sehen Sie Informationen, die Ihnen alles sagen, was Sie wissen müssen, wo der Test fehlschlägt:

  • Das erste Element in der Ausgabe ist der Fehler, der Ihnen mitteilt, dass mindestens ein Test im Testfall zu einem Fehler geführt hat.
  • Als nächstes sehen Sie die Datei und Methode, in der der Fehler aufgetreten ist.
  • Danach sehen Sie die Zeile, in der der Fehler aufgetreten ist.
  • Und was für ein Fehler es ist, in diesem Fall fehlt 1 Argument "zweiter_name".
  • Sie sehen auch die Anzahl der ausgeführten Tests, die Zeit, die für den Abschluss der Tests benötigt wird, und eine Textnachricht, die den Status der Tests mit der Anzahl der aufgetretenen Fehler darstellt.

Was tun, wenn der Test fehlgeschlagen ist?

Ein bestehender Test bedeutet, dass sich die Funktion entsprechend den Erwartungen verhält. Ein fehlgeschlagener Test bedeutet jedoch, dass Sie mehr Spaß vor sich haben.

Ich habe einige Programmierer gesehen, die es vorziehen, den Test zu ändern, anstatt den Code zu verbessern - aber nicht dazu. Nehmen Sie sich etwas mehr Zeit, um das Problem zu beheben, da dies Ihnen hilft, den Code besser zu verstehen und auf lange Sicht Zeit zu sparen.

In this example, our function formatted_name() first required two  parameters, and now as it is rewritten it requires one extra: a middle name. Adding a middle name to our function broke the desired behavior of  it. Since the idea is not to make changes to the tests, the best solution is to make middle name optional.

After we do this the idea is to make the tests pass when the first and last name are used, for example “Pete Seeger”, as well as when first, last and middle names are used, for example “Raymond Red Reddington”. So  let’s modify the code of formatted_name() once again:

#Generate a formatted full name including a middle name def formatted_name(first_name, last_name,): if len(middle_name) > 0: full_name = first_name + ' ' + middle_name + ' ' + last_name else: full_name = first_name + ' ' + last_name return full_name.title()

Now the function should work for names with and without the middle name.

And to make sure it still works with “Pete Seeger” run the test again:

Ran 1 test in 0.001s OK
Und das wollte ich Ihnen zeigen: Es ist immer besser, Änderungen an Ihrem Code vorzunehmen, um sie an Ihre Tests anzupassen, als umgekehrt. Jetzt ist es an der Zeit, einen neuen Test für Namen hinzuzufügen, die einen zweiten Vornamen haben.

Neue Tests hinzufügen

Schreiben Sie eine neue Methode in die NamesTestCase-Klasse, die auf Zweitnamen prüft:

import unittest from name_function import formatted_name class NamesTestCase(unittest.TestCase): def test_first_last_name(self): result = formatted_name("pete", "seeger") self.assertEqual(result, "Pete Seeger") def test_first_last_middle_name(self): result = formatted_name("raymond", "reddington", "red") self.assertEqual(result, "Raymond Red Reddington")

Nachdem Sie den Test ausgeführt haben, sollten beide Tests bestanden werden:

Ran 2 tests in 0.001s OK
Bra gjort!

Gut gemacht!

Sie haben Ihre Tests geschrieben, um zu überprüfen, ob die Funktion mit Namen mit oder ohne Zweitnamen funktioniert. Seien Sie gespannt auf Teil 2, in dem ich mehr über das Testen in Python sprechen werde.

Danke fürs Lesen! Weitere Artikel wie diesen finden Sie in meinem freeCodeCamp-Profil: //www.freecodecamp.org/news/author/goran/ und andere lustige Dinge, die ich auf meiner GitHub-Seite baue: //github.com/GoranAviani