Löst eine AssertionError-Ausnahme aus, wenn der Variablentest falsch ist.
test = 0
data = "assertion error"
try:
assert test,data
except AssertionError:
print data
finally:
print "the end"
Wenn es sich nur um den Teil der Assert-Anweisung handelt, können Sie ihn wie folgt ersetzen.
if __debug__:
if not test
raise AssertionError, data
somedata = 1
#Korrigieren Sie die Ausnahmen, die Sie abfangen möchten.
fatal_exceptions = (KeyboardInterrupt, MemoryError)
try:
assert somedata
except fatal_exceptions, inst: #Sie können den Inhalt der Ausnahme mit dem Argument inst erhalten.
print type(inst) #Ausnahmetyp anzeigen
print inst #Zeigen Sie den Inhalt der Ausnahme an
raise
#Fangen Sie alle anderen Ausnahmen ab
except Exception, inst:
print type(inst) #Ausnahmetyp anzeigen
print inst #Zeigen Sie den Inhalt der Ausnahme an
finally:
print "the end"
UnitTest Leicht modifizierte und hinzugefügte Beispiele aus dem offiziellen Tutorial.
import random
import unittest
class TestSequenceFunctions(unittest.TestCase):
#Der Initialisierungsprozess wird jedes Mal aufgerufen
#Darüber hinaus gibt es eine Methode, die nach Ausführung des Tests usw. aufgerufen wird.
def setUp(self):
self.seq = range(10)
#Beschreiben Sie den Methodennamen beginnend mit test.
def test_shuffle(self):
random.shuffle(self.seq)
self.seq.sort()
#Überprüfen Sie, ob die beiden Argumente gleich sind.
#Das Überprüfen auf Ungleichheit ist assertNotEqual()Sie können es mit tun.
self.assertEqual(self.seq, range(10))
#Auf Ausnahmen prüfen.
# assertRaises(exception, callable, *args, **kwds)
#Übergeben Sie args und kwds an die Funktion des zweiten Arguments und überprüfen Sie, ob die durch das erste Argument angegebene Ausnahme auftritt.
self.assertRaises(TypeError, random.shuffle, (1,2,3))
def test_choice(self):
element = random.choice(self.seq)
#Überprüfen Sie, ob der Wert des Arguments True ist.
# bool(element)Entspricht ist True
self.assertTrue(element in self.seq)
def test_sample(self):
#Wenn nur das Ausnahmeargument übergeben wird, wird der Kontextmanager zurückgegeben.
#Sie können den zu testenden Code inline schreiben.
with self.assertRaises(ValueError):
random.sample(self.seq, 20)
for element in random.sample(self.seq, 5):
self.assertTrue(element in self.seq)
if __name__ == '__main__':
# main()Kann mit ausgeführt werden.
unittest.main()
#Lassen Sie Tests einzeln ausführen.
_test_choice = TestSequenceFunctions('test_choice')
_test_sample = TestSequenceFunctions('test_sample')
#Es kann in der Testsuite registriert und vom Läufer gemeinsam ausgeführt werden.
TestSuite = unittest.TestSuite()
TestSuite.addTest(_test_choice)
TestSuite.addTest(_test_sample)
runner = unittest.TextTestRunner()
runner.run(TestSuite)
#Mit dem Loader können Sie gemeinsam Testfunktionen abrufen.
suite = unittest.TestLoader().loadTestsFromTestCase(TestSequenceFunctions)
unittest.TextTestRunner(verbosity=2).run(suite)
traceback Der Stapel ist der Speicherbereich, in dem das Programm gerade ausgeführt wird. Ein Stack-Trace zeichnet den Ausführungsstatus (Funktionsname, aufrufender Funktionsname, Zeile, Anweisung, Dateiname) des Programms im Speicherbereich auf. Dies ist ein Objekt in Skriptsprachen wie Python. Es ist vorgesehen.
Erstens können Stapelverfolgungsinformationen von sys.exc_info () abgerufen werden.
exc_type, exc_value, exc_traceback = sys.exc_info()
Mit diesen drei Variablen als Argumente zeigen traceback.print_tb () und traceback.print_exception () Informationen an.
Wenn Sie jedoch traceback.print_exc () unten verwenden, können Sie die Variablenerfassung in sys.exc_info () weglassen und den Typ und den Inhalt anzeigen, was praktisch ist. Grundsätzlich können Sie dies verwenden.
import sys
import traceback
def somework():
try:
print a #Verwenden Sie undefinierte Variablen
except Exception:
print "error"
traceback.print_exc(file=sys.stdout)
finally:
print "the end"
if __name__ == '__main__':
somework()
Ausgabeergebnis Der Modulname, die Zeile, der Funktionsname, die Ursachenanweisung und die Ursachenfehlermeldung werden ausgegeben.
error
Traceback (most recent call last):
File "/Users/test.py", line 8, in somework
print a
NameError: global name 'a' is not defined
the end
Dies ist die Ausgabe, wenn kein Traceback geschrieben wird. Es wird nichts ausgegeben, nur die Ausnahme übergeben.
error
the end
Als nächstes wird ein Verfahren zum Erfassen von Stapelverfolgungsinformationen als Liste einschließlich Taples gezeigt. Hier ist auch ein Beispiel für das Abrufen einer Variablen aus sys.exc_info (). (Weil es als Argument verwendet wird)
import sys
import traceback
def somework():
try:
print a #Verwenden Sie undefinierte Variablen
except Exception:
print "error"
exc_type, exc_value, exc_traceback = sys.exc_info()
print traceback.extract_tb(exc_traceback) #Holen Sie sich nur aktuelle Informationen
print traceback.extract_stack() #Holen Sie sich ein Taple mit den Funktionsinformationen des Anrufers
#Rufen Sie dies auf, wenn Sie es nur in einer Liste anstelle eines Taples erhalten möchten, und vereinfachen Sie die Anzeige.
traceback.format_tb(exc_traceback)
traceback.format_stack()
print "the end"
if __name__ == '__main__':
somework()
nosetest
Ich bezog mich auf "Python Professional Programming".
Installation der Nase
pip install nose
Zu testende Klasse Diese Klasse addiert oder subtrahiert einfach Zahlen zu Ihrem Bankkonto.
# coding: UTF-8
class NotEnoughFundsException(Exception):
pass
class BankAccount(object):
def __init__(self):
self._balance = 0
def deposit(self, amount):
self.balance += amount
def withdraw(self, amount):
self.balance -= amount
def get_balance(self):
return self._balance
def set_balance(self, value):
if value < 0:
raise NotEnoughFundsException
self._balance = value
#Bereiten Sie einen Wrapper vor, damit Sie Getter und Setter verwenden können.
#ausbalancieren=Oder+Diese Funktionen werden beim Zugriff mit automatisch aufgerufen.
balance = property(get_balance, set_balance)
Schreiben Sie Code, um mit der Nase zu testen. Hier wird das Vorbereiten eines festen Werts zum Testen wie 100 oder 0 als Datenvorrichtung bezeichnet.
# coding: UTF-8
import unittest
class BankAccountTest(unittest.TestCase):
def _getTarget(self):
from bankaccount import BankAccount
return BankAccount
#Erstellen Sie eine zu testende Instanz.
def _makeOne(self, *args, **kwargs):
return self._getTarget()(*args, **kwargs)
def test_construct(self):
target = self._makeOne()
self.assertEqual(target._balance, 0)
def test_deposit(self):
target = self._makeOne()
target.deposit(100)
self.assertEqual(target._balance, 100)
def test_withdraw(self):
target = self._makeOne()
target._balance = 100
target.withdraw(20)
self.assertEqual(target._balance, 80)
def test_get_blance(self):
target = self._makeOne()
target._balance = 500
self.assertEqual(target.get_balance(), 500)
def test_set_balance_not_enough_funds(self):
target = self._makeOne()
from bankaccount import NotEnoughFundsException
try:
target.set_balance(-1)
self.fail()
except NotEnoughFundsException:
pass
Legen Sie die beiden oben genannten in dasselbe Verzeichnis und führen Sie die Nase in diesem Verzeichnis aus.
nosetest
.....
----------------------------------------------------------------------
Ran 5 tests in 0.004s
OK
pip install coverage
# nosetests -v --with-coverage
test_construct (test_bankaccount.BankAccountTest) ... ok
test_deposit (test_bankaccount.BankAccountTest) ... ok
test_get_blance (test_bankaccount.BankAccountTest) ... ok
test_set_balance_not_enough_funds (test_bankaccount.BankAccountTest) ... ok
test_withdraw (test_bankaccount.BankAccountTest) ... ok
Name Stmts Miss Cover Missing
-------------------------------------------
bankaccount 16 0 100%
----------------------------------------------------------------------
Ran 5 tests in 0.006s
OK
Es wird eine leicht lesbare Abdeckung ausgegeben.
Ausgabe im XUNIT-Format mit der Option "--with-xunit".
# nosetests -v -w . --with-coverage --with-xunit
test_construct (test_bankaccount.BankAccountTest) ... ok
test_deposit (test_bankaccount.BankAccountTest) ... ok
test_get_blance (test_bankaccount.BankAccountTest) ... ok
test_set_balance_not_enough_funds (test_bankaccount.BankAccountTest) ... ok
test_withdraw (test_bankaccount.BankAccountTest) ... ok
----------------------------------------------------------------------
XML: nosetests.xml
Name Stmts Miss Cover Missing
-------------------------------------------
bankaccount 16 0 100%
----------------------------------------------------------------------
Ran 5 tests in 0.006s
OK
Ausgabe in XML, damit es von Jenkins gelesen werden kann.
coverage xml
mock
Zu testende Klasse testモジュールのTest.py
# coding: UTF-8
class Widget(object):
def __init__(self):
self.value = 10
def Additional(self, add):
self.value += add
return self.value
Testcode
from mock import Mock
from test import Test
def mock_value(value):
return 20 + value
if __name__ == '__main__':
#
Test.Widget.Additional = Mock(return_value=100)
w = Test.Widget()
print w.Additional(1)
#_
Test.Widget.Additional = Mock(side_effect=mock_value)
print w.Additional(1)
100
21
from mock import Mock
from test import Test
def mock_value(value):
return 20 + value
if __name__ == '__main__':
#
Test.Widget = Mock()
#
Test.Widget.return_value.Additional.return_value = 10
w = Test.Widget()
print w.Additional(1)
#Wenn Sie anstelle eines festen Werts eine Berechnung durchführen möchten, übergeben Sie eine Dummy-Funktion mit Nebeneffekt. Klasse durch Schein ersetzen Klasse selbst ersetzen. Der von der Funktion zurückgegebene Wert ist fest. Funktionen tauschen
Test.Widget.return_value.Additional = mock_value
print w.Additional(1)
patch Ersetzen Sie das Scheinobjekt, das die Funktion ausführt, durch das reale Objekt.
# coding: UTF-8
from mock import patch
#Geben Sie die Methode und den Rückgabewert an, die nur ersetzt werden sollen, während diese Funktion ausgeführt wird
@patch("Test.Widget.Additional", return_value=10)
def test_func(m):
import Test
w = Test.Widget()
print w.Additional(1)
assert w.Additional(1) == 10
#Übrigens ist m, das als Argument empfangen wird, eine zusätzliche Funktion, die durch einen Schein ersetzt wird.
#Auch hier ist das Ergebnis 10.
#Dieses Mal habe ich die Methode ersetzt, aber im Fall einer Klasse wird sie zu einer Klasse.
print m()
if __name__ == '__main__':
test_func()
# coding: UTF-8
from mock import patch
def test_func():
#Geben Sie die Methode und den Rückgabewert an, die nur während dieser Ausführung durch den Bereich ersetzt werden sollen
with patch("Test.Widget.Additional", return_value=10) as m:
import Test
w = Test.Widget()
print w.Additional(1)
assert w.Additional(1) == 10
print m()
if __name__ == '__main__':
test_func()
mock = Mock(spec=SomeClass)
isinstance(mock, SomeClass) #Dies ist erfolgreich
# coding: UTF-8
from mock import Mock, patch
if __name__ == '__main__':
#Eine Methode, die 3 mit der Namensmethode zurückgibt.
#Eine Methode, die eine KeyError-Ausnahme mit dem Namen other auslöst
attrs = {'method.return_value': 3, 'other.side_effect': KeyError}
#Sie können Attribute gleichzeitig mit der Deklaration hinzufügen(some_attribute)。
mock = Mock(some_attribute='eggs', **attrs)
print mock.some_attribute
print mock.method()
print mock.other()
Eine andere Sache, die nützlich zu sein scheint
@patch('sys.stdout', new_callable=StringIO)
Es wird also zum Zeitpunkt der Erstellung als StringIO-Objekt erstellt.
Sie können eine Pseudoklasse zum Testen schreiben und sie mit "Test.Widget =" zuweisen, ohne mock zu verwenden. Wenn Sie die Validierungsfunktion von mock nicht verwenden, ist diese Methode möglicherweise schneller.
Sehr nützlich zum Testen von Django.
pip install webtest
pip install django-webtest
Die Django-Anwendung sieht folgendermaßen aus:
mysite
|-mysite
| |-__init__.py
| |-settings.py
| |-urls.py
| |-wsgi.py
|-test app
| |-__init__.py
| |-form.py
| |-modes.py
| |-views.py
| |-tests.py Schreiben Sie diesen Test in diese Datei|
|-templates
|-manage.py
Schreiben Sie den Inhalt von tests.py wie folgt
from django_webtest import WebTest
class TestIndex(WebTest):
def test_index(self):
res = self.app.get("/") #Erhalten Sie die Antwort
#Überprüfen Sie den Statuscode und den Inhalt.
assert res.status == '200 OK'
assert 'html' in res
Starten Sie den Entwicklungsserver mit manage.py runserver und führen Sie den Test mit dem folgenden Befehl aus.
# sudo python manage.py test testapp
Ausgabeergebnis
Creating test database for alias 'default'...
.
----------------------------------------------------------------------
Ran 1 test in 0.175s
OK
Destroying test database for alias 'default'...
Recommended Posts