前言
编写函数或类时,还可为其编写测试。通过测试,可确定代码 面对各种输入都能够按要求的那样工作。测试让你信心满满,深信 即便有更多的人使用你的程序,它也能正确地工作。在程序中添加 新代码时,你也可以对其进行测试,确认它们不会破坏程序既有的 行为。程序员都会犯错,因此每个程序员都必须经常测试其代码, 在用户发现问题前找出它们。
在本章中,你将学习如何使用Python模块unittest中的工具来测 试代码。你将学习编写测试用例,核实一系列输入都将得到预期的 输出。你将看到测试通过了是什么样子,测试未通过又是什么样子, 还将知道测试未通过如何有助于改进代码。你将学习如何测试函数和类,并将知道该为项 目编写多少个测试。
一、测试函数
# _*_ coding:utf-8 _*_
"""name_function.py"""
#测试函数
# def get_formatted_name(first,last):
# full_name = first+" "+last
# return full_name.title()
#不能通过的测试
"""修改get_formatted_name(),使其能够处理中间名, 但这样做时,故意让这个函数无法正确地处理像Janis Joplin这样只有名和姓的姓名。"""
# def get_formatted_name(first,middle,last):
# full_name = first+" "+middle+" "+last
# return full_name.title()
#测试未通过时怎么办
"""
将中间名设置为可选的,然后再次运行这个测试用例
要将中间名设置为可选的,可在函数定义中将形参middle移到形参列表末尾,并将其默认值 指定为一个空字符串
"""
def get_formatted_name(first,middle,last):
if middle:
full_name = first+' '+middle+' '+last
else:
full_name = first+' '+last
return full_name.title()
二、添加新测试
#要为函数编写测试用例,可先导入模块unittest以及要测试的函数,再创建一个
#继承unittest.TestCase的类,并编写一系列方法对函数行为的不同方面进行测试。
# _*_ 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(fromatted_name,'janis joplin')
# """我们使用了unittest类最有用的功能之一:一个断言方法。断言方法用来核实得到 的结果是否与期望的结果一致"""
#
# #添加新测试
# def test_first_last_middle_name(self):
# formatted_name = get_formatted_name(
# 'wolfgang','mozart','amadeus')
# self.assertEqual(formatted_name,'wolfgang Amadeus Mozart')
#
#
# unittest.main()
"""我们使用了unittest类最有用的功能之一:一个断言方法。断言方法用来核实得到 的结果是否与期望的结果一致"""
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()
我们将这个方法命名为test_first_last_middle_name()。方法名必须以test_打头,这样它才 会在我们运行test_name_function.py时自动运行。这个方法名清楚地指出了它测试的是get_ formatted_name()的哪个行为,这样,如果该测试未通过,我们就会马上知道受影响的是哪种类 型的姓名。在TestCase类中使用很长的方法名是可以的;这些方法的名称必须是描述性的,这才 能让你明白测试未通过时的输出;这些方法由Python自动调用,你根本不用编写调用它们的代码。
为测试函数get_formatted_name(),我们使用名、姓和中间名调用它,再使用 assertEqual()检查返回的姓名是否与预期的姓名(名、中间名和姓)一致。我们再次运行 test_name_function.py时,两个测试都通过了:
课后习题:
**11-1 城市和国家:**编写一个函数,它接受两个形参:一个城市名和一个国家名。这 个函数返回一个格式为 City, Country 的字符串,如 Santiago, Chile。将这个函数存储 在一个名为 city _functions.py的模块中。
创建一个名为 test_cities.py的程序,对刚编写的函数进行测试(别忘了,你需要导 入模块 unittest 以及要测试的函数)。编写一个名为 test_city_country()的方法,核实使用类似于’santiago’和’chile’这样的值来调用前述函数时,得到的字符串是正确的。 运行 test_cities.py,确认测试 test_city_country()通过了。
**11-2 人口数量:**修改前面的函数,使其包含第三个必不可少的形参 population,并 返回一个格式为 City, Country – population xxx 的字符串,如 Santiago, Chile – population 5000000。运行 test_cities.py,确认测试 test_city_country()未通过。
修改上述函数,将形参 population 设置为可选的。再次运行 test_cities.py,确认测 试 test_city_country()又通过了。
再编写一个名为 test_city_country_population()的测试,核实可以使用类似于 ‘santiago’、'chile’和’population=5000000’这样的值来调用这个函数。再次运行 test_cities.py,确认测试 test_city_country_population()通过了。
#city_functions.py
def city_functions(City,Country,population):
full_city_name = City+" "+Country+"-population"+" "+population
return full_city_name
#将形参population设置为可选
def city_functions(City,Country,population):
if population:
full_city_name = City+" "+Country+" population="+population
else:
full_city_name = City+" "+Country
return full_city_name
#test_city_country.py
import unittest
from city_functions import city_functions
class CityTestCase(unittest.TestCase):
def test_city_country(self):
formatted_name = city_functions('santiago','chile','5000')
self.assertEqual(formatted_name,'santiago chile-population 5000')
unittest.main()
#再编写一个名为 test_city_country_population()的测试,核实可以使用类似于 'santiago'、'chile'和'population=5000000'这样的值来调用这个函数。
class CityTestCase(unittest.TestCase):
def test_city_country_population(self):
formatted_name = city_functions('santiago','chile','5000000')
self.assertEqual(formatted_name,'santiago chile population=5000000')
unittest.main()