Parametrisiertes Unit-Testen in Python

Abid Ullah 21 Juni 2023
  1. Zweck des parametrisierten Unit-Tests in Python
  2. Beispiele für parametrisierte Komponententests in Python
  3. Vorteile des parametrisierten Unit-Tests in Python
  4. Python-Bibliotheken, die parametrisierte Komponententests unterstützen
Parametrisiertes Unit-Testen in Python

Unit-Tests sind ein mächtiges Werkzeug, um die Qualität der Software zu erhalten. Komponententests für Software sind eine Reihe von Überprüfungen eines Codeabschnitts, um sicherzustellen, dass die Software gemäß den Softwaredesignspezifikationen entwickelt wurde und sich wie für den Endbenutzer vorgesehen verhält oder reagiert.

In Python können wir mit einem parametrisierten Unit-Test unterwegs einen Test für jedes Item oder jeden Testfall generieren. In diesem Artikel werden die parametrisierten Komponententests von Python untersucht.

Zweck des parametrisierten Unit-Tests in Python

Wenn Entwickler Unit-Tests schreiben, wenden sie häufig den One-Test-for-One-Case-Ansatz an. Die ähnlichsten oder verwandten Tests werden dann zu einer Suite zusammengefasst.

Sehen Sie sich die Reihe von Tests im folgenden Code an:

class TestSuite(TestCase):
    def test_first_case(self):
        assert example_test()

    def test_second_case(self):
        assert more_example_tests()

    def test_third_case(self):
        assert another_example_test()

Das Testen durch Suiten wie diese würde bedeuten, dass jeder Testfall eine Reihe von benutzerdefinierten Phasen der Vorbereitung, Ausführung und schließlich der Behauptung durchlaufen muss. Wenn jeder dieser Testfälle ähnlich ist, wäre die resultierende Suite ein Durcheinander von doppeltem oder redundantem Code, was in der Welt der Softwareentwickler geradezu ein Fluch ist.

Diese Suiten führen auch zu großen Codebasen, die extrem schwer zu warten sind, wenn Änderungen vorgenommen werden (was zu erwarten ist). Um diesem Problem entgegenzuwirken, haben wir den Segen dynamischer oder parametrisierter Komponententests in Python, die es uns ermöglichen, einen einzelnen Test für mehrere Fälle zu generieren.

Beispiele für parametrisierte Komponententests in Python

Lassen Sie uns in ein beispielhaftes Testszenario oder eine Methode eintauchen, die wir als Grundlage verwenden können, um parametrisierte Komponententests in Python zu verstehen und wie sie unser Leben als Softwareentwickler viel einfacher machen.

Unten ist eine einfache Funktion, die wir testen möchten:

def compute(a, b):
    return (a + b) / (a * b)

Nun wissen wir, wie bei jedem Test, dass es mehrere Eingaben gibt, die wir auf die obige Funktion anwenden müssen, um zu testen, ob sie sich wie gewünscht verhält. Um die Testparameter ausführlicher zu spezifizieren, müssen wir die Methode anhand folgender Parameter testen:

  • positive ganze Zahlen
  • negative ganze Zahlen
  • lange ganze Zahlen
  • regelmäßige ganze Zahlen
  • Float-Nummer
  • Eine oder beide Zahlen sind Null
  • Eines oder beide Argumente sind undefiniert
  • eines oder beide Argumente sind Zeichenfolgen oder andere Arten von Objekten

Wenn dies mit der Ein-Test-pro-Fall-Methode getestet würde, würden wir eine lange Reihe von sich wiederholendem Code für eine einzeilige Methode schreiben. Sie können sich vorstellen, wie hektisch und mühsam dies für Methoden sein kann, die auf mehreren Codezeilen mit Schleifen und Bedingungen basieren.

Bei der Parametrisierung müssen wir nur Folgendes tun:

def test_compute(self, a, b, expected, raises=None):
    if raises is not None:
        with self.assertRaises(raises):
            compute(a, b)
    else:
        assert compute(a, b) == expected

Damit müssten wir eine Liste von Parametern erstellen, die alle Möglichkeiten für die Berechnungsmethode am besten testen. Die Liste der Parameter kann so lang sein, wie wir wollen, oder nur eine Sammlung der Fälle, die wir testen müssen.

Hier ist ein Beispiel für eine Liste von Parametern, die an den obigen Komponententest übergeben werden können.

Die Ausgabe des Codes:

a           | b   | expected | raises
------------+-----+----------+-------
-2          | 2   | 0        |
0           | 2   |          | ZeroDivisionError
2           | 2   | 1        |
0.5         | 0.4 | 4.5      |
None        | 2   |          | TypeError
"10"        | "1" |          | TypeError
3000000000L | 2   | 0.5      |

Wie man sehen kann, machen es diese Liste und der obige parametrisierte Komponententest für uns viel effizienter, die verschiedenen Szenarien von Argumenten zu testen, die an die compute()-Methode übergeben werden können. Es erleichtert auch die Aufzeichnung der unterschiedlichen Ergebnisse erheblich.

Vorteile des parametrisierten Unit-Tests in Python

Das Schreiben regelmäßiger Komponententests kann sehr repetitiv, erschöpfend, zeitaufwändig und nervenaufreibend sein, insbesondere wenn wir möchten, dass die Tests jedes Softwareszenario durchlaufen und sicherstellen, dass alles den Anforderungen entspricht.

Die Verwendung parametrisierter Komponententests in Python bedeutet, dass wir uns als Entwickler keine Gedanken darüber machen müssen, Hunderte von Codezeilen zu schreiben, um die verschiedenen Szenarien zu testen, die in der zu entwickelnden Software auftreten können, um deren Qualität aufrechtzuerhalten. Wir benötigen lediglich einen einzigen Test, um alle zu testenden Szenarien zu testen.

Dies bedeutet, dass die Testcodebasis immer einfach zu warten ist und wenig bis gar keine Wiederholungen aufweist, was zu effizienten Testfällen und zeitsparenden Ergebnissen führt.

Darüber hinaus zwingen parametrisierte Unit-Tests den betreffenden Entwickler, klarer und definitiver über alle möglichen Eingaben nachzudenken, die in die Methode einfließen. Es hilft, Grenzfälle wie große Ganzzahlen oder inkonsistente Eingabetypen für unser obiges Beispiel und alle fehlerhaften Fälle wie undefinierte Eingaben im Auge zu behalten.

Dieser Test zwingt den Entwickler natürlich auch, mehr darüber nachzudenken, wie die Randfälle gehandhabt werden können, anstatt nur über die Art der Eingabe nachzudenken, die ihren Code beschädigen könnte. Es trägt dazu bei, die Qualität des Codes aufrechtzuerhalten, indem es uns zwingt, vorherzusagen, was die Funktion unter einer bestimmten Kombination von Umständen tun soll, und führt zur Entwicklung konzeptioneller und effizienter Lösungen für alle auftretenden Probleme.

Wenn wir uns dazu entschließen, eine vollständigere oder umfangreichere Liste von Parametern zum Testen unserer Methoden zu verwenden, erhalten wir möglicherweise Ergebnisse und Lösungen für Testfälle, von denen wir zunächst dachten, dass sie zu trivial sind, um einen Testfall zu schreiben. Da uns jedoch ein parametrisierter Test zur Verfügung steht, müssen wir nur die Kombination eingeben, die wir testen möchten, um zu sehen, wie der Code reagiert.

Python-Bibliotheken, die parametrisierte Komponententests unterstützen

Python bietet an, uns das Leben mit der parametrisierten Bibliothek zu erleichtern, die die Entwicklung der Testmethode unkompliziert macht. Alles, was wir tun müssen, ist, parametrisiert zu importieren und die Parameter, die wir testen möchten, durch den parametrisierten Decorator in unserer Methode in der Testsuite wie folgt zu übergeben:

from parameterized import parameterized


class TestSuite(TestCase):
    @parameterized.expand([("test_1", 0, 0, 0), ("test_2", 0, 1, 1)])
    def test_my_feature(self, name, in_1, in_2, expected):
        assert my_feature(in_1, in_2) == expected

Eine andere Möglichkeit besteht darin, eine .csv-Datei mit einer Liste aller Parameter zu erstellen. Dann übergeben wir es an den Dekorateur, um es folgendermaßen zu testen:

def load_test_cases():
    return load_from_csv("my_feature_parameters.csv")


class TestSuite(TestCase):
    @parameterized.expand(load_test_cases)
    def test_my_feature(self, name, in_1, in_2, expected):
        assert my_feature(in_1, in_2) == expected

Wir haben alles abgedeckt, von der Frage, warum wir dynamische (parametrisierte) Komponententests verwenden müssen, bis hin zu den verschiedenen Möglichkeiten, wie wir sie implementieren können, und ihren Vorteilen im Lebenszyklus der Softwareentwicklung. Wir hoffen, dass Sie diesen Artikel hilfreich finden, um zu verstehen, wie Sie Komponententests in Python generieren.

Autor: Abid Ullah
Abid Ullah avatar Abid Ullah avatar

My name is Abid Ullah, and I am a software engineer. I love writing articles on programming, and my favorite topics are Python, PHP, JavaScript, and Linux. I tend to provide solutions to people in programming problems through my articles. I believe that I can bring a lot to you with my skills, experience, and qualification in technical writing.

LinkedIn

Verwandter Artikel - Python Unit Test