函数get_formatted_name() 将名和姓合并成姓名,在名和姓之间加上一个空格,并将它们的首字母都大写,再返回结果。为核实get_formatted_name() 像期望的那样工作,我们来编写一个使用这个函数的程序。程序names.py让用户输入名和姓,并显示整洁的全名:
# -*- coding: utf-8 -*-
def get_formatted_name(first,last):
"""Generate a neatly formatted full name."""
full_name = first + " " + last
return full_name.title()
再编写一段测试代码,从name_function.py中导入函数get_formatted_name() 。用户可输入一系列的名和姓,并看到格式整洁的全名:
# -*- coding: utf-8 -*-
from name_function import get_formatted_name
print("Enter 'q' at any time to quit.")
while True:
first = raw_input("\nPlease give me a first name: ")
if first == "q":
break
last = raw_input("Please give me a last name: ")
if last == "q":
break
formatted_name = get_formatted_name(first,last)
print("\nNeatly formatted name: " + formatted_name + ".")
测试结果如下:
Enter 'q' at any time to quit.
Please give me a first name: janis
Please give me a last name: joplin
Neatly formatted name: Janis Joplin.
Please give me a first name: leilei
Please give me a last name: 23
Neatly formatted name: Leilei 23.
Please give me a first name: bob
Please give me a last name: dylan
Neatly formatted name: Bob Dylan.
Please give me a first name: q
Process finished with exit code 0
从测试的结果可以看到,得到的姓名正确无误。
可通过的测试
为函数编写测试用例,可先导入模块
unittest 以及要测试的函
数,再创建一个继承unittest.TestCase 的类,并编写一系列方法对函数行为的不同方面进行测试。
# -*- coding: utf-8 -*-
import unittest
from name_function import get_formatted_name
class NamesTestCase(unittest.TestCase): # 子类NamesTestCase继承unittest.TestCase类
"""测试name_function.py"""
def test_first_last_name(self):
"""能否正确处理像Janis Joplin这样的姓名?"""
formatted_name = get_formatted_name("janis","joplin")
self.assertEqual(formatted_name,"Janis Joplin") # self.assertEqual测试代码并返回结果
unittest.main()
们使用了unittest 类的断言的方法用来核实得到的结果是否与期望的结果是否一致。我们知道在函数get_formatted_name中,输入"janis","joplin",最后得到的结果应为"Janis Joplin",接下来就看测试的结果是否是预测的那样。
代码行self.assertEqual(formatted_name, 'Janis Joplin') 的意思是说:“将formatted_name 的值同字符串'Janis Joplin' 进行比较,并把结果返回。
测试结果如下:
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
Process finished with exit code 0
在测试结果中第1行的句点表明有一个测试通过了。
接下来的一行指出Python运行了一个测试,消耗的时间不到0.001秒。
最后的OK 表明该测试用例中的所有单元测试都通过了。
未通过的测试
我们来修改函数get_formatted_name() ,使其能够处理中间名,故意让这个函数无法正确地处理像Janis Joplin这样只有名和姓的姓名。
# -*- coding: utf-8 -*-
def get_formatted_name(first,middle,last):
"""Generate a neatly formatted full name."""
full_name = first + " " + middle + " " + last
return full_name.title()
再运行程序测试
# -*- coding: utf-8 -*-
import unittest
from name_function import get_formatted_name
class NamesTestCase(unittest.TestCase):
"""测试name_function.py"""
def test_first_last_name(self):
"""能否正确处理像Janis Joplin这样的姓名?"""
formatted_name = get_formatted_name("janis","joplin")
self.assertEqual(formatted_name,"Janis Joplin")
unittest.main()
测试结果如下:
E
======================================================================
ERROR: test_first_last_name (__main__.NamesTestCase)
能否正确处理像Janis Joplin这样的姓名?
----------------------------------------------------------------------
Traceback (most recent call last):
File "D:/Python/python_work/test/test_name_function.py", line 10, in test_first_last_name
formatted_name = get_formatted_name("janis","joplin")
TypeError: get_formatted_name() takes exactly 3 arguments (2 given)
----------------------------------------------------------------------
Ran 1 test in 0.001s
FAILED (errors=1)
Process finished with exit code 1
从测试结果可以看出测试未通过。
其中第1行输出只有一个字母E,它指出测试用例中有一个单元测试导致了错误。
接下来可以看到出错的原因是:NamesTestCase 中的test_first_last_name() 函数导致了错误。
"Ran 1 test in 0.001s"这一句指出Python运行了一个测试,消耗的时间不到0.001秒。
"FAILED (errors=1)"这一句整个测试用例都未通过,因为运行该测试用例时发生了一个错误。
当遇到测试未通过时,先检查测试的条件是否有错,如果没错那就着重检查导致测试不能通过的代码:像上面的例子就要检查刚对函数所做的修改,找出导致函数行为不符合预期的修改。
在上述例子中,get_formatted_name() 函数以前只需要两个实参——名和姓,但现在它要求提供名、中间名和姓。因此,我们把新增的中间名变为可选的,可在函数定义中将形参
middle 移到形参列表末尾,并将其默认值指定为一个空字符串。我们还要添加一个if 测试,如果提供了中间名就创建 名 + 中间名 + 姓,如果不提供中间名就创建 名 + 姓
所以函数get_formatted_name()修改为:
# -*- coding: utf-8 -*-
def get_formatted_name(first,last,middle = ""):
"""生成整洁的姓名"""
if middle:
full_name = first + " " + middle + " " + last
else:
full_name = first + " " + last
return full_name.title()
测试结果为:
# -*- coding: utf-8 -*-
import unittest
from name_function import get_formatted_name
class NamesTestCase(unittest.TestCase):
"""测试name_function.py"""
def test_first_last_name(self):
"""能否正确处理像Janis Joplin这样的姓名?"""
formatted_name = get_formatted_name("janis","joplin")
self.assertEqual(formatted_name,"Janis Joplin")
unittest.main()
.
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
Process finished with exit code 0
如果要增加测试中间名,我们需要在NamesTestCase 类中再添加一个方法:
# -*- coding: utf-8 -*-
import unittest
from name_function import get_formatted_name
class NamesTestCase(unittest.TestCase):
"""测试name_function.py"""
def test_first_last_name(self):
"""能否正确处理像Janis Joplin这样的姓名?"""
formatted_name = get_formatted_name("janis","joplin")
self.assertEqual(formatted_name,"Janis Joplin")
def test_first_last_middle_name(self):
"""是否能够正确地处理像Wolfgang Amadeus Mozart这样的姓名?"""
formatted_name = get_formatted_name("wolfgang","mozart","amadeus")
self.assertEqual(formatted_name,"Wolfgang Amadeus Mozart")
unittest.main()
测试结果:
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
Process finished with exit code 0