python《从入门到实践》第11章测试代码 笔记

测试是用来确定代码在面对各种输入时能按照要求进行工作,提前测试有利于防止新代码不会破坏程序既有的行为,本章使用unittest中的工具,编写测试用例,核实输入将得到的输出

formatted 格式化 Generate生成 neatly 整洁的 full完全的

 1 from name_function import get_formatted_name #从name_function.py中导入get_formatted_name() 

11-1城市和国家:编写一个函数,它接受两个形参:一个城市名和一个国家名。这个函数返回一个格式为City, Country的字符串,如Santiago, Chile。将这个函数存储在一个名为city _functions.py的模块中。创建一个名为test_cities.py的程序,对刚编写的函数进行测试(别忘了,你需要导入模块unittest以及要测试的函数)。编写一个名为test_city_country()的方法,核实使用类似于'santiago'和'chile'这样的值来调用前述函数时,得到的字符串是正确的。运行test_cities.py,确认测试test_city_country()通过了。

 1 #city_functions.py
 2 def city_country(city_name, country_name, middle=','):  #
 3     """输出城市名和国家名,例如Santiago, chile"""
 4     full_city_country = city_name + middle + country_name
 5     return full_city_country.title()
 6 
 7 #city_name_country_name.py
 8 from city_functions import city_country
 9 print("Enter 'q' at any time to quit.")
10 while True:
11     city_name = input("亲输入城市名: ")
12     if city_name == 'q':
13         break
14     country_name = input("亲输入国家名: ")
15     if country_name == 'q':
16         break
17 
18     formatted_name = city_country(city_name, country_name)
19     print("\n城市和国家名的输出结果: " + formatted_name)
20 
21 
22 #test_cityname_and_country_name.py
23 import unittest                     #导入inttest模块中的工具
24 from city_functions import city_country    
25 
26 class NamesTestCase(unittest.TestCase):    #这个命名可以随意,但通常都与测试的函数相关而且要包含Test字样
27     """测试city_functions.py"""            #继承TestCase类这样Python才知道如何运行你编写的测试,可以认为是一个接口将你的函数
28                                    #在另一个地方运行
29     def test_city_country_name(self):     #这个测试文件的方法要用test_为开头,_test为开头的方法在文件运行时会自动运行
30         """能够正确地处理像Santigo, Chile这类的名字吗?"""
31         formatted_name = city_country('Santigo', 'Chile') #调用了要测试的函数,并将返回值储存到formatted_name中
32         self.assertEqual(formatted_name, 'Santigo,Chile')#使用断言方法assertEqual用来核实得到的结果是否与期望的结果一致
33                         
34   '''在这里,我们知道get_formatted_name()应返回这样的城市国家名,即
35 首字母为大写,且它们之间有一个‘,’,因此我们期望formatted_name的值为Santigo,Chile。为检查是否确实如此,我们调用unittest的方法assertEqual(),并向它传递formatted_
36 name和'Santigo Chile'。代码行self.assertEqual(formatted_name, 'Janis Joplin')的意思是说:“将formatted_name的值同字符串'Santigo,Chile'进行比较,如果它们相等,就万事大吉,如果它
37 们不相等,跟我说一声!'''
38 unittest.main()

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()通过了。

 1 #写到一般才看到是测试两个。。一个可选,一个不可选
 2 #不可选
 3 def city_country_population(city_name, country_name, population='population-50000'):
 4     """输出城市名和国家名,例如Santiago, chile"""
 5     full_city_country = (city_name + ', ' +
 6                          country_name + str(population))
 7     return full_city_country.title()
 8 #city_country_population_name.py
 9 from city_country_population import city_country_population
10 population = 'population-500000'
11 print("Enter 'q' at any time to quit.")
12 while True:
13     city_name = input("亲输入城市名: ")
14     if city_name == 'q':
15         break
16     country_name = input("亲输入国家名: ")
17     if country_name == 'q':
18         break
19     #population = input("请输入人口数: ")
20     #if population == 'q':
21         #break
22 
23     formatted_name = city_country_population(city_name, country_name, population)
24     print("\n城市和国家名和人口的输出结果: " + formatted_name)
25 #可选
26 #city_country_population.py
27 def city_country_population(city_name, country_name, population):
28     """输出城市名和国家名,例如Santiago, chile"""
29     full_city_country = (city_name + ', ' +
30                          country_name + ' -population ' + population)
31     return full_city_country.title()
32 
33 #city_country_population_name.py
34 from city_country_population import city_country_population
35 print("Enter 'q' at any time to quit.")
36 while True:
37     city_name = input("亲输入城市名: ")
38     if city_name == 'q':
39         break
40     country_name = input("亲输入国家名: ")
41     if country_name == 'q':
42         break
43     population = input("请输入人口数: ")
44     if population == 'q':
45         break
46 
47     formatted_name = city_country_population(city_name, country_name, population)
48     print("\n城市和国家名和人口的输出结果: " + formatted_name)
49 
50 #test_city_and_country_populations.py
51 import unittest
52 from city_country_population import city_country_population
53 
54 class NamesTestCase(unittest.TestCase):
55     """测试city_functions.py"""
56 
57     def test_city_country_population_name(self):
58         """能够正确地处理像Santigo, Chile这类的名字吗?"""
59         formatted_name = city_country_population('Asd', 'Asd', '456')
60         self.assertEqual(formatted_name, 'Asd, Asd -Population 456')
61 
62 unittest.main()
63 #测试不通过的没写,因为太多不通过的方法了,没有明确定义用啥

断言方法

assertEqual(a, b)        核实a == b
assertNotEqual(a, b)     核实a != b
assertTrue(x)            核实x为True
assertFalse(x)           核实x为False
assertIn(item, list)     核实item在list中
assertNotIn(item, list)  核实item不在list中

11-3雇员:编写一个名为Employee的类,其方法__init__()接受名、姓和年薪,并将它们都存储在属性中。编写一个名为give_raise()的方法,它默认将年薪增加5000美元,但也能够接受其他的年薪增加量。为Employee编写一个测试用例,其中包含两个测试方法:test_give_default_raise()和test_give_custom_raise()。使用方法setUp(),以免在每个测试方法中都创建新的雇员实例。运行这个测试用例,确认两个测试都通过了。

 1 #Employee.py
 2 class Employee:
 3       """收集打工人的信息"""
 4       def __init__(self, firstname, lastname, money):
 5           """打工人初始化"""
 6           self.firstname = firstname
 7           self.lastname = lastname
 8           self.money = money
 9      def give_raise(self, addmoney=5000):
10           """应该加的钱(可能吗)"""
11           self.money += addmoney
12 
13 #测试用例
14 import inttest
15 from Employee import Employee     #文件Employee内的Employee类         
16 class EmployeeTestCase(unittest.TestCase):              #如果你在TestCase类中包含了方法setUp(),Python将先运行
17                                                    # 它,再运行各个以test_打头的方法
18       """测试不同打工人的信息"""
19       def setUp(self):
20            """初始化打工人信息"""                        #方法setUp(),让我们只需创建这些对象一
21                                                         # 次,并在每个测试方法中使用它们。
22            self.default = Employee('xiao', 'ma', 1000) #变量名包含前缀self(即存储在属性中)
23           """默认加的薪水"""
24           self.default.give_raise()
25           self.assertEqual(self.default.money,6000)
26       def test_igive_coustom_raise(self):
27           """特殊加薪"""
28           self.default.give_raise(8000)
29           self.assertEqual(self.default.money,9000)
30 unittest.main()

小结:测试代码

参与工作量较大的项目时,你应对自己编写的函数和类的重要行为进行测试,在项目早期,不要试图去编写全覆盖的测试用例,除非有充分的理由这样做。

使用模块unittest中的工具来为函数和类编写测试;如何编写继承unittest.TestCase的类,以及如何编写测试方法,以核实函数和类的行为符合预期;如何使用方法setUp()来根据类高效地创建实例并设置其属性,以便在类的所有测试方法中都可使用它们。

 

上一篇:NIOS II 中直接调用Modelsim仿真


下一篇:1024程序员节特别篇:Linux三十年的发展历程以及未来的走向