table of Contents
setUp() and tearDown() methods
Error handling
The function to open the file open()
returns the file descriptor (that is, an integer) when successful, and returns when an error occurs -1
.
try:
foo()
except ValueError as e:
print('ValueError')
except UnicodeError as e:
print('UnicodeError')
Python's error is actually a class, all error types are inherited from BaseException
, so when you use except
it, you need to pay attention to that it not only catches errors of this type, but also "catch all of its subclasses."
The second one except
will never be captured UnicodeError
, because it UnicodeError
is ValueError
a subclass, if there is, it is also except
captured by the first one .
All errors in Python are BaseException
derived from classes. For common error types and inheritance relationships, see here:
https://docs.python.org/3/library/exceptions.html#exception-hierarchy
Affirmation
Those who use print()
the place to aid viewing, you can use assertions (assert) instead, if the assertion fails, the assert
statement itself will throwAssertionError
logging
No errors will be thrown, and can be output to a file
import logging
s = '0'
n = int(s)
logging.info('n = %d' % n)
print(10 / n)
After running, I found ZeroDivisionError
that there is no information except that, import logging
add a line of configuration afterwards and try again:
import logging
logging.basicConfig(level=logging.INFO)
See the output:
$ python err.py
INFO:root:n = 0
Traceback (most recent call last):
File "err.py", line 8, in <module>
print(10 / n)
ZeroDivisionError: division by zero
This is logging
the advantage, it allows you to specify the level of logging information,
The log levels are as follows:
CRITICAL : 'CRITICAL',
ERROR : 'ERROR',
WARNING : 'WARNING',
INFO : 'INFO',
DEBUG : 'DEBUG',
NOTSET : 'NOTSET',
When we specify level=INFO
, logging.debug
it doesn't work . Similarly, designated level=WARNING
later, debug
and info,notset
it does not work the
unit test
For example, for functions abs()
, we can write the following test cases:
-
Enter a positive number, for example
1
, ,1.2
,0.99
the same input value expected return; -
Negative input, for example
-1
,-1.2
,-0.99
, opposite to the input expected return value; -
Enter
0
, expect to return0
; -
Enter non-numeric types, such as
None
,[]
,{}
and look forward to throwTypeError
.
Putting the above test cases into a test module is a complete unit test.
Let's write a Dict
class. The behavior of this class is dict
consistent, but it can be accessed through attributes. It is used as follows:
>>> d = Dict(a=1, b=2)
>>> d['a']
1
>>> d.a
1
mydict.py
code show as below:
class Dict(dict):
def __init__(self, **kw):
super().__init__(**kw)
def __getattr__(self, key):
try:
return self[key]
except KeyError:
raise AttributeError(r"'Dict' object has no attribute '%s'" % key)
def __setattr__(self, key, value):
self[key] = value
In order to write a unit test, we need to introduce the unittest
module that comes with Python , which is written mydict_test.py
as follows:
import unittest
from mydict import Dict
class TestDict(unittest.TestCase):
def test_init(self):
d = Dict(a=1, b='test')
self.assertEqual(d.a, 1)
self.assertEqual(d.b, 'test')
self.assertTrue(isinstance(d, dict))
def test_key(self):
d = Dict()
d['key'] = 'value'
self.assertEqual(d.key, 'value')
def test_attr(self):
d = Dict()
d.key = 'value'
self.assertTrue('key' in d)
self.assertEqual(d['key'], 'value')
def test_keyerror(self):
d = Dict()
with self.assertRaises(KeyError): #期待抛出指定类型的Error,比如通过d['empty']访问不存在的key时,断言会抛出KeyError
value = d['empty']
def test_attrerror(self):
d = Dict()
with self.assertRaises(AttributeError):
value = d.empty
When writing unit tests, we need to write a test class that unittest.TestCase
inherits from it .
test
The method with the beginning is the test method, test
the method without the beginning is not considered as the test method, and will not be executed during the test.
Unit testing, the simplest way to run is to mydict_test.py
add two lines of code at the end:
if __name__ == '__main__':
unittest.main()
In this way, you can run it mydict_test.py
as a normal python script:
$ python mydict_test.py
Another way is -m unittest
to run unit tests directly on the command line with parameters :
$ python -m unittest mydict_test
.....
----------------------------------------------------------------------
Ran 5 tests in 0.000s
OK
This is the recommended approach, because it allows you to run many unit tests in batches at once, and there are many tools that can automatically run these unit tests.
setUp()
And tearDown()
method
These two methods will be executed before and after each test method is called.
Imagine that your test needs to start a database. At this time, you can setUp()
connect to the database in the tearDown()
method and close the database in the method . In this way, you don't have to repeat the same code in each test method:
class TestDict(unittest.TestCase):
def setUp(self):
print('setUp...')
def tearDown(self):
print('tearDown...')
Run test: Whether the setUp
sum will be printed before and after each test method is called tearDown
.