The codes below demonstrate how to add unit test (including function test and method test in an object) and integration test:
cat mymodule.py
def myadd(x, y):
'''unit test for function
>>> myadd(3, 5)
35
'''
return x * 10 + y
class MyClass:
'''class level test
>>> mobj = MyClass(7)
>>> mobj.newMul(8)
60
'''
def __init__(self, p0):
self.a0 = p0
def ynadd(self, p1):
'''unit test for object method
>>> mobj = MyClass(6)
>>> mobj.ynadd(4)
14
'''
return self.a0 + p1 * 2
def newMul(self, p1):
return self.a0 * p1 + 4
integration_test = '''
>>> mo = MyClass(2)
>>> mo.newMul(3) + myadd(5, 7)
67
'''
__test__ = {
"integration_test": integration_test
}
if __name__ == "__main__":
import doctest
doctest.testmod(extraglobs={'mobj': MyClass(7)})
You can run tests in 3 ways.
Option 1: python mymodule.py
or python mymodule.py -v
.
Here when you specify object name with extraglobs
parameter,
mobj = MyClass(6)
can be omitted.
Option 2: python -m doctest mymodule.py
or python -m doctest mymodule.py -v
.
In this way the global part if __name__ == "__main__":
will not be executed,
which can be omitted.
Option 3: put all doctest texts into another text file (named mytests.txt),
run tests with doctest.testfile('mytests.txt')
.
You can generating doctest texts with %doctest_mode
command in IPython.
Use ...
for multiline expression. For example:
def myfunc(x):
""" my demo function
>>> inp = [
... 1,2,3]
>>> myfunc(inp)
3
"""
return len(x)
Python doesn't keep the order of dict keys. To avoid mismatch caused by different key orders in testing, use
>>> myfunc() == {1: 'a', 2: 'b'}
True
instead of
>>> myfunc()
{1: 'a', 2: 'b'}
To avoid the mismatch caused by different whitespace,
use doctest.NORMALIZE_WHITESPACE
:
def foo():
""" whitespace test
>>> foo()
... # doctest: +NORMALIZE_WHITESPACE
'abc'
"""
return "abc"
Ref: