unittest 測試函數、測試類


針對單個函數的測試

1.要測試的函數

name_function.py

1 def get_formatted_name(first, last):
2      """接受名和姓並返回整潔的姓名"""
3      full_name = first + ' ' + last
4      return full_name.title()
5 
6 #函數 get_formatted_name() 將名和姓合並成姓名,在名和姓之間加上一個空格,並將它們的首字母都大寫,再返回結果。

2.編寫測試用例

test_name_function.py

 1 import unittest  #導入 unittest 模塊
 2 from name_function import get_formatted_name  #導入要測試的函數
 3 
 4 class NamesTestCase(unittest.TestCase):  #測試用例:創建一個繼承 unittest.TestCase 的類,包含一系列針對 get_formatted_name 的單元測試
 5     """ 測試 name_function.py"""
 6 
 7     def test_first_last_name(self):   #編寫方法對函數的行為進行測試
 8          """ 檢查函數 get_formatted_name() 在給定名和姓時能否正確地工作 """
 9          formatted_name = get_formatted_name('janis', 'joplin')  #在這個方法中,我們調用了要測試的函數,並存儲了要測試的返回值。
10          self.assertEqual(formatted_name, 'Janis Joplin')  #通過斷言,將 formatted_name 的值同字符串 'Janis Joplin' 進行比較。
11  
12 unittest.main()  #運行這個文件中的測試,運行 testname_function.py 時,所有以 test_ 打頭的方法都將自動運行。

3.運行結果(測試通過)

1 .   # . 表示有一個測試通過了
2 ----------------------------------------------------------------------
3 Ran 1 test in 0.000s    # 表示執行了一個測試,執行時間0.000s
4 OK  #表示該測試用例中的所有單元測試都通過了

1.修改要測試的函數

name_function.py

1 def get_formatted_name(first, middle, last):
2       """ 接受名和姓並返回整潔的姓名 """
3       full_name = first + ' ' + middle + ' ' + last
4       return full_name.title()
5 
6 #函數 get_formatted_name() 將姓、中間名、名合並成姓名。

2.運行測試用例(測試未通過)

 1 E  #測試用例中有一個單元測試導致了錯誤
 2 ======================================================================
 3 ERROR: test_first_last_name (__main__.NamesTestCase)  # NamesTestCase 中的 test_first_last_name() 導致了錯誤
 4 ----------------------------------------------------------------------
 5 Traceback (most recent call last):
 6   File "test_name_function.py", line 8, in test_first_last_name
 7      formatted_name = get_formatted_name('janis', 'joplin')
 8 TypeError: get_formatted_name() missing 1 required positional argument: 'last'
 9 # traceback指出:函數調用 get_formatted_name('janis', 'joplin') 有問題,因為它缺少一個必不可少的位置實參。
10 
11 ----------------------------------------------------------------------
12 Ran 1 test in 0.000s
13
14
FAILED (errors=1) #整個測試用例都未通過,因為運行該測試用例時發生了一個錯誤

1.修改要測試的函數

name_function.py

1 def get_formatted_name(first, last, middle=''):  #將形參 middle 移到形參列表末尾,默認值為一個空字符串,變成可選項
2       """ 接受名、中間名、姓並返回整潔的姓名 """
3       if middle:  #添加 if 測試,以便根據是否提供了中間名相應地創建姓名
4             full_name = first + ' ' + middle + ' ' + last
5       else:
6             full_name = first + ' ' + last
7       return full_name.title()

2.編寫測試用例,新增單元測試

test_name_function.py

 1 import unittest
 2 from name_function import get_formatted_name
 3 
 4 class NamesTestCase(unittest.TestCase):
 5       """ 測試 name_function.py """
 6 
 7       def test_first_last_name(self):
 8             """ 能夠正確地處理像 Janis Joplin 這樣的姓名嗎? """
 9             formatted_name = get_formatted_name('janis', 'joplin')
10             self.assertEqual(formatted_name, 'Janis Joplin')
11 
12       def test_first_last_middle_name(self):  #方法名必須是描述性的,這樣測試未通過時,才知道是哪種行為未通過
13            """ 能夠正確地處理像 Wolfgang Amadeus Mozart 這樣的姓名嗎? """
14            formatted_name = get_formatted_name(
15 'wolfgang', 'mozart', 'amadeus')
16            self.assertEqual(formatted_name, 'Wolfgang Amadeus Mozart')
17 
18 unittest.main()

3.運行結果(測試通過)

1 ..
2 ----------------------------------------------------------------------
3 Ran 2 tests in 0.000s
4 
5 OK

針對類的測試

1.要測試的類

survey.py

 1 class AnonymousSurvey():
 2       """ 收集匿名調查問卷的答案 """
 3 
 4       def __init__(self, question):
 5           self.question = question  #存儲一個問題
 6           self.responses = []  #創建一個空列表,用於存儲答案
 7 
 8       def show_question(self):
 9           """ 打印調查問題 """
10           print(question)
11 
12       def store_response(self, new_response):
13           """ 在答案列表中添加新答案 """
14           self.responses.append(new_response)
15 
16       def show_results(self):
17           """ 將存儲在列表中的答案都打印出來 """
18           print("Survey results:")
19           for response in responses:
20                print('- ' + response)

2.編寫測試用例

test_survey.py

 1 import unittest  #導入unittest
 2 from survey import AnonymousSurvey  #導入要測試的類
 3 
 4 class TestAnonmyousSurvey(unittest.TestCase):
 5       """ 針對 AnonymousSurvey 類的測試 """
 6 
 7       def test_store_single_response(self):
 8            """ 測試單個答案會被妥善地存儲 """
 9            question = "What language did you first learn to speak?"
10            my_survey = AnonymousSurvey(question)  #創建實例
11            my_survey.store_response('English')  #調用方法 store_response() 存儲單個答案 English 12 
13            self.assertIn('English', my_survey.responses)
14 
15       def test_store_three_responses(self):
16            """ 測試三個答案會被妥善地存儲 """
17            question = "What language did you first learn to speak?"
18            my_survey = AnonymousSurvey(question)
19            responses = ['English', 'Spanish', 'Mandarin']
20            for response in responses:
21                 my_survey.store_response(response)
22 
23            for response in responses:
24                 self.assertIn(response, my_survey.responses)
25 
26 unittest.main()

3.運行結果(測試通過)

1 ..
2 ----------------------------------------------------------------------
3 Ran 2 tests in 0.000s
4 
5 OK

1.方法 setUp() 

如果在 TestCase 類中包含了方法 setUp() , Python 將先運行它,再運行各個以 test_ 打頭的方法。

所以如果每個方法中都要創建同一個實例,那么直接在方法 setUp() 中創建這些對象,就可以在每個測試方法中使用它們。

 1 import unittest
 2 from survey import AnonymousSurvey
 3 
 4 class TestAnonymousSurvey(unittest.TestCase):
 5        """ 針對 AnonymousSurvey 類的測試 """
 6 
 7        def setUp(self):
 8             """ 創建一個調查對象和一組答案,供使用的測試方法使用 """
 9             question = "What language did you first learn to speak?"
10             self.my_survey = AnonymousSurvey(question)  #創建一個調查對象
11             self.responses = ['English', 'Spanish', 'Mandarin']  #創建一個答案列表
12 
13        def test_store_single_response(self):
14             """ 測試單個答案會被妥善地存儲 """
15             self.my_survey.store_response(self.responses[0])
16             self.assertIn(self.responses[0], self.my_survey.responses)
17             #存儲這兩樣東西的變量名包含前綴 self (即存儲在屬性中),因此可在這個類的任何地方使用。
18 
19        def test_store_three_responses(self):
20             """ 測試三個答案會被妥善地存儲 """
21             for response in self.responses:
22                  self.my_survey.store_response(response)
23             for response in self.responses:
24                  self.assertIn(response, self.my_survey.responses)
25 
26 unittest.main()
27 
28 #編寫測試類時,可在 setUp() 方法中創建一系列實例並設置它們的屬性,再在測試方法中直接使用這些實例。

2.運行結果分析

1 #運行測試用例時,每完成一個單元測試, Python 都打印一個字符:
2 
3 '''   .      測試通過
4      E      測試引發錯誤
5      F      測試導致斷言失敗    '''

實例

 

  1 #!/usr/bin/env python
  2 # -*- coding: utf-8 -*-
  3 """
  4 @desc:       測試126郵箱的登陸功能
  5 1.使用公共方法public.login
  6 2.將測試數據放在xml文件中,使用數據驅動(/test_data/login.xml)
  7 3.這里使用xml.dom.minidom讀取xml數據
  8 """
  9 import unittest
 10 import xml.dom.minidom
 11 import os
 12 import sys
 13 from selenium import webdriver
 14 
 15 cur_dir = os.getcwd()
 16 sys.path.append(cur_dir.split(r'\test_case')[0])
 17 
 18 from public import login
 19 
 20 fpath = cur_dir.split('test_case')[0] + 'test_data' + os.path.sep + 'login.xml'
 21 
 22 # 打開 xml 文檔
 23 dom = xml.dom.minidom.parse(fpath)
 24 
 25 # 得到文檔元素對象
 26 root = dom.documentElement
 27 
 28 
 29 class TestLogin(unittest.TestCase):
 30     def setUp(self):
 31         self.driver = webdriver.Firefox()
 32         self.driver.implicitly_wait(30)
 33         logins = root.getElementsByTagName('url')
 34         self.base_url = logins[0].firstChild.data
 35         self.verificationErrors = []
 36 
 37     # 用例1:用戶名、密碼為空
 38     def test_null(self):
 39         driver = self.driver
 40         driver.get(self.base_url)
 41         # 讀取xml中的數據
 42         logins = root.getElementsByTagName('null')
 43         # 獲得 null 標簽的 username、password 屬性值
 44         username = logins[0].getAttribute("username")
 45         password = logins[0].getAttribute("password")
 46         prompt_info = logins[0].firstChild.data
 47         # 登錄
 48         login.login(self, username, password)
 49         # 獲取斷言信息進行斷言
 50         text = driver.find_element_by_xpath("//div[@class='error-tt']/p").text
 51         self.assertEqual(text, prompt_info)
 52 
 53     # 用例2:用戶名為空
 54     def test_user_null(self):
 55         driver = self.driver
 56         driver.get(self.base_url)
 57         logins = root.getElementsByTagName('user_null')
 58         # 獲得 user_null 標簽的 username、passwrod 屬性值
 59         username = logins[0].getAttribute("username")
 60         password = logins[0].getAttribute("password")
 61         prompt_info = logins[0].firstChild.data
 62         # 登錄
 63         login.login(self, username, password)
 64         # 獲取斷言信息進行斷言
 65         text = driver.find_element_by_xpath("//div[@class='error-tt']/p").text
 66         self.assertEqual(text, prompt_info)
 67 
 68     # 用例3:密碼為空
 69     def test_pwd_null(self):
 70         driver = self.driver
 71         driver.get(self.base_url)
 72         logins = root.getElementsByTagName('pwd_null')
 73         # 獲得 pwd_null 標簽的 username、passwrod 屬性值
 74         username = logins[0].getAttribute("username")
 75         password = logins[0].getAttribute("password")
 76         prompt_info = logins[0].firstChild.data
 77         # 登錄
 78         login.login(self, username, password)
 79         # 獲取斷言信息進行斷言
 80         text = driver.find_element_by_xpath("//div[@class='error-tt']/p").text
 81         self.assertEqual(text, prompt_info)
 82 
 83     # 用例4:錯誤的用戶名和密碼
 84     def test_error(self):
 85         driver = self.driver
 86         driver.get(self.base_url)
 87         logins = root.getElementsByTagName('error')
 88         # 獲得 error 標簽的 username、passwrod 屬性值
 89         username = logins[0].getAttribute("username")
 90         password = logins[0].getAttribute("password")
 91         prompt_info = logins[0].firstChild.data
 92         # 登錄
 93         login.login(self, username, password)
 94         # 獲取斷言信息進行斷言
 95         text = driver.find_element_by_xpath("//div[@class='error-tt']/p").text
 96         self.assertEqual(text, prompt_info)
 97 
 98     def tearDown(self):
 99         self.driver.quit()
100         self.assertEqual([], self.verificationErrors)
101 
102 
103 if __name__ == "__main__":
104     unittest.main()

 

文章參考自:Python編程:從入門到實踐.pdf

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM