成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

Python學(xué)習(xí)之路10-測(cè)試代碼

huangjinnan / 3201人閱讀

摘要:也就是說(shuō),你可以將上述代碼中的看做單元測(cè)試,而將看做測(cè)試用例。在測(cè)試類(lèi)中的每一個(gè)測(cè)試方法都必須以開(kāi)頭,否則將不會(huì)被認(rèn)定是一個(gè)單元測(cè)試。

《Python編程:從入門(mén)到實(shí)踐》筆記。
本章主要學(xué)習(xí)如何使用Python標(biāo)準(zhǔn)庫(kù)中的unittest模塊對(duì)代碼進(jìn)行簡(jiǎn)單的測(cè)試。
1. 前言

作為初學(xué)者,并非必須為你嘗試的所有項(xiàng)目編寫(xiě)測(cè)試;但參與工作量較大的項(xiàng)目時(shí),你應(yīng)對(duì)自己編寫(xiě)的函數(shù)和類(lèi)的重要行為進(jìn)行測(cè)試。這樣你就能夠更加確定自己所做的工作不會(huì)破壞項(xiàng)目的其他部分,你就能夠隨心所欲地改進(jìn)即有代碼。如果不小心破壞了原來(lái)的功能,你馬上就會(huì)知道,從而能夠輕松地修復(fù)問(wèn)題。相比于等到Bug出現(xiàn)后再去改,在測(cè)試未通過(guò)時(shí)采取措施要容易得多。而且,如果你想要分享你的項(xiàng)目,有測(cè)試的代碼更容易讓人接受。

2. 測(cè)試函數(shù) 2.1 一個(gè)能通過(guò)的測(cè)試

以下是一個(gè)將用戶(hù)輸入的姓與名拼接的函數(shù):

# name_function.py
def get_formatted_name(first, last):
    """返回一個(gè)整潔的完整姓名"""
    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 + ".")

當(dāng)然你也可以將if語(yǔ)句下面的代碼多帶帶放在一個(gè)文件中,并在該文件開(kāi)頭帶入get_formatted_name()函數(shù)。

對(duì)if __name__ == "__main__"的補(bǔ)充:

在Python中,模塊就是對(duì)象,所有模塊都有一個(gè)內(nèi)置屬性__name__,當(dāng)該模塊被導(dǎo)入時(shí),該模塊的__name__屬性會(huì)被置為模塊名,當(dāng)直接運(yùn)行該模塊,或者說(shuō)直接運(yùn)行該文件時(shí),該屬性就會(huì)使用默認(rèn)值"__main__",可以用一句經(jīng)典的話(huà)總結(jié)這個(gè)用法:

Make a script both importable and executable.

if語(yǔ)句下面的代碼相當(dāng)于對(duì)上面的函數(shù)的測(cè)試,不過(guò)這樣的測(cè)試每次都需要我們自己輸入數(shù)據(jù),并自己根據(jù)結(jié)果判斷代碼是否工作正常,如果代碼稍微多一點(diǎn),稍微復(fù)雜一點(diǎn),這樣的測(cè)試方法將會(huì)很繁瑣,所以,我們使用unittest模塊了測(cè)試代碼。

# 代碼test_name_function.py:
import unittest
from name_function import get_formatted_name

class NamesTestCase(unittest.TestCase):
    """測(cè)試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é)果:
.     # 這里有個(gè)實(shí)心句點(diǎn)
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK

這里先明確兩個(gè)概念:

單元測(cè)試:用于核實(shí)函數(shù)在某個(gè)方面沒(méi)有問(wèn)題

測(cè)試用例:一組單元測(cè)試,這些單元測(cè)試一起核實(shí)函數(shù)在各種情況下的行為都符合要求。

也就是說(shuō),你可以將上述代碼中的test_first_last_name看做單元測(cè)試,而將NamesTestCase看做測(cè)試用例。

一般測(cè)試文件多帶帶放在一個(gè)文件夾中,也可以將測(cè)試都放在一個(gè)文件中。

為函數(shù)編寫(xiě)測(cè)試用例,可先導(dǎo)入unittest模塊和要測(cè)試的函數(shù),再創(chuàng)建一個(gè)繼承unittest.TestCase的類(lèi),并編寫(xiě)一系列方法對(duì)函數(shù)行為的不同方面進(jìn)行測(cè)試。在測(cè)試用,我們使用斷言self.assertEqual()(并不是只有這一個(gè)斷言函數(shù))來(lái)判斷結(jié)果與期望是否相同。在測(cè)試類(lèi)中的每一個(gè)測(cè)試方法都必須以test_開(kāi)頭,否則將不會(huì)被認(rèn)定是一個(gè)單元測(cè)試。最后我們通過(guò)unittest.main()來(lái)運(yùn)行這個(gè)文件中的所有測(cè)試。當(dāng)測(cè)試通過(guò)時(shí),結(jié)果中會(huì)先輸出一個(gè)實(shí)心句點(diǎn),輸出幾個(gè)句點(diǎn)表示通過(guò)了幾個(gè)單元測(cè)試,然后輸出單元測(cè)試數(shù)目,最后輸出OK。

2.2 一個(gè)不能通過(guò)的測(cè)試

外國(guó)人的名字還有中間名,以上代碼并未考慮這個(gè)情況。我們通過(guò)將上述代碼改成含有中間名的版本來(lái)演示測(cè)試不通過(guò)的情況:

# 代碼:
def get_formatted_name(first, middle, last):
    """返回一個(gè)整潔的完整姓名"""
    full_name = first + " " + middle + " " + last
    return full_name.title()

# 其余代碼均不變

# 運(yùn)行上面測(cè)試代碼后的結(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)

第一行輸出了一個(gè)字母Etraceback指出缺少了參數(shù)。如果你檢查的條件沒(méi)錯(cuò),測(cè)試通過(guò)了意味著函數(shù)的行為是對(duì)的,而測(cè)試未通過(guò)意味著你編寫(xiě)的新代碼有錯(cuò)。因此,測(cè)試未通過(guò)時(shí),不是去修改測(cè)試代碼,而失去修改你編寫(xiě)的代碼。

2.3 添加新測(cè)試

以下我們將上述的get_formatted_name()函數(shù)修改為能自動(dòng)處理中間名的函數(shù),并在測(cè)試文件中添加一個(gè)單元測(cè)試:

# name_function.py
def get_formatted_name(first, last, middle=""):
    """返回一個(gè)整潔的完整姓名"""
    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):
    """測(cè)試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

OK
3. 測(cè)試類(lèi)

前面講的都是對(duì)函數(shù)的測(cè)試,這里我們開(kāi)始對(duì)類(lèi)的測(cè)試。在測(cè)試之前,先介紹幾種常用的斷言方法:

方法 用途
assertEqual(a, b) 核實(shí) a == b
assertNotEqual(a, b) 核實(shí) a != b
assertTrue(x) 核實(shí)x為T(mén)rue
assertFalse(x) 核實(shí)x為False
assertIn(item, list) 核實(shí)item在list中
assertNotIn(item, list) 核實(shí)item不在list中

下面創(chuàng)建一個(gè)匿名調(diào)查類(lèi):

# survey.py
class AnonymousSurvey:
    """收集匿名調(diào)查問(wèn)卷的答案"""

    def __init__(self, question):
        """存儲(chǔ)一個(gè)問(wèn)題,并為存儲(chǔ)答案做準(zhǔn)備"""
        self.question = question
        self.responses = []

    def show_question(self):
        """顯示調(diào)查問(wèn)卷"""
        print(self.question)

    def store_response(self, new_response):
        """存儲(chǔ)單份調(diào)查問(wèn)卷"""
        self.responses.append(new_response)

    def show_results(self):
        """顯示收集到的所有答卷"""
        print("Survey results:")
        for response in self.responses:
            print("- " + response)

以下是對(duì)該類(lèi)的測(cè)試代碼:

# test_survey.py
import unittest
from chapter11 import AnonymousSurvey

class TestAnonymousSurvey(unittest.TestCase):
    """針對(duì)AnonymousSurvey類(lèi)的測(cè)試"""

    def setUp(self):
        """創(chuàng)建一個(gè)調(diào)查對(duì)象和一組答案,共測(cè)試方法使用"""
        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):
        """測(cè)試單個(gè)答案唄妥善地存儲(chǔ)"""
        self.my_survey.store_response(self.responses[0])
        self.assertIn(self.responses[0], self.my_survey.responses)

    def test_store_three_responses(self):
        """測(cè)試三個(gè)答案會(huì)被妥善地存儲(chǔ)"""
        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()方法相當(dāng)于普通函數(shù)的__init__()方法,用于初始化這個(gè)測(cè)試類(lèi),減少重復(fù)代碼,比如,如果不用setUp()方法,那么question變量在每個(gè)測(cè)試函數(shù)中都要聲明一次,十分麻煩低效。你過(guò)測(cè)試類(lèi)中包含了setUp()方法,Python將先運(yùn)行它,再運(yùn)行各個(gè)以test_開(kāi)頭的方法。

至此,Python的基礎(chǔ)部分大致結(jié)束,后面將是項(xiàng)目部分,以后可能還會(huì)對(duì)基礎(chǔ)部分進(jìn)行補(bǔ)充。


迎大家關(guān)注我的微信公眾號(hào)"代碼港" & 個(gè)人網(wǎng)站 www.vpointer.net ~

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/41791.html

相關(guān)文章

  • Python學(xué)習(xí)之路10-測(cè)試代碼

    摘要:也就是說(shuō),你可以將上述代碼中的看做單元測(cè)試,而將看做測(cè)試用例。在測(cè)試類(lèi)中的每一個(gè)測(cè)試方法都必須以開(kāi)頭,否則將不會(huì)被認(rèn)定是一個(gè)單元測(cè)試。 《Python編程:從入門(mén)到實(shí)踐》筆記。本章主要學(xué)習(xí)如何使用Python標(biāo)準(zhǔn)庫(kù)中的unittest模塊對(duì)代碼進(jìn)行簡(jiǎn)單的測(cè)試。 1. 前言 作為初學(xué)者,并非必須為你嘗試的所有項(xiàng)目編寫(xiě)測(cè)試;但參與工作量較大的項(xiàng)目時(shí),你應(yīng)對(duì)自己編寫(xiě)的函數(shù)和類(lèi)的重要行為進(jìn)行測(cè)...

    Developer 評(píng)論0 收藏0
  • Python學(xué)習(xí)之路4-if語(yǔ)句

    摘要:本章主要講述條件語(yǔ)句等結(jié)構(gòu)。是一條包羅萬(wàn)象的語(yǔ)句,只要不滿(mǎn)足前面的條件,其中的代碼就會(huì)執(zhí)行,這可能會(huì)引入無(wú)效甚至惡意的數(shù)據(jù)。使用語(yǔ)句處理列表語(yǔ)句常和循環(huán)結(jié)構(gòu)配合使用。 《Python編程:從入門(mén)到實(shí)踐》筆記。本章主要講述條件語(yǔ)句if, if-else, if-elif, if-elif-else等結(jié)構(gòu)。 1. 條件測(cè)試 包括了相等,不等,大于,小于,大于等于,小于等于,存在于,與或非等...

    JouyPub 評(píng)論0 收藏0
  • Python 進(jìn)階之路 (九) 再立Flag, 社區(qū)最全的itertools深度解析(上)

    摘要:例如,以下對(duì)兩個(gè)的相應(yīng)元素求和這個(gè)例子很好的解釋了如何構(gòu)建中所謂的迭代器代數(shù)的函數(shù)的含義。為簡(jiǎn)單起見(jiàn),假設(shè)輸入的長(zhǎng)度可被整除。接受兩個(gè)參數(shù)一個(gè)可迭代的正整數(shù)最終會(huì)在中個(gè)元素的所有組合的元組上產(chǎn)生一個(gè)迭代器。 前言 大家好,今天想和大家分享一下我的itertools學(xué)習(xí)體驗(yàn)及心得,itertools是一個(gè)Python的自帶庫(kù),內(nèi)含多種非常實(shí)用的方法,我簡(jiǎn)單學(xué)習(xí)了一下,發(fā)現(xiàn)可以大大提升工作...

    tuantuan 評(píng)論0 收藏0
  • 《正規(guī)軍的Python進(jìn)階之路Python技能樹(shù)測(cè)評(píng)》

    摘要:每個(gè)模塊都有對(duì)應(yīng)的分支內(nèi)容,并且分支內(nèi)容都分為參考資料練習(xí)題交流討論三個(gè)內(nèi)容,我最喜歡的是練習(xí)題,之前都是非正規(guī)軍的學(xué)習(xí),沒(méi)有系統(tǒng)訓(xùn)練過(guò),現(xiàn)在有技能樹(shù)測(cè)評(píng)終于可以把之前散亂的知識(shí)點(diǎn)總結(jié)在一起了。祝大家都能在技能樹(shù)測(cè)評(píng)判斷自己在哪個(gè)級(jí)別的。 通過(guò)《Python技能樹(shù)測(cè)評(píng)》判斷自己在哪個(gè)級(jí)別: ...

    jayzou 評(píng)論0 收藏0
  • Python學(xué)習(xí)之路9-文件和異常

    摘要:本章主要是學(xué)習(xí)的文件操作,主要是從文件中讀取數(shù)據(jù)以及將數(shù)據(jù)存儲(chǔ)到文件中,還有錯(cuò)誤處理,異常類(lèi),模塊等。函數(shù)返回一個(gè)文件對(duì)象,用于接收該對(duì)象。異常中使用被稱(chēng)為異常的特殊對(duì)象來(lái)管理程序執(zhí)行期間發(fā)生的錯(cuò)誤。 《Python編程:從入門(mén)到實(shí)踐》筆記。本章主要是學(xué)習(xí)Python的文件操作,主要是從文件中讀取數(shù)據(jù)以及將數(shù)據(jù)存儲(chǔ)到文件中,還有錯(cuò)誤處理,異常類(lèi),json模塊等。 1. 從文件中讀數(shù)據(jù) ...

    chenatu 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<