Raises an AssertionError exception if the variable test is false.
test = 0
data = "assertion error"
try:
assert test,data
except AssertionError:
print data
finally:
print "the end"
If it is only the assert statement part, you can substitute it by writing as follows.
if __debug__:
if not test
raise AssertionError, data
somedata = 1
#Tuple the exceptions you want to catch.
fatal_exceptions = (KeyboardInterrupt, MemoryError)
try:
assert somedata
except fatal_exceptions, inst: #You can receive the contents of the exception with the argument inst.
print type(inst) #Show exception type
print inst #Show the contents of the exception
raise
#Catch all other exceptions
except Exception, inst:
print type(inst) #Show exception type
print inst #Show the contents of the exception
finally:
print "the end"
UnitTest Slightly modified and added examples from the official tutorial.
import random
import unittest
class TestSequenceFunctions(unittest.TestCase):
#Initialization process called every time
#In addition to this, there is a method called after executing the test etc.
def setUp(self):
self.seq = range(10)
#Describe the method name starting with test.
def test_shuffle(self):
random.shuffle(self.seq)
self.seq.sort()
#Check that the two arguments are equal.
#Checking for inequality is assertNotEqual()You can do it with.
self.assertEqual(self.seq, range(10))
#Check that an exception will occur.
# assertRaises(exception, callable, *args, **kwds)
#Pass args and kwds to the function of the second argument and check that the exception specified by the first argument occurs.
self.assertRaises(TypeError, random.shuffle, (1,2,3))
def test_choice(self):
element = random.choice(self.seq)
#Check that the value of the argument is True.
# bool(element)Equivalent to is True
self.assertTrue(element in self.seq)
def test_sample(self):
#If only the exception argument is passed, the context manager is returned.
#You can write the code to be tested inline.
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()Can be executed with.
unittest.main()
#Get tests to run individually.
_test_choice = TestSequenceFunctions('test_choice')
_test_sample = TestSequenceFunctions('test_sample')
#It can be registered in the test suite and executed collectively by the runner.
TestSuite = unittest.TestSuite()
TestSuite.addTest(_test_choice)
TestSuite.addTest(_test_sample)
runner = unittest.TextTestRunner()
runner.run(TestSuite)
#You can get test functions collectively with the loader.
suite = unittest.TestLoader().loadTestsFromTestCase(TestSequenceFunctions)
unittest.TextTestRunner(verbosity=2).run(suite)
traceback The stack is the memory area where the program is currently running. A stack trace is a record of the execution status (function name, calling function name, line, statement, file name) of the program in the memory area, and this is an object in a script language such as Python. It is provided.
First, stack trace information can be obtained from sys.exc_info ().
exc_type, exc_value, exc_traceback = sys.exc_info()
Using these three variables as arguments, traceback.print_tb () and traceback.print_exception () display the information.
However, if you use traceback.print_exc () below, you can omit the variable acquisition from sys.exc_info (), and you can also display the type and contents, which is convenient. Basically you can use this.
import sys
import traceback
def somework():
try:
print a #Use undefined variables
except Exception:
print "error"
traceback.print_exc(file=sys.stdout)
finally:
print "the end"
if __name__ == '__main__':
somework()
Output result The module name, line, function name, cause statement, and cause error message are output.
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
This is the output when traceback is not written. Nothing is output, just passing the exception.
error
the end
Next, a method of acquiring stack trace information as a list including tuples is shown. Here is also an example of getting a variable from sys.exc_info (). (Because it is used as an argument)
import sys
import traceback
def somework():
try:
print a #Use undefined variables
except Exception:
print "error"
exc_type, exc_value, exc_traceback = sys.exc_info()
print traceback.extract_tb(exc_traceback) #Get only current information
print traceback.extract_stack() #Get a tuple containing the caller's function information
#Call this if you just want to receive it as a list instead of a tuple and make it easier to display.
traceback.format_tb(exc_traceback)
traceback.format_stack()
print "the end"
if __name__ == '__main__':
somework()
nosetest
I referred to "Python Professional Programming".
installation of nose
pip install nose
Class to be tested This class simply adds or subtracts numbers to your bank account.
# 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
#Prepare a wrapper so that you can use getters and setters.
#to balance=Or+These functions will be called automatically by accessing with.
balance = property(get_balance, set_balance)
Write code to test with nose. Preparing a fixed value for testing, such as 100 or 0, is called a data fixture.
# coding: UTF-8
import unittest
class BankAccountTest(unittest.TestCase):
def _getTarget(self):
from bankaccount import BankAccount
return BankAccount
#Create an instance to be tested.
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
Place the above two in the same directory and execute nose in that directory.
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
Easy-to-read coverage is output.
Output in XUNIT format with the "--with-xunit" option.
# 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
Output in XML so that it can be read by jenkins.
coverage xml
mock
Class to be tested 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
Test code
from mock import Mock
from test import Test
def mock_value(value):
return 20 + value
if __name__ == '__main__':
#Replace the function with a mock that returns 100 fixedly.
Test.Widget.Additional = Mock(return_value=100)
w = Test.Widget()
print w.Additional(1)
#If you want to do some calculation instead of a fixed value, side_Pass a dummy function in effect.
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__':
#Replace the class itself.
Test.Widget = Mock()
#The value returned by the function is fixed.
Test.Widget.return_value.Additional.return_value = 10
w = Test.Widget()
print w.Additional(1)
#Swap functions
Test.Widget.return_value.Additional = mock_value
print w.Additional(1)
patch Replaces a mock object running a function with a real object.
# coding: UTF-8
from mock import patch
#Specify the method and return value to replace only while this function is executing
@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
#By the way, m received as an argument is an additional function replaced with a mock.
#So here too the result is 10.
#This time I replaced the method, but in the case of a class, it becomes a class.
print m()
if __name__ == '__main__':
test_func()
# coding: UTF-8
from mock import patch
def test_func():
#Specify the method and return value to replace only during this with scope execution
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) #This succeeds
# coding: UTF-8
from mock import Mock, patch
if __name__ == '__main__':
#A method that returns 3 with the name method,
#A method that raises a KeyError exception with the name other
attrs = {'method.return_value': 3, 'other.side_effect': KeyError}
#You can add attributes at the same time as declaring(some_attribute)。
mock = Mock(some_attribute='eggs', **attrs)
print mock.some_attribute
print mock.method()
print mock.other()
Another thing that seems to be useful
@patch('sys.stdout', new_callable=StringIO)
So, it will be created as a StringIO object at the time of creation.
You can write a pseudo class for testing and assign it with "Test.Widget =" without using mock. If you don't use the mock's validation feature, that may be faster.
Very useful for testing Django.
pip install webtest
pip install django-webtest
The Django application looks like this:
mysite
|-mysite
| |-__init__.py
| |-settings.py
| |-urls.py
| |-wsgi.py
|-test app
| |-__init__.py
| |-form.py
| |-modes.py
| |-views.py
| |-tests.py Write this test in this file|
|-templates
|-manage.py
Write the contents of tests.py as follows
from django_webtest import WebTest
class TestIndex(WebTest):
def test_index(self):
res = self.app.get("/") #Get the response
#Check the status code and content.
assert res.status == '200 OK'
assert 'html' in res
After starting the development server with manage.py runserver, run the test with the following command.
# sudo python manage.py test testapp
Output result
Creating test database for alias 'default'...
.
----------------------------------------------------------------------
Ran 1 test in 0.175s
OK
Destroying test database for alias 'default'...
Recommended Posts