1. 程式人生 > 其它 >python《從入門到實踐》第11章測試程式碼 筆記

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()來根據類高效地建立例項並設定其屬性,以便在類的所有測試方法中都可使用它們。