Python-Testing-Wesentliches

PythonPythonBeginner
Jetzt üben

This tutorial is from open-source community. Access the source code

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einführung

Die dynamische Natur von Python macht das Testen für die meisten Anwendungen von entscheidender Wichtigkeit. Es gibt keinen Compiler, der Ihre Fehler findet. Die einzige Möglichkeit, Fehler zu finden, besteht darin, den Code auszuführen und sicherzustellen, dass Sie alle seine Funktionen testen.

Assertionen

Die assert-Anweisung ist eine interne Prüfung für das Programm. Wenn ein Ausdruck nicht wahr ist, wird eine AssertionError-Ausnahme ausgelöst.

Syntax der assert-Anweisung.

assert <expression> [, 'Diagnostische Nachricht']

Beispielsweise.

assert isinstance(10, int), 'Erwartet int'

Sie sollte nicht verwendet werden, um die Benutzereingabe zu überprüfen (z. B. Daten, die auf einem Webformular eingegeben werden). Ihr Zweck liegt eher in internen Prüfungen und Invarianten (Bedingungen, die immer wahr sein sollten).

Vertragsprogrammierung

Auch als Design By Contract bekannt, ist das weit verbreitete Verwenden von Assertionen ein Ansatz zur Softwareentwicklung. Es besagt, dass Softwareentwickler präzise Schnittstellenbeschreibungen für die Komponenten der Software definieren sollten.

Beispielsweise könnten Sie Assertionen für alle Eingaben einer Funktion setzen.

def add(x, y):
    assert isinstance(x, int), 'Expected int'
    assert isinstance(y, int), 'Expected int'
    return x + y

Das Überprüfen der Eingaben wird sofort aufrufende Funktionen erkennen, die nicht passende Argumente verwenden.

>>> add(2, 3)
5
>>> add('2', '3')
Traceback (most recent call last):
...
AssertionError: Expected int
>>>

Inline-Tests

Assertionen können auch für einfache Tests verwendet werden.

def add(x, y):
    return x + y

assert add(2,2) == 4

Auf diese Weise integrieren Sie den Test in das gleiche Modul wie Ihren Code.

Vorteil: Wenn der Code offensichtlich defekt ist, wird das Versuch, das Modul zu importieren, fehlschlagen.

Dies wird nicht für erschöpfende Tests empfohlen. Es ist eher ein grundlegender "Smoke-Test". Funktioniert die Funktion überhaupt mit einem Beispiel? Wenn nicht, dann ist definitiv etwas kaputt.

unittest-Modul

Angenommen, Sie haben einige Code in simple.py.

## simple.py

def add(x, y):
    return x + y

Nun möchten Sie ihn testen. Erstellen Sie eine separate Testdatei wie folgt in /home/labex/project/test_simple.py.

## test_simple.py

import simple
import unittest

Dann definieren Sie eine Testklasse.

## test_simple.py

import simple
import unittest

## Beachten Sie, dass sie von unittest.TestCase erbt
class TestAdd(unittest.TestCase):
  ...

Die Testklasse muss von unittest.TestCase erben.

In der Testklasse definieren Sie die Testmethoden.

## test_simple.py

import simple
import unittest

## Beachten Sie, dass sie von unittest.TestCase erbt
class TestAdd(unittest.TestCase):
    def test_simple(self):
        ## Testen Sie mit einfachen ganzzahligen Argumenten
        r = simple.add(2, 2)
        self.assertEqual(r, 5)
    def test_str(self):
        ## Testen Sie mit Zeichenketten
        r = simple.add('hello', 'world')
        self.assertEqual(r, 'helloworld')

*Wichtig: Jede Methode muss mit test beginnen.

Verwendung von unittest

unittest bietet mehrere integrierte Assertionen. Jede von ihnen stellt etwas anderes fest.

## Stellt sicher, dass expr True ist
self.assertTrue(expr)

## Stellt sicher, dass x == y
self.assertEqual(x,y)

## Stellt sicher, dass x!= y
self.assertNotEqual(x,y)

## Stellt sicher, dass x in der Nähe von y ist
self.assertAlmostEqual(x,y,places)

## Stellt sicher, dass die aufrufbare Funktion (callable) mit den Argumenten (arg1,arg2,...) eine Ausnahme vom Typ exc auslöst
self.assertRaises(exc, callable, arg1, arg2,...)

Dies ist keine erschöpfende Liste. Es gibt weitere Assertionen in diesem Modul.

Ausführen von unittest

Um die Tests auszuführen, verwandeln Sie den Code in ein Skript.

## test_simple.py

...

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

Dann führen Sie Python auf der Testdatei aus.

$ python3 test_simple.py
F.
========================================================
FAIL: test_simple (__main__.TestAdd)
--------------------------------------------------------
Traceback (most recent call last):
  File "testsimple.py", line 8, in test_simple
    self.assertEqual(r, 5)
AssertionError: 4!= 5
--------------------------------------------------------
Ran 2 tests in 0.000s
FAILED (failures=1)

Kommentar

Effektives Unit-Testing ist eine Kunst und kann für große Anwendungen recht kompliziert werden.

Das unittest-Modul hat eine Vielzahl von Optionen, die sich auf Testrunner, Ergebnisammlung und andere Aspekte des Testens beziehen. Lesen Sie die Dokumentation für Details.

Dritte-Party-Testwerkzeuge

Das integrierte unittest-Modul hat den Vorteil, überall verfügbar zu sein - es ist Teil von Python. Allerdings finden viele Programmierer auch, dass es ziemlich umständlich ist. Eine beliebte Alternative ist pytest. Mit pytest vereinfacht sich Ihre Testdatei zu etwas wie Folgendem:

## test_simple.py
import simple

def test_simple():
    assert simple.add(2,2) == 4

def test_str():
    assert simple.add('hello','world') == 'helloworld'

Um einen Test auszuführen, geben Sie einfach einen Befehl wie python -m pytest ein. Es wird dann alle Tests finden und ausführen. Das Modul kann mit pip install pytest installiert werden.

Es gibt mit pytest viel mehr als dieses Beispiel, aber es ist normalerweise ziemlich einfach, loszulegen, sollten Sie sich entscheiden, es auszuprobieren.

In dieser Übung werden Sie die grundlegenden Mechanismen des Einsatzes des unittest-Moduls von Python erkunden.

In früheren Übungen haben Sie eine Datei stock.py geschrieben, die eine Stock-Klasse enthielt. Für diese Übung wird angenommen, dass Sie den in Übung 7.9 geschriebenen Code mit typisierten Eigenschaften verwenden. Wenn aus irgendeinem Grund das nicht funktioniert, können Sie die Lösung aus Lösungen/7_9 in Ihr Arbeitsverzeichnis kopieren.

Übung 8.1: Schreiben von Unit-Tests

In einer separaten Datei test_stock.py schreiben Sie eine Reihe von Unit-Tests für die Stock-Klasse. Um Sie zu starten, hier ist ein kleiner Codeausschnitt, der die Instanzerstellung testet:

## test_stock.py

import unittest
import stock

class TestStock(unittest.TestCase):
    def test_create(self):
        s = stock.Stock('GOOG', 100, 490.1)
        self.assertEqual(s.name, 'GOOG')
        self.assertEqual(s.shares, 100)
        self.assertEqual(s.price, 490.1)

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

Führen Sie Ihre Unit-Tests aus. Sie sollten eine Ausgabe erhalten, die ungefähr so aussieht:

.

Ran 1 tests in 0.000s

OK

Wenn Sie sich vergewissert haben, dass es funktioniert, schreiben Sie zusätzliche Unit-Tests, die Folgendes überprüfen:

  • Stellen Sie sicher, dass die s.cost-Eigenschaft den richtigen Wert (49010.0) zurückgibt.
  • Stellen Sie sicher, dass die s.sell()-Methode richtig funktioniert. Sie sollte den Wert von s.shares entsprechend verringern.
  • Stellen Sie sicher, dass das s.shares-Attribut nicht auf einen nicht ganzzahligen Wert gesetzt werden kann.

Für den letzten Teil müssen Sie überprüfen, dass eine Ausnahme ausgelöst wird. Ein einfacher Weg, das zu tun, ist mit Code wie diesem:

class TestStock(unittest.TestCase):
 ...
    def test_bad_shares(self):
         s = stock.Stock('GOOG', 100, 490.1)
         with self.assertRaises(TypeError):
             s.shares = '100'
✨ Lösung prüfen und üben

Zusammenfassung

Herzlichen Glückwunsch! Sie haben das Testing-Labor abgeschlossen. Sie können in LabEx weitere Labs ausprobieren, um Ihre Fähigkeiten zu verbessern.