测试代码之测试函数

测试代码可以使程序面对各种情况都能按照预期那样工作。编写单元测试,如果我们对已经通过该单元测试的代码进行了修改,那么再进行一次单元测试,可以快速定位程序问题——如果通过了,说明我们的修改未对原程序造成影响;如果没通过,就说明我们的修改存在问题,要么修改代码,要么修改测试。

测试函数

测试通过

现在有一个格式化姓名的函数:

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!测试通过了!