日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

十五、Python第十五课——测试代码

發(fā)布時間:2025/3/8 python 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 十五、Python第十五课——测试代码 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

(請先看這篇文章:https://blog.csdn.net/GenuineMonster/article/details/104495419)?

? ? ? ? 也許你聽過軟件測試?編寫函數(shù)或類時,可以為其編寫對應(yīng)的測試代碼。通過測試,可檢驗(yàn)代碼是否能夠按照編寫意圖工作。在本博文中,將會學(xué)習(xí)如何使用Python模塊unittest中的工具來測試代碼(測試函數(shù)和類),將會學(xué)習(xí)如何編寫測試用例,編寫多少個測試代碼。

1?測試函數(shù)?

????????要學(xué)習(xí)測試,得有要測試的代碼。依據(jù)原書在此提供一個簡單的函數(shù),它接受名和姓并返回整潔的姓名,代碼如下所示:

def get_formatted_name(first,last): # 函數(shù)將名和姓結(jié)合成姓名"""生成整潔的姓名"""full_name = first + " " + lastreturn full_name.title()

測試代碼如下:(將上述代碼單獨(dú)一個文件,名為name_function.py)

from name_function import get_formatted_name print("Enter 'q' at any time to quit. ") while True:first = input("\nPlease give me a first name: ")if first == 'q':breaklast = input("Please give me a last name: ")if last == 'q':breakformatted_name = get_formatted_name(first,last)print("\tNeatly formatted name:" + formatted_name +". ")

?????????從上述輸出可知,合并得到的姓名正確無誤。如果修改了get_formatted_name(),即使原有功能不變,還得運(yùn)行測試代碼進(jìn)行測試,此時就體現(xiàn)出自動測試函數(shù)的好處。

1.1?單元測試和測試用例?

????????Python標(biāo)準(zhǔn)庫中的模塊unittest提供了代碼測試工具。單元測試用于核實(shí)函數(shù)的某個方面沒有問題;測試用例是一組單元測試,這些單元測試一起核實(shí)函數(shù)在各種情形下的行為都符合要求。良好的測試用例考慮到了函數(shù)可能收到的各種輸入,包含針對所有這些情形的測試。全覆蓋式測試用例包含―整套單元測試,涵蓋了各種可能的函數(shù)使用方式。

1.2?可通過的測試

????????為函數(shù)編寫測試用例,可先導(dǎo)人模塊unittest以及要測試的函數(shù),再創(chuàng)建一個繼承unittest.TestCase的類,并編寫一系列方法對函數(shù)行為的不同方面進(jìn)行測試。接下來給出一個只包含一個方法的測試用例,它將檢查函數(shù)get_formatted_name()在給定名和姓時能否正確地工作:

# 首先,導(dǎo)入模塊unittest和要測試的函數(shù)get_formatted_name() import unittest from name_function import get_formatted_name # 創(chuàng)建名為NamesTestCase的類,并在類的命名時體現(xiàn)出類的命名原則。 # 這個類必須繼承uniunittest.TestCase類,這樣Python才知道自動運(yùn)行你編寫的測試代碼。# 可以看出NamesTestCase類中只包含一個方法,因此我們核實(shí)的是只有名和姓的姓名能否被正確地格式化。 """我們運(yùn)行test_name_function.py時,所有以test打頭的方法都將自動運(yùn)行。在這個方法中,我們調(diào)用了要測試的函數(shù),并存儲了要測試的返回值 """class NamesTestCase(unittest.TestCase):"""測試name_function.py"""def test_first_last_name(self):"""能夠正確處理像Janis Joplin這樣的姓名嗎?"""formatted_name = get_formatted_name('janis','joplin')# 我們使用了unittest類中最有用的功能之一:一個斷言方法。斷言方法是用來核實(shí)得到的結(jié)果是否與期望的結(jié)果一致# 下面這行代碼的意思是說:請將程序處理得出的結(jié)果和我指定的結(jié)果進(jìn)行比對,一樣就萬事大吉;不一樣,就告訴我。self.assertEqual(formatted_name,'Janis Joplin')unittest.main()

第1行的句點(diǎn)表明有一個測試通過了。接下來的一行指出Python運(yùn)行了一個測試,消耗的時間不到0.001s。最后的ok表明該測試用例中的所有單元測試都通過了。

1.3 不能通過的測試

????????代碼錯誤通常是導(dǎo)致測試未通過的根本原因,接下來我們修改get_formatted_name(),使其能夠處理中間名,但是這樣的話,此函數(shù)無法正確處理像Janis Joplin這樣只用名和姓的姓名。下面是函數(shù)get_formatted_name()的新版本,它要求通過一個實(shí)參指定中間名:(下面的代碼是更新過的)

def get_formatted_name(first,middle,last):"""生成整潔的姓名"""full_name = first + " " + middle + lastreturn full_name.title()

? ? ? ? ?上述展示的是測試未通過時的結(jié)果。因?yàn)闇y試未通過,所以需要說明的事情更多。其中:

1、第1行輸出只有一個字母E,它表示測試用例中有一個單元測試導(dǎo)致了錯誤。

2、接下來,我們看到NameTestCase中的test_first_last_name()導(dǎo)致了錯誤。

3、錯誤提示信息中給出標(biāo)準(zhǔn)的Traceback,它指出函數(shù)調(diào)用get_formatted_name(' janis ', ' joplin ')有問題,因?yàn)樗鄙僖粋€必不可少的位置實(shí)參。

4、“Ran 1 test in 0.000s”指的是運(yùn)行了一個單元測試。最后在這句的下面還看到一條消息,指出整個測試用例都未通過,因?yàn)檫\(yùn)行該測試用例時發(fā)生了一個錯誤。

1.4 如何處理未通過的測試

????????測試未通過意味著編寫的代碼有錯誤。因此在測試未通過時,不要修改測試,而是修復(fù)新編寫的代碼:檢查剛對函數(shù)所做的修改,找出導(dǎo)致函數(shù)行為不符合預(yù)期的修改。

? ? ? ? 對1.3中提到的例子而言,最佳的解決方法是將中間名變?yōu)榭蛇x項(xiàng),這樣就能兼容有中間名的姓名了。對此,將代碼進(jìn)行如下修改:

def get_formatted_name(first,last,middle = ''):"""生成整潔的姓名"""if middle:full_name = first + ' ' + middle + ' ' + lastelse:full_name = first + ' ' + lastreturn full_name.title()

????????上述代碼:將中間名設(shè)置為可選的,并在函數(shù)定義時,將形參middle移到形參列表的末尾,并將其默認(rèn)值設(shè)定為一個空字符串。與此同時,使用一個if-else語句進(jìn)行判斷,分別處理有middle和沒middle的情況。接下來我們再次運(yùn)行測試代碼。

?1.5 添加新測試

確定get_formatted_name()又能正確的處理簡答的姓名后,我們再編寫一個測試,用于測試包含中間名的姓名。為此,我們在NamesTestCase類中再添加一個方法,代碼如下所示:

# 首先,導(dǎo)入模塊unittest和要測試的函數(shù)get_formatted_name() import unittest from name_function import get_formatted_name # 創(chuàng)建名為NamesTestCase的類,并在類的命名時體現(xiàn)出類的命名原則。 # 這個類必須繼承uniunittest.TestCase類,這樣Python才知道自動運(yùn)行你編寫的測試代碼。# 可以看出NamesTestCase類中只包含一個方法,因此我們核實(shí)的是只有名和姓的姓名能否被正確地格式化。 """我們運(yùn)行test_name_function.py時,所有以test打頭的方法都將自動運(yùn)行。在這個方法中,我們調(diào)用了要測試的函數(shù),并存儲了要測試的返回值 """class NamesTestCase(unittest.TestCase):"""測試name_function.py"""def test_first_last_name(self):"""能夠正確處理像Janis Joplin這樣的姓名嗎?"""formatted_name = get_formatted_name('janis','joplin')# 我們使用了unittest類中最有用的功能之一:一個斷言方法。斷言方法是用來核實(shí)得到的結(jié)果是否與期望的結(jié)果一致# 下面這行代碼的意思是說:請將程序處理得出的結(jié)果和我指定的結(jié)果進(jìn)行比對,一樣就萬事大吉;不一樣,就告訴我。self.assertEqual(formatted_name,'Janis Joplin')# 以下是新加的內(nèi)容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()

?我們在命名函數(shù)時,都是以test開頭,而且必須這么做。這樣它才可以在我們運(yùn)行test_name_function.py時自動運(yùn)行。在TestCase類中使用很長的方法名是可以的,這些方法名的名稱必須是描述性的,這才能讓你明白測試未通過時的輸出;這些方法由Python自動調(diào)用,你根本不用編寫調(diào)用他們的代碼。雖然加備注也可以起到描述性的作用,但是備注不會再錯誤時顯示到終端里。

2 測試類

????????1中介紹了編寫針對單個函數(shù)的測試,下面來編寫針對類的測試。 如果針對類的測試通過了,你就能確信對類所做的改進(jìn)沒有以外的破壞其原有的行為。

?2.1 各種斷言方法

????????Python在unittest.TestCase類中提供了很多斷言的方法。前面說過,斷言方法檢查你認(rèn)為應(yīng)該滿足的條件是否確實(shí)滿足。如果該條件確實(shí)滿足,你對程序行為的假設(shè)就得到了確認(rèn),你就可以確信其中沒有錯誤。

? ? ? ? 下面提供6種斷言方法,可核實(shí)返回的值等于或不等于預(yù)期的值;返回的值為True或False;返回的值在列表種或不在列表中(只能在繼承unittest.TestCase的類中使用這些方法)

assertEqual(a,b) # 核實(shí)a = b assertNotEqual(a,b) # 核實(shí)a!= b assertTrue(x) # 核實(shí)x為True assertFalse(x) # 核實(shí)x為False assertIn(item,list) # 核實(shí)item在list中 assertNotIn(item,list) # 核實(shí)item不在list

2.2 一個要測試的類

? ? ? ? 類的測試與函數(shù)的測試類似——所做的大部分工作都是測試類中方法的行為,但存在一些不同之處。

survey.py文件中的代碼:

class AnonymousSurvey():"""收集匿名調(diào)查問卷的答案"""def __init__(self,question):"""存儲一個問題,并為存儲答案做準(zhǔn)備"""self.question = questionself.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_result(self):"""顯示收集到的所有答案"""print("Survey results:")for response in self.responses:print('- ' + response)

使用上述類代碼的另一段代碼:文件名為language_survey.py

from survey import AnonymousSurvey# 定義一個問題,并創(chuàng)建一個表示調(diào)查的AnonymousSurvey對象 question = "What language did you first learn to speak?" my_survey = AnonymousSurvey(question)# 顯示問題并存儲答案 my_survey.show_question() print("Enter 'q' at any time to quit.\n") while True:response = input("Language: ")if response == 'q':breakmy_survey.store_response(response)# 顯示調(diào)查結(jié)果 print("\nThank you everyone who participated in the survey!") my_survey.show_results()

這個程序定義了一個問題(“ What language did you first learn to speak? "),并使用這個問題創(chuàng)建了一個AnonymousSurvey對象。下面是程序運(yùn)行結(jié)果:

????????AnonymousSurvey類可用于進(jìn)行簡單的匿名調(diào)查。假設(shè)我們將它放在了模板survey中,并想進(jìn)行改進(jìn):讓每位用戶都可以輸入多個答案;編寫一個方法,它只列出不同的答案,并指出每個答案出現(xiàn)了多少次;再編寫一個類,用于管理非匿名調(diào)查。

? ? ? ? 進(jìn)行上述修改存在風(fēng)險,可能會影響AnonymousSurvey類的當(dāng)前行為。例如,允許每位用戶輸入多個答案時,可能不小心修改了處理單個答案的方式。要確認(rèn)在開發(fā)這個模塊時沒有破壞既有的行為,可以編寫針對這個類的測試。

2.3 測試AnonymousSurvey類

? ? ? ? 在此小節(jié)中,我們編寫一個測試,對AnonymousSurvey類的行為進(jìn)行驗(yàn)證。文件名為test_survey.py。

# 導(dǎo)入模塊unittest以及要測試的類AnonymousSurvey。將測試用例命名為TestAnonymousSurvey,它也 # 繼承了unittest.Testcase import unittest from survey import AnonymousSurvey class TestAnonymousSurvey(unittest.TestCase):"""針對AnonymousSurvey類的測試"""def test_store_single_response(self):"""測試單個答案會被妥善地存儲"""question = "what language did you first learn to speak? "# 使用問題“ what language did you first learn to speak? ”創(chuàng)建了一個名為my_survey的實(shí)例,# 然后使用方法store_response()存儲了單個答案English。接下來,并使用斷言,檢測English是否包含# 在列表my_survey.responses中,以核實(shí)這個答案是否被妥善的存儲了。my_survey =AnonymousSurvey(question)my_survey.store_response('English')self.assertIn('English',my_survey.responses)unittest.main()

?

?但只能收集一個答案的調(diào)查用途不大,我們擴(kuò)大為3個:

import unittest # 導(dǎo)入模塊unittest以及要測試的類AnonymousSurvey。將測試用例命名為TestAnonymousSurvey,它也 # 繼承了unittest.Testcase from survey import AnonymousSurveyclass TestAnonymousSurvey(unittest.TestCase):"""針對AnonymousSurvey類的測試"""def test_store_single_response(self):"""測試單個答案會被妥善地存儲"""question = "what language did you first learn to speak?"# 使用問題“ what language did you first learn to speak? ”創(chuàng)建了一個名為my_survey的實(shí)例,# 然后使用方法store_response()存儲了單個答案English。接下來,并使用斷言,檢測English是否包含# 在列表my_survey.responses中,以核實(shí)這個答案是否被妥善的存儲了。my_survey = AnonymousSurvey(question)my_survey.store_response('English')self.assertIn('English',my_survey.responses)def test_store_three_responses(self):"""測試三個答案會被妥善的存儲"""question = 'What language did you first learn to speak?'my_survey = AnonymousSurvey(question)responses = 'English','Spnish','Mandarin'for response in responses:my_survey.store_response(response)for response in responses:self.assertIn(response,my_survey.responses)unittest.main()

?前述做法的效果很好,但這些測試有冗余。下面使用unittest的另一項(xiàng)功能來提高他們的效率。

2.4 方法setUp()

????????在前面的test_survey.py中,在每個測試方法中都創(chuàng)建了一個AnonymousSurvey實(shí)例,并在每個方法中都創(chuàng)建了答案。unittest.TestCase類中包含方法setUp(),讓我們只需要創(chuàng)建這些對象一次,并在每個測試方法中使用它們。如果你在TestCase類中包含了方法setUp(),Python將先運(yùn)行它,再運(yùn)行各個以test_打頭的方法。這樣,在編寫的每個測試方法中都可以使用在方法setUp()中創(chuàng)建的對象了。

? ? ? ? 下面使用setUp()來創(chuàng)建一個調(diào)查對象和一組答案,供方法test_store_single_response()和test_store_three_response()使用:

import unittest # 導(dǎo)入模塊unittest以及要測試的類AnonymousSurvey。將測試用例命名為TestAnonymousSurvey,它也 # 繼承了unittest.Testcase from survey import AnonymousSurveyclass 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()

? ? ? ? 以上代碼的解釋——setUp()做了兩件事情:創(chuàng)建一個調(diào)查對象;創(chuàng)建一個答案列表。存儲這兩樣?xùn)|西的變量名包含前綴self(即存儲在屬性中),因此可在這個類的任何地方使用。這讓兩個個測試方法都更簡單,因?yàn)樗麄兌疾挥脛?chuàng)建對象和答案。再次運(yùn)行代碼的結(jié)果為:

? ? ? ? ?測試自己編寫的類時,方法setUp()讓測試方法編寫起來更容易:可在setUp()方法中創(chuàng)建一系列實(shí)例并設(shè)置它們的屬性,再在測試方法中直接使用這些實(shí)例。相比于在每個測試方法中都創(chuàng)建實(shí)例并設(shè)置其屬性,這要容易得多。

? ? ? ? 需要注意的是,運(yùn)行測試用例時,每完成一個單元測試,Python都打印一個字符:測試通過時打印一個句點(diǎn);測試引發(fā)錯誤時打印一個E;測試導(dǎo)致斷言失敗時打印一個F。這就是運(yùn)行測試用例時,在輸出的第一行中看到的句點(diǎn)和字符數(shù)量各不相同的原因。如果測試用例包含很多單元測試,需要運(yùn)行很長時間,就可通過觀察這些結(jié)果來獲悉有多少個測試通過了。

????????在項(xiàng)目早期,不要試圖去編寫全覆蓋的測試用例,除非有充分的理由這樣做。

總結(jié)

以上是生活随笔為你收集整理的十五、Python第十五课——测试代码的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 奇米视频在线观看 | 妺妺窝人体色www在线下载 | 一本色道久久综合熟妇 | 中文字幕av高清 | 黄色片网站免费观看 | 豆花在线视频 | 成人高潮视频 | 天堂久久精品 | 日韩不卡中文字幕 | av一级 | 亚洲av综合一区 | 久久99成人| 99久久婷婷国产精品综合 | 日本乱子伦 | 亚洲综合视频在线播放 | 亚欧成人精品一区二区 | 一边摸一边做爽的视频17国产 | 2019亚洲天堂 | 亚洲同性gay激情无套 | 日韩欧美精品在线观看 | 国产极品视频在线观看 | 亚洲欧美精品一区 | 亚洲一区在线视频 | 国产91av视频 | 亚洲黄片一区二区 | 可以在线观看av的网站 | 中文字幕在线观看日韩 | 草av| 日本美女一级片 | 国产视频一区二区三区在线观看 | 秋霞午夜鲁丝一区二区 | 综合性色| 欧美日韩1区2区 | 久久久久久久久久久久久久久久久久久 | 一区二区三区美女 | 日韩成人在线网站 | 免费av在线网址 | 亚洲A∨无码国产精品 | 国产日韩欧美在线 | 婷婷激情视频 | 色小说香蕉 | 91免费看黄 | 精品精品| 男女扒开双腿猛进入爽爽免费 | 男人网站在线观看 | 国产乱码精品一区二三赶尸艳谈 | 麻豆蜜桃在线观看 | 亚洲一区二区在线观看视频 | 你懂的在线观看视频 | 国产视频麻豆 | 欧美zozo | 久久不卡av | 女人脱下裤子让男人捅 | 玖玖在线资源 | 免费爱爱视频 | 国产精品一区二区三区免费 | 高潮毛片又色又爽免费 | 91成人免费在线观看 | 美女激情av | 欧美激情福利 | 五月深爱网 | 国产富婆一级全黄大片 | 97人妻精品一区二区 | 伊人久久综合视频 | 特级黄毛片 | www.久久婷婷 | 在线中文字幕av | 欧美多人猛交狂配 | 国产ts三人妖大战直男 | 日韩在线网址 | 96av视频| 开心激情站 | 亚洲精品国产欧美在线观看 | 欧美黄色免费网站 | 久久99影院 | 欧美日韩一区电影 | 色wwwwww| av免费观看不卡 | 国产日韩欧美精品在线 | 国产精品天天av精麻传媒 | 深夜在线视频 | 久久人人爽人人爽人人片av免费 | 午夜日韩| 亚洲成人久久精品 | 美女被爆操网站 | 色丁香婷婷 | 亚洲免费视频播放 | 精品人妻aV中文字幕乱码色欲 | 欧洲一区二区 | 国产αv| 欧类av怡春院 | 亚洲激情久久 | 国产小视频91 | 成年人国产视频 | 综合激情亚洲 | 国产永久在线观看 | 国产精品久久久爽爽爽麻豆色哟哟 | 日韩欧美一区二区三区四区 | 韩国av中文字幕 |