Testen von Thread-Anwendungen

In diesem Kapitel erfahren Sie, wie Sie Thread-Anwendungen testen. Wir werden auch lernen, wie wichtig das Testen ist.

Warum testen?

Bevor wir in die Diskussion über die Wichtigkeit des Testens eintauchen, müssen wir wissen, was Testen ist. Im Allgemeinen ist das Testen eine Technik, um herauszufinden, wie gut etwas funktioniert. Wenn wir jedoch speziell über Computerprogramme oder Software sprechen, ist Testen die Technik des Zugriffs auf die Funktionalität eines Softwareprogramms.

In diesem Abschnitt werden wir die Bedeutung von Softwaretests diskutieren. Bei der Softwareentwicklung muss vor der Freigabe der Software an den Client eine doppelte Überprüfung durchgeführt werden. Aus diesem Grund ist es sehr wichtig, die Software von einem erfahrenen Testteam zu testen. Berücksichtigen Sie die folgenden Punkte, um die Bedeutung von Softwaretests zu verstehen:

Verbesserung der Softwarequalität

Sicherlich möchte kein Unternehmen Software von geringer Qualität liefern und kein Kunde möchte Software von geringer Qualität kaufen. Das Testen verbessert die Qualität der Software, indem die darin enthaltenen Fehler gefunden und behoben werden.

Kundenzufriedenheit

Der wichtigste Teil eines Unternehmens ist die Zufriedenheit seiner Kunden. Durch die Bereitstellung fehlerfreier und qualitativ hochwertiger Software können die Unternehmen Kundenzufriedenheit erreichen.

Verringern Sie die Auswirkungen neuer Funktionen

Angenommen, wir haben ein Softwaresystem mit 10000 Zeilen erstellt und müssen eine neue Funktion hinzufügen, dann hätte das Entwicklungsteam Bedenken hinsichtlich der Auswirkungen dieser neuen Funktion auf die gesamte Software. Auch hier spielt das Testen eine wichtige Rolle, denn wenn das Testteam eine gute Reihe von Tests durchgeführt hat, kann es uns vor möglichen katastrophalen Unterbrechungen bewahren.

Benutzererfahrung

Ein weiterer wichtiger Teil eines Unternehmens ist die Erfahrung der Benutzer dieses Produkts. Nur durch Tests kann sichergestellt werden, dass der Endbenutzer das Produkt einfach und leicht verwenden kann.

Kosten senken

Durch Testen können die Gesamtkosten von Software gesenkt werden, indem die Fehler in der Testphase ihrer Entwicklung gefunden und behoben werden, anstatt sie nach der Auslieferung zu beheben. Wenn nach der Lieferung der Software ein schwerwiegender Fehler auftritt, erhöht dies die materiellen Kosten, beispielsweise in Bezug auf die Kosten, und die immateriellen Kosten, beispielsweise in Bezug auf die Unzufriedenheit der Kunden, den negativen Ruf des Unternehmens usw.

Was zu testen?

Es wird immer empfohlen, über ausreichende Kenntnisse darüber zu verfügen, was getestet werden soll. In diesem Abschnitt werden wir zunächst verstehen, was das Hauptmotiv des Testers beim Testen einer Software ist. Codeabdeckung, dh wie viele Codezeilen unsere Testsuite beim Testen trifft, sollte vermieden werden. Dies liegt daran, dass beim Testen die Konzentration auf die Anzahl der Codezeilen unserem System keinen wirklichen Wert verleiht. Möglicherweise bleiben einige Fehler bestehen, die sich auch nach der Bereitstellung zu einem späteren Zeitpunkt widerspiegeln.

Berücksichtigen Sie die folgenden wichtigen Punkte in Bezug auf das zu testende Element:

  • Wir müssen uns darauf konzentrieren, die Funktionalität des Codes zu testen und nicht die Codeabdeckung.

  • Wir müssen zuerst die wichtigsten Teile des Codes testen und uns dann den weniger wichtigen Teilen des Codes zuwenden. Das spart definitiv Zeit.

  • Der Tester muss über eine Vielzahl unterschiedlicher Tests verfügen, die die Software an ihre Grenzen bringen können.

Ansätze zum Testen gleichzeitiger Softwareprogramme

Aufgrund der Fähigkeit, die wahre Fähigkeit einer Mehrkernarchitektur zu nutzen, ersetzen gleichzeitige Softwaresysteme sequentielle Systeme. In jüngster Zeit werden gleichzeitige Systemprogramme in allen Bereichen verwendet, von Mobiltelefonen bis zu Waschmaschinen, von Autos bis zu Flugzeugen usw. Wir müssen beim Testen der gleichzeitigen Softwareprogramme vorsichtiger sein, da wir einer einzelnen Thread-Anwendung mehrere Threads hinzugefügt haben schon ein Fehler, dann würden wir am Ende mehrere Fehler haben.

Testtechniken für gleichzeitige Softwareprogramme konzentrieren sich weitgehend auf die Auswahl von Verschachtelungen, die potenziell schädliche Muster wie Rennbedingungen, Deadlocks und Verstöße gegen die Atomizität aufdecken. Es folgen zwei Ansätze zum Testen gleichzeitiger Softwareprogramme:

Systematische Erforschung

Dieser Ansatz zielt darauf ab, den Raum der Verschachtelungen so weit wie möglich zu untersuchen. Solche Ansätze können eine Brute-Force-Technik anwenden, und andere verwenden eine Technik zur Reduzierung der Teilordnung oder eine heuristische Technik, um den Raum der Verschachtelungen zu erkunden.

Immobiliengetrieben

Eigenschaftsgesteuerte Ansätze beruhen auf der Beobachtung, dass Parallelitätsfehler eher bei Verschachtelungen auftreten, die bestimmte Eigenschaften wie verdächtiges Speicherzugriffsmuster offenlegen. Unterschiedliche eigenschaftsgesteuerte Ansätze zielen auf unterschiedliche Fehler wie Rennbedingungen, Deadlocks und Verletzung der Atomizität ab, was ferner von der einen oder anderen spezifischen Eigenschaft abhängt.

Teststrategien

Die Teststrategie wird auch als Testansatz bezeichnet. Die Strategie definiert, wie Tests durchgeführt werden sollen. Testansatz hat zwei Techniken -

Proaktiv

Ein Ansatz, bei dem der Testentwurfsprozess so früh wie möglich eingeleitet wird, um die Fehler zu finden und zu beheben, bevor der Build erstellt wird.

Reaktiv

Ein Ansatz, bei dem das Testen erst nach Abschluss des Entwicklungsprozesses beginnt.

Bevor wir eine Teststrategie oder einen Testansatz auf ein Python-Programm anwenden, müssen wir eine grundlegende Vorstellung von der Art der Fehler haben, die ein Softwareprogramm haben kann. Die Fehler sind wie folgt:

Syntaktische Fehler

Während der Programmentwicklung können viele kleine Fehler auftreten. Die Fehler sind hauptsächlich auf Tippfehler zurückzuführen. Zum Beispiel fehlender Doppelpunkt oder falsche Schreibweise eines Schlüsselworts usw. Solche Fehler sind auf Fehler in der Programmsyntax und nicht in der Logik zurückzuführen. Daher werden diese Fehler als syntaktische Fehler bezeichnet.

Semantische Fehler

Die semantischen Fehler werden auch als logische Fehler bezeichnet. Wenn im Softwareprogramm ein logischer oder semantischer Fehler vorliegt, wird die Anweisung kompiliert und korrekt ausgeführt, es wird jedoch nicht die gewünschte Ausgabe ausgegeben, da die Logik nicht korrekt ist.

Unit Testing

Dies ist eine der am häufigsten verwendeten Teststrategien zum Testen von Python-Programmen. Diese Strategie wird zum Testen von Einheiten oder Komponenten des Codes verwendet. Mit Einheiten oder Komponenten meinen wir Klassen oder Funktionen des Codes. Unit-Tests vereinfachen das Testen großer Programmiersysteme, indem „kleine“ Einheiten getestet werden. Mit Hilfe des obigen Konzepts kann das Testen von Einheiten als ein Verfahren definiert werden, bei dem einzelne Einheiten des Quellcodes getestet werden, um festzustellen, ob sie die gewünschte Ausgabe zurückgeben.

In unseren folgenden Abschnitten lernen wir die verschiedenen Python-Module für Unit-Tests kennen.

unittest Modul

Das allererste Modul für Unit-Tests ist das unittest-Modul. Es ist von JUnit inspiriert und standardmäßig in Python3.6 enthalten. Es unterstützt die Testautomatisierung, die gemeinsame Nutzung von Setup- und Shutdown-Code für Tests, die Aggregation von Tests zu Sammlungen und die Unabhängigkeit der Tests vom Berichtsframework.

Im Folgenden finden Sie einige wichtige Konzepte, die vom unittest-Modul unterstützt werden

Textvorrichtung

Es wird verwendet, um einen Test so einzurichten, dass er vor Beginn des Tests ausgeführt und nach Beendigung des Tests abgerissen werden kann. Möglicherweise müssen temporäre Datenbanken, Verzeichnisse usw. erstellt werden, die vor Beginn des Tests erforderlich sind.

Testfall

Der Testfall prüft, ob eine erforderliche Antwort von einem bestimmten Satz von Eingaben kommt oder nicht. Das unittest-Modul enthält eine Basisklasse namens TestCase, mit der neue Testfälle erstellt werden können. Es enthält standardmäßig zwei Methoden:

  • setUp()- eine Hakenmethode zum Aufstellen der Prüfvorrichtung vor dem Training. Dies wird aufgerufen, bevor die implementierten Testmethoden aufgerufen werden.

  • tearDown( - Eine Hook-Methode zum Dekonstruieren des Klassen-Fixtures, nachdem alle Tests in der Klasse ausgeführt wurden.

Testsuite

Es ist eine Sammlung von Testsuiten, Testfällen oder beidem.

Testläufer

Es steuert den Ablauf der Testfälle oder Anzüge und liefert dem Benutzer das Ergebnis. Es kann eine grafische Benutzeroberfläche oder eine einfache Textschnittstelle verwenden, um das Ergebnis bereitzustellen.

Example

Das folgende Python-Programm verwendet das unittest-Modul, um ein Modul mit dem Namen zu testen Fibonacci. Das Programm hilft bei der Berechnung der Fibonacci-Reihe einer Zahl. In diesem Beispiel haben wir eine Klasse mit dem Namen Fibo_test erstellt, um die Testfälle mithilfe verschiedener Methoden zu definieren. Diese Methoden werden von unittest.TestCase geerbt. Wir verwenden standardmäßig zwei Methoden - setUp () und tearDown (). Wir definieren auch die Testfibokalmethode. Der Name des Tests muss mit dem Buchstabentest begonnen werden. Im letzten Block bietet unittest.main () eine Befehlszeilenschnittstelle zum Testskript.

import unittest
def fibonacci(n):
   a, b = 0, 1
   for i in range(n):
   a, b = b, a + b
   return a
class Fibo_Test(unittest.TestCase):
   def setUp(self):
   print("This is run before our tests would be executed")
   def tearDown(self):
   print("This is run after the completion of execution of our tests")

   def testfibocal(self):
   self.assertEqual(fib(0), 0)
   self.assertEqual(fib(1), 1)
   self.assertEqual(fib(5), 5)
   self.assertEqual(fib(10), 55)
   self.assertEqual(fib(20), 6765)

if __name__ == "__main__":
   unittest.main()

Wenn das obige Skript über die Befehlszeile ausgeführt wird, wird eine Ausgabe erstellt, die folgendermaßen aussieht:

Ausgabe

This runs before our tests would be executed.
This runs after the completion of execution of our tests.
.
----------------------------------------------------------------------
Ran 1 test in 0.006s
OK

Um es klarer zu machen, ändern wir jetzt unseren Code, der bei der Definition des Fibonacci-Moduls geholfen hat.

Betrachten Sie den folgenden Codeblock als Beispiel:

def fibonacci(n):
   a, b = 0, 1
   for i in range(n):
   a, b = b, a + b
   return a

Einige Änderungen am Codeblock werden wie unten gezeigt vorgenommen -

def fibonacci(n):
   a, b = 1, 1
   for i in range(n):
   a, b = b, a + b
   return a

Nachdem Sie das Skript mit dem geänderten Code ausgeführt haben, erhalten wir die folgende Ausgabe:

This runs before our tests would be executed.
This runs after the completion of execution of our tests.
F
======================================================================
FAIL: testCalculation (__main__.Fibo_Test)
----------------------------------------------------------------------
Traceback (most recent call last):
File "unitg.py", line 15, in testCalculation
self.assertEqual(fib(0), 0)
AssertionError: 1 != 0
----------------------------------------------------------------------
Ran 1 test in 0.007s

FAILED (failures = 1)

Die obige Ausgabe zeigt, dass das Modul die gewünschte Ausgabe nicht liefern konnte.

Docktest-Modul

Das Docktest-Modul hilft auch beim Testen von Einheiten. Es kommt auch mit Python vorverpackt. Es ist einfacher zu bedienen als das unittest Modul. Das unittest-Modul eignet sich besser für komplexe Tests. Um das doctest-Modul verwenden zu können, müssen wir es importieren. Die Dokumentzeichenfolge der entsprechenden Funktion muss zusammen mit ihren Ausgaben über eine interaktive Python-Sitzung verfügen.

Wenn in unserem Code alles in Ordnung ist, wird vom Docktest-Modul keine Ausgabe ausgegeben. Andernfalls wird die Ausgabe bereitgestellt.

Beispiel

Das folgende Python-Beispiel verwendet das Docktest-Modul, um ein Modul namens Fibonacci zu testen, das bei der Berechnung der Fibonacci-Reihe einer Zahl hilft.

import doctest
def fibonacci(n):
   """
   Calculates the Fibonacci number

   >>> fibonacci(0)
   0
   >>> fibonacci(1)
   1
   >>> fibonacci(10)
   55
   >>> fibonacci(20)
   6765
   >>>

   """
   a, b = 1, 1
   for i in range(n):
   a, b = b, a + b
   return a
      if __name__ == "__main__":
   doctest.testmod()

Wir können sehen, dass die Dokumentzeichenfolge der entsprechenden Funktion namens fib zusammen mit den Ausgaben eine interaktive Python-Sitzung hatte. Wenn unser Code in Ordnung ist, wird vom doctest-Modul keine Ausgabe ausgegeben. Um zu sehen, wie es funktioniert, können wir es mit der Option –v ausführen.

(base) D:\ProgramData>python dock_test.py -v
Trying:
   fibonacci(0)
Expecting:
   0
ok
Trying:
   fibonacci(1)
Expecting:
   1
ok
Trying:
   fibonacci(10)
Expecting:
   55
ok
Trying:
   fibonacci(20)
Expecting:
   6765
ok
1 items had no tests:
   __main__
1 items passed all tests:
4 tests in __main__.fibonacci
4 tests in 2 items.
4 passed and 0 failed.
Test passed.

Jetzt werden wir den Code ändern, der bei der Definition des Fibonacci-Moduls geholfen hat

Betrachten Sie den folgenden Codeblock als Beispiel:

def fibonacci(n):
   a, b = 0, 1
   for i in range(n):
   a, b = b, a + b
   return a

Der folgende Codeblock hilft bei den Änderungen -

def fibonacci(n):
   a, b = 1, 1
   for i in range(n):
   a, b = b, a + b
   return a

Nachdem Sie das Skript auch ohne die Option –v mit dem geänderten Code ausgeführt haben, erhalten Sie die Ausgabe wie unten gezeigt.

Ausgabe

(base) D:\ProgramData>python dock_test.py
**********************************************************************
File "unitg.py", line 6, in __main__.fibonacci
Failed example:
   fibonacci(0)
Expected:
   0
Got:
   1
**********************************************************************
File "unitg.py", line 10, in __main__.fibonacci
Failed example:
   fibonacci(10)
Expected:
   55
Got:
   89
**********************************************************************
File "unitg.py", line 12, in __main__.fibonacci
Failed example:
   fibonacci(20)
Expected:
   6765
Got:
   10946
**********************************************************************
1 items had failures:
   3 of 4 in __main__.fibonacci
***Test Failed*** 3 failures.

Wir können in der obigen Ausgabe sehen, dass drei Tests fehlgeschlagen sind.