Unit -Checks sind Codesegmente, die zum Testen anderer Codeteile geschrieben wurden, typischerweise eine einzelne Funktion oder Methode, die wir als Einheit bezeichnen. Sie sind ein sehr wichtiger Bestandteil des Softwareentwicklungsprozesses, da sie dazu beitragen, sicherzustellen, dass der Code wie beabsichtigt funktioniert und Fehler frühzeitig fangen. Die Implementierung von Unit -Checks in Python ist auch eine bewährte Verfahren, die Zeit und Geld sparen kann, indem sie Probleme finden und beheben, bevor sie größere Probleme verursachen.

In diesem Artikel werden wir das Schreiben von Unit -Checks in Python vom Verständnis des Verständnisses abdecken assert Anweisung zur Verwendung eines Frameworks, das speziell für diese Artwork von Aufgabe entwickelt wurde – und nach Greatest Practices der Python -Unit -Checks.

Python verfügt über zwei Hauptrahmen, damit die Testen der Unit -Checks erleichtert werden: unittest Und PyTest. Der erste ist seit Python 2.1 Teil der Standardbibliothek von Python und das ist diejenige, auf die wir uns in diesem Artikel konzentrieren.

Um das Tutorial für das Unit -Check zu verfolgen, benötigen Sie kein erweitertes Wissen, aber wir erwarten, dass Sie ein grundlegendes Verständnis dafür haben, wie Python funktioniert und Klassen funktionieren.

Der assert Stellungnahme

Der assert Die Erklärung ist eine integrierte Aussage in Python, die wie der Title angegeben hat, ob eine bestimmte Bedingung wahr ist oder nicht. Wenn die Bedingung wahr ist, passiert nichts, aber wenn es nicht wahr ist, wird ein Fehler aufgeworfen. Obwohl es zunächst so aussehen kann wie das attempt Und besides Klauseln, sie sind völlig anders und assert sollte nicht für die Fehlerbehandlung verwendet werden, sondern aus Gründen des Debuggens und der Prüfung.

Beispielsweise ist die Bedingung in der folgenden Zeile wahr und daher nichts ausgibt oder zurückgibt:

assert 1 > 0

Wenn wir diese Bedingung jedoch ändern, sodass sie falsch wird, bekommen wir eine AssertionError:

assert 1 < 0
---------------------------------------------------------------------------
AssertionError                            Traceback (most up-to-date name final)
<ipython-input-2-2d19dbe67b58> in <module>
----> 1 assert 1 < 0

AssertionError: 

Beachten Sie, dass in der letzten Zeile der Fehlermeldung keine tatsächliche Nachricht danach keine Nachricht AssertionError:. Das liegt daran, dass der Benutzer diese Nachricht übergeben sollte. So wie: wie:

n = 0
assert 1 < n, 'The Situation is False'
---------------------------------------------------------------------------
AssertionError                            Traceback (most up-to-date name final)
<ipython-input-3-e335e3eb84ff> in <module>
      1 n = 0
----> 2 assert 1 < n, 'The Situation is False'

AssertionError: The Situation is False

Die grundlegende Syntax für die Verwendung assert ist die folgende:

assert <situation being examined>, <error message to be displayed>

assert ist sehr einfach zu bedienen. Das Verständnis für Testzwecke ist, wie wir in den folgenden Abschnitten sehen werden.

Der unittest Modul

Der unittest Modul ist ein Framework, das unser Leben beim Testen von Code erleichtert. Das Modul funktioniert auf einigen wichtigen objektorientierten Konzepten, und deshalb müssen Sie die Grundlagen von Klassen und Methoden in Python verstehen.

Ein Testfall wird als einzelne Testeinheit angesehen und durch die dargestellt TestCase Klasse. Unter den zahlreichen Instruments von unittest Dadurch können wir Code testen, diese Klasse ist eine der wichtigsten. Es wird als Basisklasse verwendet, um unsere eigenen Testfälle zu erstellen, mit denen wir mehrere Checks gleichzeitig durchführen können.

Obwohl wir die Bedeutung des Python gesehen haben assert Anweisung Im letzten Abschnitt wird es hier nicht verwendet. Das liegt daran, dass die TestCase Die Klasse liefert auch einige seiner eigenen Assert -Methoden, die genau wie die funktionieren assert Aussage, aber für bestimmte Arten von Behauptungen.

Zum Beispiel die assertEqual Nimmt zwei Elemente und Checks, wenn sie gleich sind, während sie gleich sind assertNotEqual Checks, wenn die Elemente unterschiedlich sind. Auch die assertTrue Methode nimmt ein Component und testet, wenn es wahr ist, während es wahr ist assertFalse Checks, wenn es falsch ist.

Hier ist eine Liste der am häufigsten verwendeten Assert -Methoden in der TestCase Klasse, bereitgestellt vom Beamten unittest Dokumentation:

Verfahren Überprüft das
assertEqual(a, b) a == b
assertNotEqual(a, b) a != b
assertTrue(x) bool(x) is True
assertFalse(x) bool(x) is False
assertIs(a, b) a is b
assertIsNot(a, b) a is not b
assertIsNone(x) x is None
assertIsNotNone(x) x is not None
assertIn(a, b) a in b
assertNotIn(a, b) a not in b
assertIsInstance(a, b) isinstance(a, b)
assertNotIsInstance(a, b) not isinstance(a, b)

Es ist wichtig zu sagen, dass alle Methoden in der TestCase Klasse nehmen auch a msg Argument, das als Fehlermeldung verwendet wird, falls der Check fehlschlägt.

Implementierung von Unit -Checks in Python

Implementieren wir additionally einen einfachen Satz von Unit -Checks. Zunächst müssen wir einen Code zum Testen haben. Dafür betrachten wir Folgendes Calculations Klasse, der sich im Inneren befindet my_calculations.py Datei in der checks Verzeichnis:

# undertaking/code/my_calculations.py

class Calculations:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def get_sum(self):
        return self.a + self.b

    def get_difference(self):
        return self.a - self.b

    def get_product(self):
        return self.a * self.b

    def get_quotient(self):
        return self.a / self.b

Dies ist eine sehr einfache Klasse, die zwei Zahlen benötigt und vier Methoden zum Addieren, Subtrahieren, Multiplizieren und Teilen der ersten Zahl durch die zweite hinzufügen, subtrahieren, multiplizieren und teilen und das Ergebnis zurückgeben.

Jetzt möchten wir die Methoden in dieser Klasse testen. Dafür müssen wir eine Klasse basierend auf dem erstellen TestCase Klasse und diese Klasse enthält Methoden, die die Checks durchführen.

Nehmen wir an, wir haben die folgende Ordnerstruktur:

undertaking/
│
├── code/
│   ├── __initII.py
│   └── my_calculations
│
└── checks.py
# undertaking/check.py

import unittest
from code.my_calculations import Calculations

class TestCalculations(unittest.TestCase):

    def test_sum(self):
        calculation = Calculations(8, 2)
        self.assertEqual(calculation.get_sum(), 10, 'The sum is unsuitable.')

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

Der obige Code testet die get_sum Methode der Calculations Klasse. Um dies zu erreichen, mussten wir Folgendes tun:

  1. Beide importieren unittests und die Calculations Klasse
  2. Ein Objekt instanziieren, wenn die Calculations Klasse
  3. Erstellen die TestCalculations Klasse und die test_sum Methode darin

Beachten Sie, dass wir verwenden assertEqual zu behaupten, ob die Ausgabe von get_sum ist gleich 10. Wir haben auch einen Meldung für den Fehler des Fehlers. Schließlich, wenn wir dieses Skript ausführen, unittest.important() leitet den Check aus. Dies ist die Ausgabe, die wir erhalten:

.
----------------------------------------------------------------------
Ran 1 check in 0.000s
OK

Wenn wir beispielsweise den erwarteten Wert von 10 auf 11 ändern, würde der Check fehlschlagen und wir hätten diese Ausgabe:

----------------------------------------------------------------------
Traceback (most up-to-date name final):
  File ".my_test.py", line 9, in test_sum
    self.assertEqual(calculation.get_sum(), 11, 'The sum is unsuitable.')
AssertionError: 10 != 11 : The sum is unsuitable.
----------------------------------------------------------------------
Ran 1 check in 0.001s

Beachten Sie, dass die The sum is unsuitable. Nachricht ist wie erwartet da.

Nach der gleichen Logik haben wir den Code unten, der alle vier Methoden in der testet Calculations Klasse:

import unittest
from code.my_calculations import Calculations

class TestCalculations(unittest.TestCase):

    def test_sum(self):
        calculation = Calculations(8, 2)
        self.assertEqual(calculation.get_sum(), 10, 'The sum is unsuitable.')

    def test_diff(self):
        calculation = Calculations(8, 2)
        self.assertEqual(calculation.get_difference(), 6, 'The distinction is unsuitable.')

    def test_product(self):
        calculation = Calculations(8, 2)
        self.assertEqual(calculation.get_product(), 16, 'The product is unsuitable.')

    def test_quotient(self):
        calculation = Calculations(8, 2)
        self.assertEqual(calculation.get_quotient(), 4, 'The quotient is unsuitable.')

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

Und alle Checks lagen:

....
----------------------------------------------------------------------
Ran 4 checks in 0.001s
OK

Übrigens ist es kein Unfall, dass alle Namen der Methoden mit dem Wort beginnen check. Dies ist eine Konvention, die wir verwenden, damit unittest kann die Checks identifizieren, die es durchführen soll. Beispielsweise werden im folgenden Code nur drei Checks ausgeführt:

import unittest
from code.my_calculations import Calculations

class TestCalculations(unittest.TestCase):

    def not_a_test_sum(self):
        calculation = Calculations(8, 2)
        self.assertEqual(calculation.get_sum(), 10, 'The sum is unsuitable.')

    def test_diff(self):
        calculation = Calculations(8, 2)
        self.assertEqual(calculation.get_difference(), 6, 'The distinction is unsuitable.')

    def test_product(self):
        calculation = Calculations(8, 2)
        self.assertEqual(calculation.get_product(), 16, 'The product is unsuitable.')

    def test_quotient(self):
        calculation = Calculations(8, 2)
        self.assertEqual(calculation.get_quotient(), 4, 'The quotient is unsuitable.')

if __name__ == '__main__':
    unittest.important()
...
----------------------------------------------------------------------
Ran 3 checks in 0.001s
OK

Die Ausgabe besagt, dass drei Checks ausgeführt wurden. Beachten Sie, dass die erste Methode aufgerufen wird not_a_test_sumUnd deshalb wurde es nicht ausgeführt.

Der setUp Verfahren

Jetzt, da wir die Grundlagen der Unit -Checks mit dem verstehen unittest Modul, optimieren wir unseren Code ein wenig. Sie haben wahrscheinlich bemerkt, dass wir in jedem Check ein Objekt der initialisiert haben Calculations Klasse, die getestet wird. Wir können dies jedoch vermeiden, indem wir a erstellen setUp Verfahren.

Der TestCase Klasse hat bereits eine setUp Methode, die vor jedem Check ausgeführt wird. Was wir additionally tun werden, wenn wir eine neue erstellen, ist die Standardmethode mit unserer eigenen. Dies ist der Code mit dieser neuen Methode implementiert:

import unittest
from code.my_calculations import Calculations

class TestCalculations(unittest.TestCase):

    def setUp(self):
        self.calculation = Calculations(8, 2)

    def test_sum(self):
        self.assertEqual(self.calculation.get_sum(), 10, 'The sum is unsuitable.')

    def test_diff(self):
        self.assertEqual(self.calculation.get_difference(), 6, 'The distinction is unsuitable.')

    def test_product(self):
        self.assertEqual(self.calculation.get_product(), 16, 'The product is unsuitable.')

    def test_quotient(self):
        self.assertEqual(self.calculation.get_quotient(), 4, 'The quotient is unsuitable.')

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

Dies bedeutet, dass die calculations Das Objekt wird initialisiert, bevor jeder Check ausgeführt wird. Eine andere Possibility ist die Verwendung setUpClass stattdessen. Die Idee ist gleich mit dem einzigen Unterschied, dass diese Methode nur einmal und nicht vor jedem Check ausgeführt wird. So wird diese Methode implementiert:

@classmethod
def setUpClass(self):
    self.calculation = Calculations(8, 2)

Ausführen von Checks aus der Befehlszeile

Im vorherigen Abschnitt haben wir festgestellt, dass es möglich ist, die Checks mit dem durchzuführen unittest.important() innen .py Datei. Eine weitere sehr nützliche Möglichkeit, Checks durchzuführen unittest direkt aus der Befehlszeile.

Durch die Verwendung der Befehlszeilenschnittstelle zum Ausführen von Unit-Checks können Sie Ihre Produktivität verbessern, da Sie mehrere Dateien gleichzeitig ausführen können:

>>>pyhon -m unittest

In der obigen Linie wird der Erkennungsmodus in ausgeführt unittest Das wird nach den Checks im aktuellen Verzeichnis suchen.

Damit die Checks ausgeführt werden müssen, müssen wir jedoch einigen Namenskonventionen folgen: Der Title jeder Datei mit Checks muss mit beginnen checkund alle Checks müssen Klassenmethoden sein, basierend auf der TestCase Klasse. Wie bereits erwähnt, müssen die Namen all dieser Methoden mit dem Wort beginnen check. Schließlich muss das Verzeichnis ein importierbares Modul sein, was bedeutet, dass es eine enthalten sollte init.py Datei.

Nehmen wir an, wir haben Folgendes checks Verzeichnis:

checks/
├── init.py
├── check.py
└── test_str.py

Der test_str.py Die Datei enthält die folgenden Checks, die aus einem Beispiel in der untestesten Dokumentation gestellt wurden:

import unittest

class TestStringMethods(unittest.TestCase):

    def test_upper(self):
        self.assertEqual('foo'.higher(), 'FOO')

    def test_isupper(self):
        self.assertTrue('FOO'.isupper())
        self.assertFalse('Foo'.isupper())

    def test_split(self):
        s = 'whats up world'
        self.assertEqual(s.cut up(), ('whats up', 'world'))
        # test that s.cut up fails when the separator is just not a string
        with self.assertRaises(TypeError):
            s.cut up(2)

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

Wenn wir die Checks in beiden Dateien ausführen möchten, können wir die folgende Zeile verwenden:

>>>python -m unittest -v

Der -v Macht die Ausgabe etwas ausführlicher, was bei der Durchführung mehrerer Checks gleichzeitig nützlich sein kann:

test_diff (teste.check.TestCalculations) ... okay
test_product (teste.check.TestCalculations) ... okay
test_quotient (teste.check.TestCalculations) ... okay
test_sum (teste.check.TestCalculations) ... okay
test_isupper (teste.test_str.TestStringMethods) ... okay
test_split (teste.test_str.TestStringMethods) ... okay
test_upper (teste.test_str.TestStringMethods) ... okay
----------------------------------------------------------------------
Ran 7 checks in 0.002s
OK

Wir können auch eine einzelne Datei angeben, die ausgeführt werden soll:

>>>python -m unittest -v checks.check

In der obigen Linie, checks.check stellt sicher, dass nur die Datei checks.py ausgeführt wird. Mit derselben Logik geben wir die Testklasse und sogar eine einzelne Methode an, die wir ausführen möchten:

>>>python -m unittest -v checks.check.TestCalculations.test_diff

Die obige Linie wird nur die ausgeführt test_diff Methode, wie wir in der Ausgabe sehen können:

test_diff (teste.check.TestCalculations) ... okay
----------------------------------------------------------------------
Ran 1 check in 0.000s
OK

Abschluss

In der Lage zu sein, Unit -Checks in Python zu nutzen, ist für jeden Entwickler eine sehr wichtige Fähigkeit. In diesem Tutorial haben wir die Grundlagenkonzepte und die Implementierung einiger Unit -Checks und deren Greatest Practices unter Verwendung eines leistungsstarken Python -Frameworks untersucht.

Was wir in diesem Artikel jedoch gesehen haben, ist jedoch immer noch nur eine Einführung in was unittest kann für Sie tun. Dies ist ein sehr leistungsfähiges Werkzeug, und es gibt jetzt viel mehr zu lernen, da Sie die Grundlagen kennen.

Von admin

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert