摘要:也就是說,你可以將上述代碼中的看做單元測試,而將看做測試用例。在測試類中的每一個測試方法都必須以開頭,否則將不會被認定是一個單元測試。
《Python編程:從入門到實踐》筆記。1. 前言
本章主要學習如何使用Python標準庫中的unittest模塊對代碼進行簡單的測試。
作為初學者,并非必須為你嘗試的所有項目編寫測試;但參與工作量較大的項目時,你應對自己編寫的函數(shù)和類的重要行為進行測試。這樣你就能夠更加確定自己所做的工作不會破壞項目的其他部分,你就能夠隨心所欲地改進即有代碼。如果不小心破壞了原來的功能,你馬上就會知道,從而能夠輕松地修復問題。相比于等到Bug出現(xiàn)后再去改,在測試未通過時采取措施要容易得多。而且,如果你想要分享你的項目,有測試的代碼更容易讓人接受。
2. 測試函數(shù) 2.1 一個能通過的測試以下是一個將用戶輸入的姓與名拼接的函數(shù):
# name_function.py def get_formatted_name(first, last): """返回一個整潔的完整姓名""" full_name = first + " " + last return full_name.title() if __name__ == "__main__": print("Enter "q" at any time to quit.") while True: first = input(" Please give me a first name: ") if first == "q": break last = input("Please give me a last name: ") if last == "q": break formatted_name = get_formatted_name(first, last) print(" Neatly formatted name: " + formatted_name + ".")
當然你也可以將if語句下面的代碼多帶帶放在一個文件中,并在該文件開頭帶入get_formatted_name()函數(shù)。
對if __name__ == "__main__"的補充:
在Python中,模塊就是對象,所有模塊都有一個內(nèi)置屬性__name__,當該模塊被導入時,該模塊的__name__屬性會被置為模塊名,當直接運行該模塊,或者說直接運行該文件時,該屬性就會使用默認值"__main__",可以用一句經(jīng)典的話總結(jié)這個用法:
Make a script both importable and executable.
if語句下面的代碼相當于對上面的函數(shù)的測試,不過這樣的測試每次都需要我們自己輸入數(shù)據(jù),并自己根據(jù)結(jié)果判斷代碼是否工作正常,如果代碼稍微多一點,稍微復雜一點,這樣的測試方法將會很繁瑣,所以,我們使用unittest模塊了測試代碼。
# 代碼test_name_function.py: 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() # 結(jié)果: . # 這里有個實心句點 ---------------------------------------------------------------------- Ran 1 test in 0.001s OK
這里先明確兩個概念:
單元測試:用于核實函數(shù)在某個方面沒有問題
測試用例:一組單元測試,這些單元測試一起核實函數(shù)在各種情況下的行為都符合要求。
也就是說,你可以將上述代碼中的test_first_last_name看做單元測試,而將NamesTestCase看做測試用例。
一般測試文件多帶帶放在一個文件夾中,也可以將測試都放在一個文件中。
為函數(shù)編寫測試用例,可先導入unittest模塊和要測試的函數(shù),再創(chuàng)建一個繼承unittest.TestCase的類,并編寫一系列方法對函數(shù)行為的不同方面進行測試。在測試用,我們使用斷言self.assertEqual()(并不是只有這一個斷言函數(shù))來判斷結(jié)果與期望是否相同。在測試類中的每一個測試方法都必須以test_開頭,否則將不會被認定是一個單元測試。最后我們通過unittest.main()來運行這個文件中的所有測試。當測試通過時,結(jié)果中會先輸出一個實心句點,輸出幾個句點表示通過了幾個單元測試,然后輸出單元測試數(shù)目,最后輸出OK。
2.2 一個不能通過的測試外國人的名字還有中間名,以上代碼并未考慮這個情況。我們通過將上述代碼改成含有中間名的版本來演示測試不通過的情況:
# 代碼: def get_formatted_name(first, middle, last): """返回一個整潔的完整姓名""" full_name = first + " " + middle + " " + last return full_name.title() # 其余代碼均不變 # 運行上面測試代碼后的結(jié)果: E ====================================================================== ERROR: test_first_last_name (__main__.NamesTestCase) 能夠正確地處理像Janis Joplin這樣的名字嗎? ---------------------------------------------------------------------- Traceback (most recent call last): File "test_name_function.py", line 10, in test_first_last_name formatted_name = get_formatted_name("janis", "joplin") TypeError: get_formatted_name() missing 1 required positional argument: "last" ---------------------------------------------------------------------- Ran 1 test in 0.001s FAILED (errors=1)
第一行輸出了一個字母E,traceback指出缺少了參數(shù)。如果你檢查的條件沒錯,測試通過了意味著函數(shù)的行為是對的,而測試未通過意味著你編寫的新代碼有錯。因此,測試未通過時,不是去修改測試代碼,而失去修改你編寫的代碼。
2.3 添加新測試以下我們將上述的get_formatted_name()函數(shù)修改為能自動處理中間名的函數(shù),并在測試文件中添加一個單元測試:
# name_function.py def get_formatted_name(first, last, middle=""): """返回一個整潔的完整姓名""" if middle: full_name = first + " " + middle + " " + last else: full_name = first + " " + last return full_name.title() # test_name_function.py import unittest from chapter11 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() # 結(jié)果: .. ---------------------------------------------------------------------- Ran 2 tests in 0.000s OK3. 測試類
前面講的都是對函數(shù)的測試,這里我們開始對類的測試。在測試之前,先介紹幾種常用的斷言方法:
方法 | 用途 |
---|---|
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中 |
下面創(chuàng)建一個匿名調(diào)查類:
# survey.py class AnonymousSurvey: """收集匿名調(diào)查問卷的答案""" def __init__(self, question): """存儲一個問題,并為存儲答案做準備""" self.question = question self.responses = [] def show_question(self): """顯示調(diào)查問卷""" print(self.question) def store_response(self, new_response): """存儲單份調(diào)查問卷""" self.responses.append(new_response) def show_results(self): """顯示收集到的所有答卷""" print("Survey results:") for response in self.responses: print("- " + response)
以下是對該類的測試代碼:
# test_survey.py import unittest from chapter11 import AnonymousSurvey class TestAnonymousSurvey(unittest.TestCase): """針對AnonymousSurvey類的測試""" def setUp(self): """創(chuàng)建一個調(diào)查對象和一組答案,共測試方法使用""" question = "What language did you first learn to speak?" self.my_survey = AnonymousSurvey(question) self.responses = ["English", "Spanish", "Mandarin"] def test_store_single_response(self): """測試單個答案唄妥善地存儲""" self.my_survey.store_response(self.responses[0]) self.assertIn(self.responses[0], self.my_survey.responses) def test_store_three_responses(self): """測試三個答案會被妥善地存儲""" for response in self.responses: self.my_survey.store_response(response) for response in self.responses: self.assertIn(response, self.my_survey.responses) unittest.main() # 結(jié)果: .. ---------------------------------------------------------------------- Ran 2 tests in 0.000s OK
這里的setUp()方法相當于普通函數(shù)的__init__()方法,用于初始化這個測試類,減少重復代碼,比如,如果不用setUp()方法,那么question變量在每個測試函數(shù)中都要聲明一次,十分麻煩低效。你過測試類中包含了setUp()方法,Python將先運行它,再運行各個以test_開頭的方法。
至此,Python的基礎部分大致結(jié)束,后面將是項目部分,以后可能還會對基礎部分進行補充。
迎大家關注我的微信公眾號"代碼港" & 個人網(wǎng)站 www.vpointer.net ~
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/8811.html
摘要:也就是說,你可以將上述代碼中的看做單元測試,而將看做測試用例。在測試類中的每一個測試方法都必須以開頭,否則將不會被認定是一個單元測試。 《Python編程:從入門到實踐》筆記。本章主要學習如何使用Python標準庫中的unittest模塊對代碼進行簡單的測試。 1. 前言 作為初學者,并非必須為你嘗試的所有項目編寫測試;但參與工作量較大的項目時,你應對自己編寫的函數(shù)和類的重要行為進行測...
摘要:本章主要講述條件語句等結(jié)構(gòu)。是一條包羅萬象的語句,只要不滿足前面的條件,其中的代碼就會執(zhí)行,這可能會引入無效甚至惡意的數(shù)據(jù)。使用語句處理列表語句常和循環(huán)結(jié)構(gòu)配合使用。 《Python編程:從入門到實踐》筆記。本章主要講述條件語句if, if-else, if-elif, if-elif-else等結(jié)構(gòu)。 1. 條件測試 包括了相等,不等,大于,小于,大于等于,小于等于,存在于,與或非等...
摘要:例如,以下對兩個的相應元素求和這個例子很好的解釋了如何構(gòu)建中所謂的迭代器代數(shù)的函數(shù)的含義。為簡單起見,假設輸入的長度可被整除。接受兩個參數(shù)一個可迭代的正整數(shù)最終會在中個元素的所有組合的元組上產(chǎn)生一個迭代器。 前言 大家好,今天想和大家分享一下我的itertools學習體驗及心得,itertools是一個Python的自帶庫,內(nèi)含多種非常實用的方法,我簡單學習了一下,發(fā)現(xiàn)可以大大提升工作...
摘要:每個模塊都有對應的分支內(nèi)容,并且分支內(nèi)容都分為參考資料練習題交流討論三個內(nèi)容,我最喜歡的是練習題,之前都是非正規(guī)軍的學習,沒有系統(tǒng)訓練過,現(xiàn)在有技能樹測評終于可以把之前散亂的知識點總結(jié)在一起了。祝大家都能在技能樹測評判斷自己在哪個級別的。 通過《Python技能樹測評》判斷自己在哪個級別: ...
摘要:本章主要是學習的文件操作,主要是從文件中讀取數(shù)據(jù)以及將數(shù)據(jù)存儲到文件中,還有錯誤處理,異常類,模塊等。函數(shù)返回一個文件對象,用于接收該對象。異常中使用被稱為異常的特殊對象來管理程序執(zhí)行期間發(fā)生的錯誤。 《Python編程:從入門到實踐》筆記。本章主要是學習Python的文件操作,主要是從文件中讀取數(shù)據(jù)以及將數(shù)據(jù)存儲到文件中,還有錯誤處理,異常類,json模塊等。 1. 從文件中讀數(shù)據(jù) ...
閱讀 2122·2023-04-25 14:56
閱讀 2439·2021-11-16 11:44
閱讀 2696·2021-09-22 15:00
閱讀 1902·2019-08-29 16:55
閱讀 2177·2019-08-29 14:04
閱讀 2305·2019-08-29 11:23
閱讀 3677·2019-08-26 10:46
閱讀 1907·2019-08-22 18:43