Softwaretests sind der Prozess, bei dem ein Entwickler sicherstellt, dass die tatsächliche Ausgabe der Software mit der gewünschten Ausgabe übereinstimmt, indem er einige Testeingaben für die Software bereitstellt. Das Testen von Software ist ein wichtiger Schritt, da es dem Entwickler bei ordnungsgemäßer Durchführung helfen kann, Fehler in der Software in kürzester Zeit zu finden.

Softwaretests können in zwei Klassen unterteilt werden: Manuelle Tests und automatisierte Tests . Automatisiertes Testen ist die Ausführung Ihrer Tests mithilfe eines Skripts anstelle eines Menschen. In diesem Artikel werden einige Methoden zum automatisierten Testen von Software mit Python erläutert.

Schreiben wir eine einfache Anwendung, über die wir alle Tests durchführen.

class Square: 
    def __init__(self, side): 
        
        
        self.side = side 
  
    def area(self): 
        
        
        return self.side**2
  
    def perimeter(self): 
        
        
        return 4 * self.side 
  
    def __repr__(self): 
        
        
        s = 'Square with side = ' + str(self.side) + '\n' + \ 
        'Area = ' + str(self.area()) + '\n' + \ 
        'Perimeter = ' + str(self.perimeter()) 
        return s 
  
  
if __name__ == '__main__': 
    
    side = int(input('enter the side length to create a Square: ')) 
      
    
    square = Square(side) 
  
    
    print(square) 

Hinweis: Weitere Informationen zur Funktion __repr__()finden Sie in diesem Artikel .

Nachdem wir unsere Software fertig haben, schauen wir uns die Verzeichnisstruktur unseres Projektordners an und danach beginnen wir mit dem Testen unserer Software.



---Softwaretest
   | --- __init__.py (um das Verzeichnis als Python-Paket zu initialisieren)
   | --- app.py (unsere Software)
   | --- tests (Ordner zum Speichern aller Testdateien)
           | --- __init__.py

Das 'unittest'-Modul

Eines der Hauptprobleme beim manuellen Testen ist, dass es Zeit und Mühe erfordert. Beim manuellen Testen testen wir die Anwendung über eine Eingabe. Wenn dies fehlschlägt, notieren wir sie entweder oder wir debuggen die Anwendung für diese bestimmte Testeingabe und wiederholen dann den Vorgang. Mit unittestkönnen alle Testeingaben gleichzeitig bereitgestellt werden, und dann können Sie Ihre Anwendung testen. Am Ende erhalten Sie einen detaillierten Bericht mit allen fehlgeschlagenen Testfällen, sofern vorhanden.

Das unittestModul verfügt sowohl über ein integriertes Testframework als auch über einen Testläufer. Ein Testframework besteht aus einer Reihe von Regeln, die beim Schreiben von Testfällen befolgt werden müssen, während ein Testläufer ein Tool ist, das diese Tests mit einer Reihe von Einstellungen ausführt und die Ergebnisse sammelt.

Installation: unittest ist bei PyPI verfügbar und kann mit dem folgenden Befehl installiert werden:

pip install unittest

Verwendung: Wir schreiben die Tests in ein Python-Modul (.py). Um unsere Tests auszuführen, führen wir das Testmodul einfach mit einer beliebigen IDE oder einem beliebigen Terminal aus.

Lassen Sie uns nun einige Tests für unsere kleine Software schreiben, die oben mit dem unittestModul besprochen wurden .

  1. Erstellen Sie eine Datei mit tests.pydem Namen "tests".
  2. Im tests.pyImport unittest.
  3. Erstellen Sie eine Klasse mit dem Namen, TestClassdie von der Klasse erbt unittest.TestCase.

    Regel 1: Alle Tests werden als Methoden einer Klasse geschrieben, die von der Klasse erben müssen unittest.TestCase.

  4. Erstellen Sie eine Testmethode wie unten gezeigt.
    Regel 2: Der Name jeder Testmethode sollte mit „Test“ beginnen, da er sonst vom Testläufer übersprungen wird.
    filter_none

    bearbeiten
    schließen

    play_arrow

    Link
    Helligkeit_4
    Code

    def test_area(self):
        
          
        sq = Square(2)   
     
        
        
     
        self.assertEqual(sq.area(), 4
            f'Area is shown {sq.area()} for side = {sq.side} units')
    chevron_right
    
    
    filter_none
    
    

    Regel 3: Wir verwenden spezielle assertEqual()Anweisungen anstelle der assertin Python verfügbaren integrierten Anweisungen.

    Das erste Argument von assertEqual()ist die tatsächliche Ausgabe, das zweite Argument ist die gewünschte Ausgabe und das dritte Argument ist die Fehlermeldung, die angezeigt wird, wenn sich die beiden Werte voneinander unterscheiden (Test schlägt fehl).

  5. Um die soeben definierten Tests auszuführen, müssen wir die Methode aufrufen unittest.main()und die folgenden Zeilen im Modul "tests.py" hinzufügen.
    filter_none

    bearbeiten
    schließen

    play_arrow

    Link
    Helligkeit_4
    Code

    if __name__ == '__main__':
        unittest.main()
    chevron_right
    
    
    filter_none
    
    

    Aufgrund dieser Zeilen wird die Funktion unittest.main()aufgerufen , sobald Sie das Skript "test.py" ausführen, und alle Tests werden ausgeführt.

Schließlich sollte das Modul "tests.py" dem unten angegebenen Code ähneln.



import unittest 
from .. import app 
  
class TestSum(unittest.TestCase): 
  
    def test_area(self): 
        sq = app.Square(2) 
  
        self.assertEqual(sq.area(), 4
            f'Area is shown {sq.area()} rather than 9') 
  
if __name__ == '__main__': 
    unittest.main() 

Nachdem wir unsere Testfälle geschrieben haben, können wir unsere Anwendung jetzt auf Fehler testen. Um Ihre Anwendung zu testen, müssen Sie lediglich die Testdatei „tests.py“ über die Eingabeaufforderung oder eine IDE Ihrer Wahl ausführen. Die Ausgabe sollte ungefähr so ​​sein.

.
-------------------------------------------------- --------------------
Lief 1 Test in 0,000s
OK

In der ersten Zeile steht ein .(Punkt) für einen erfolgreichen Test, während ein 'F' einen fehlgeschlagenen Testfall darstellt. Die OKNachricht sagt uns am Ende, dass alle Tests erfolgreich bestanden wurden.

Fügen wir ein paar weitere Tests in "tests.py" hinzu und testen Sie unsere Anwendung erneut.

import unittest 
from .. import app 
  
class TestSum(unittest.TestCase): 
  
    def test_area(self): 
        sq = app.Square(2) 
        self.assertEqual(sq.area(), 4
            f'Area is shown {sq.area()} rather than 9') 
  
    def test_area_negative(self): 
        sq = app.Square(-3) 
        self.assertEqual(sq.area(), -1
            f'Area is shown {sq.area()} rather than -1') 
  
    def test_perimeter(self): 
        sq = app.Square(5) 
        self.assertEqual(sq.perimeter(), 20
            f'Perimeter is {sq.perimeter()} rather than 20') 
  
    def test_perimeter_negative(self): 
        sq = app.Square(-6) 
        self.assertEqual(sq.perimeter(), -1
            f'Perimeter is {sq.perimeter()} rather than -1') 
  
if __name__ == '__main__': 
    unittest.main() 
.FF
================================================== ====================
FAIL: test_area_negative (__main __. TestSum)
-------------------------------------------------- --------------------
Traceback (letzter Anruf zuletzt):
  Datei "tests_unittest.py", Zeile 11, in test_area_negative
    self.assertEqual (sq.area(), -1, f'Area wird angezeigt {sq.area()} anstelle von -1 für negative Seitenlänge ')
AssertionError: 9! = -1: Für die negative Seitenlänge wird der Bereich 9 anstelle von -1 angezeigt
================================================== ====================
FAIL: test_perimeter_negative (__main __. TestSum)
-------------------------------------------------- --------------------
Traceback (letzter Anruf zuletzt):
  Datei "tests_unittest.py", Zeile 19, in test_perimeter_negative
    self.assertEqual (sq.perimeter(), -1, f'Perimeter ist {sq.perimeter()} anstelle von -1 für negative Seitenlänge ')
AssertionError: -24! = -1: Der Umfang ist -24 anstelle von -1 für die negative Seitenlänge
-------------------------------------------------- --------------------
4 Tests in 0,001 s durchgeführt
FEHLGESCHLAGEN (Fehler = 2)

Einige Dinge, die im obigen Testbericht zu beachten sind, sind:

  • Die erste Zeile zeigt, dass Test 1 und Test 3 erfolgreich ausgeführt wurden, während Test 2 und Test 4 fehlgeschlagen sind
  • Jeder fehlgeschlagene Testfall wird im Bericht beschrieben, die erste Zeile der Beschreibung enthält den Namen des fehlgeschlagenen Testfalls und die letzte Zeile enthält die Fehlermeldung, die wir für diesen Testfall definiert haben.
  • Am Ende des Berichts sehen Sie die Anzahl der fehlgeschlagenen Tests. Wenn kein Test fehlschlägt, endet der Bericht mit OK

Hinweis: Für weitere Informationen können Sie die vollständige Dokumentation von lesen unittest.

Das Modul "Nase2"

Der Zweck von nose2ist zu erweitern unittest, um das Testen zu vereinfachen. nose2ist kompatibel mit Tests, die mit dem unittestTestframework geschrieben wurden, und kann als Ersatz für den unittestTestläufer verwendet werden.

Installation: nose2 Kann mit dem Befehl von PyPI installiert werden.

Pip installieren Nase2

Verwendung: nose2 hat kein Testframework und ist lediglich ein Testläufer, der mit dem unittestTestframework kompatibel ist . Daher werden wir dieselben Tests ausführen, die wir oben (für unittest) geschrieben haben nose2. Um die Tests auszuführen, verwenden wir den folgenden Befehl im Projektquellverzeichnis (in unserem Fall „Software_Testing“):

Nase2

In der nose2Terminologie werden alle Python-Module (.py) mit einem Namen ab "test" (dh test_file.py, test_1.py) als Testdateien betrachtet. Sucht bei der Ausführung nose2nach allen Testdateien in allen Unterverzeichnissen, die unter einer oder mehreren der folgenden Kategorien liegen:

  • Dies sind Python-Pakete (enthalten "__init__.py").
  • dessen Name mit "test" beginnt, nachdem er in Kleinbuchstaben geschrieben wurde, dh "TestFiles", testet.
  • die entweder "src" oder "lib" heißen.

nose2Lädt zuerst alle im Projekt vorhandenen Testdateien und führt dann die Tests aus. So haben nose2wir die Freiheit, unsere Tests auf verschiedene Testdateien in verschiedenen Ordnern aufzuteilen und gleichzeitig auszuführen, was bei einer großen Anzahl von Tests sehr nützlich ist.



Lassen Sie uns nun verschiedene Anpassungsoptionen kennenlernen, nose2die uns beim Testen helfen können.

  1. Ändern des Suchverzeichnisses -
    Wenn Sie das Verzeichnis ändern möchten, in dem nose2nach Testdateien gesucht wird , können Sie dies mithilfe der Befehlszeilenargumente -soder --start-dirals, tun.
    Nase2 -s DIR_ADD DIR_NAME

    Hier DIR_NAMEist das Verzeichnis, in dem nach den Testdateien gesucht werden soll, und DIR_ADDdie Adresse des übergeordneten Verzeichnisses DIR_NAMErelativ zum Projektquellverzeichnis (dh verwenden Sie "./", wenn sich das Testverzeichnis im Projektquellverzeichnis selbst befindet).
    Dies ist äußerst nützlich, wenn Sie jeweils nur eine Funktion Ihrer Anwendung testen möchten.

  2. Ausführen bestimmter Testfälle -
    Mit nose2können Sie auch einen bestimmten Test gleichzeitig ausführen, indem Sie die Befehlszeilenargumente -sund --start-diras verwenden.
    Nase2 -s DIR_ADD DIR_NAME.TEST_FILE.TEST_CLASS.TEST_NAME
    • TEST_NAME: Name der Testmethode.
    • TEST_CLASS: Klasse, in der die Testmethode definiert ist.
    • TEST_FILE: Name der Testdatei, in der der Testfall definiert ist, dh test.py.
    • DIR_NAME: Verzeichnis, in dem die Testdatei vorhanden ist.
    • DIR_ADD: Adresse des übergeordneten Verzeichnisses von DIR_NAME relativ zur Projektquelle.

    Mit dieser Funktion können wir unsere Software an bestimmten Eingaben testen.

  3. Ausführen von Tests in einem einzelnen Modul -
    nose2 kann auch wie unittestdurch Aufrufen der Funktion verwendet werden, nose2.main()wie wir sie unittest.main()in den vorherigen Beispielen aufgerufen haben .
  4. Abgesehen von den oben genannten grundlegenden Anpassungen nose2bietet es erweiterte Funktionen wie das Laden verschiedener Plugins und Konfigurationsdateien oder das Erstellen eines eigenen Testläufers.

Das "Pytest" -Modul

pytestist das beliebteste Testframework für Python. Mit können pytestSie alles testen, von einfachen Python-Skripten bis hin zu Datenbanken, APIs und Benutzeroberflächen. Obwohl pytestes hauptsächlich für API-Tests verwendet wird, werden in diesem Artikel nur die Grundlagen von behandelt pytest.

Installation: Sie können pytestvon PyPI mit dem Befehl installieren.

pip install pytest

Verwendung: Der pytestTestläufer wird mit dem folgenden Befehl in der Projektquelle aufgerufen:

py.test

Im Gegensatz dazu nose2wird pytestan allen Speicherorten im Projektverzeichnis nach Testdateien gesucht. Jede Datei mit einem Namen, der mit "test_" beginnt oder mit "_test" endet, wird in der pytestTerminologie als Testdatei betrachtet . Erstellen wir eine Datei "test_file1.py" im Ordner "tests" als unsere Testdatei.

Erstellen von Testmethoden:
pytest Unterstützt die im unittestFramework geschriebenen Testmethoden , das pytestFramework bietet jedoch eine einfachere Syntax zum Schreiben von Tests. Im folgenden Code finden Sie Informationen zur Testmethodensyntax des pytestFrameworks.

from .. import app 
  
def test_file1_area(): 
    sq = app.Square(2) 
    assert sq.area() == 4
        f"area for side {sq.side} units is {sq.area()}"
  
def test_file1_perimeter(): 
    sq = app.Square(-1) 
    assert sq.perimeter() == -1
        f'perimeter is shown {sq.perimeter()} rather than -1'

Hinweis: Ähnlich wie unittestbei pytestmüssen alle Testnamen mit "test" beginnen.

Im Gegensatz zu unittest, pytestnutzt die Python - Standard assertAnweisungen , die es weiter einfacher zu bedienen.



Beachten Sie, dass der Ordner "tests" jetzt zwei Dateien enthält, nämlich "tests.py" (im unittestFramework geschrieben) und "test_file1.py" (im pytestFramework geschrieben). Lassen Sie uns nun den pytestTestläufer ausführen .

py.test

Sie erhalten einen ähnlichen Bericht wie mit unittest.

============================= Die Testsitzung beginnt ================== ============
Plattform Linux - Python 3.6.7, pytest-4.4.1, py-1.8.0, pluggy-0.9.0
rootdir: / home / manthan / articles / Software_testing_in_Python
sammelte 6 Gegenstände                                                              
tests / test_file1.py . F                                                    [33%]
tests / test_file2.py . F . F                                                  [100%]
================================== FEHLER ============== =====================

Die Prozentsätze auf der rechten Seite des Berichts geben den Prozentsatz der Tests an, die zu diesem Zeitpunkt abgeschlossen wurden, dh 2 der 6 Testfälle wurden am Ende von „test_file1.py“ abgeschlossen.

Hier sind einige weitere grundlegende Anpassungen, die mitgeliefert werden pytest.

  1. Ausführen bestimmter Testdateien: Um nur eine bestimmte Testdatei auszuführen, verwenden Sie den Befehl:
    py.test <Dateiname>
  2. Teilstring-Matching: Angenommen, wir möchten nur die area()Methode unserer SquareKlasse testen. Wir können dies mithilfe des Teilstring-Matchings wie folgt tun:
    py.test -k "Bereich"

    Mit diesem Befehl pytestwerden nur die Tests ausgeführt, deren Namen die Zeichenfolge "area" enthalten, dh "test_file1_area()", "test_area()" usw.

  3. Markierung: Als Ersatz für die Teilzeichenfolgenübereinstimmung ist die Markierung eine weitere Methode, mit der wir eine bestimmte Reihe von Tests ausführen können. Bei dieser Methode markieren wir die Tests, die wir ausführen möchten. Beachten Sie das unten angegebene Codebeispiel.
    filter_none

    bearbeiten
    schließen

    play_arrow

    Link
    Helligkeit_4
    Code

    @pytest.mark.area     
     
    def test_file1_area():
        sq = app.Square(2)
        assert sq.area() == 4
            f"area for side {sq.side} units is {sq.area()}"
    chevron_right
    
    
    filter_none
    
    

    Im obigen Code test_file1_area()ist das Beispiel mit dem Tag "Bereich" gekennzeichnet. Alle Testmethoden, die mit einem Tag markiert wurden, können mit dem Befehl ausgeführt werden.

    py.test -m <Tagname>
  4. Parallele Verarbeitung: Wenn Sie über eine große Anzahl von Tests verfügen, pytestkönnen Sie diese anpassen, um diese Testmethoden parallel auszuführen. Dazu müssen Sie installieren, pytest-xdistwas mit dem Befehl installiert werden kann.
    pip install pytest-xdist

    Jetzt können Sie den folgenden Befehl verwenden, um Ihre Tests mithilfe von Multiprocessing schneller auszuführen:

    py.test -n 4

    Mit diesem Befehl werden pytest4 Mitarbeiter zugewiesen, um die Tests parallel durchzuführen. Sie können diese Nummer entsprechend Ihren Anforderungen ändern.

    Wenn Ihre Tests threadsicher sind, können Sie auch Multithreading verwenden , um den Testprozess zu beschleunigen. Dazu müssen Sie installieren pytest-parallel(mit pip). Um Ihre Tests im Multithreading auszuführen, verwenden Sie den Befehl:

    pytest - Arbeiter 4