测试代码可以使程序面对各种情况都能按照预期那样工作。编写单元测试,如果我们对已经通过该单元测试的代码进行了修改,那么再进行一次单元测试,可以快速定位程序问题——如果通过了,说明我们的修改未对原程序造成影响;如果没通过,就说明我们的修改存在问题,要么修改代码,要么修改测试。
现在有一个格式化姓名的函数:
def print_name(l,f):
a = l.title() + ' ' + f.title()
return a
这段代码保存在
name.py
我们要测试这段代码在处理我们提供的姓名时能否正确工作。这时可以使用Python自带的unittest
模块编写单元测试:
import unittest
from name import print_name
class Test_print_name(unittest.TestCase):
def test_print_name(self):
a = print_name('joecy','wang')
self.assertEqual(a,"Joecy Wang")
unittest.main()
首先,导入模块unittest和要测试的函数print_name()
,然后创建一个继承于unittest.TestCase
的类Test_print_name
,接着创建一个方法test_print_name()
,用来测试print_name()
,在这个方法中,我们调用了函数print_name()
,并在结果(返回值)存储在变量a
中。最后,我们使用断言方法assertEqual()
判断输出是否是我们期望的。
代码行
unittest.main()
让Python运行这个文件中的测试。
运行这个单元测试,得到结果:
.
----------------------------------------------------------------------
Ran 1 test in 0.002s
OK
第一行的句点.
代表有一个测试通过了,下一行显示的是Python运行这个测试的耗时,OK
则表示这个测试用例中的所有单元测试都通过了。
如果这时修改了函数print_name()
,使其多接受一个中间名参数:
def print_name(l,m,f):
a = l.title() + ' ' + m.title() + ' '+ f.title()
return a
再次运行函数print_name()
的单元测试时,输出如下:
E
======================================================================
ERROR: test_print_name (__main__.Test_print_name)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/joecy/Desktop/TestCode/testname.py", line 7, in test_print_name
a = print_name('joecy','wang')
TypeError: print_name() missing 1 required positional argument: 'f'
----------------------------------------------------------------------
Ran 1 test in 0.002s
FAILED (errors=1)
第一行的字母E
,表示有一个测试没通过,第二行告诉我们是哪里发生了错误,第三行是一个标准的traceback
,告诉我们调用函数时缺少了一个必不可少的位置参数。
测试不通过,说明我们新编写的代码存在问题,要检查刚刚进行的修改,并处理。
修改后代码如下:
def print_name(l,f,m=''):
if m:
a = l.title() + ' ' + m.title() + ' '+ f.title()
else:
a = l.title() + ' ' + f.title()
return a
中间名变为可选的,并添加了if
测试。
再次测试:
.
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
通过了!
函数print_name
现在可以处理包含中间名的姓名了,我们也需要再编写一个测试,用于测试包含中间名的姓名:
import unittest
from name import print_name
class Test_print_name(unittest.TestCase):
def test_print_name(self):
a = print_name('joecy','wang')
self.assertEqual(a,"Joecy Wang")
def test_print_m_name(self):
a = print_name('joecy','wang','li')
self.assertEqual(a,"Joecy Li Wang")
unittest.main()
运行测试,结果如下:
..
----------------------------------------------------------------------
Ran 2 tests in 0.003s
OK
OK!测试通过了!