《Python編程從入門到實(shí)踐》第十一章

在本章中,你將學(xué)習(xí)如何使用Python模塊unittest中的工具來測(cè) 試代碼。

測(cè)試函數(shù)

要為函數(shù)編寫測(cè)試用例,可先導(dǎo)入模塊unittest以及要測(cè)試的函數(shù),再創(chuàng)建一個(gè)繼承unittest.TestCase的類,并編寫一系列方法對(duì)函數(shù)行為的不同方面進(jìn)行測(cè)試。

"""name_function.py"""
def get_formatted_name(first, last):
    full_name = first + ' ' + last
    return full_name.title()
'''names.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':
        break
    last = input("Please give me a last name: ")
    if last == 'q':
        break

    formatted_name = get_formatted_name(first, last)
    print("\tNeatly formatted name: " + formatted_name + '.')
'''test_name_function.py'''
import unittest
from name_function import get_formatted_name

class NameTestCase(unittest.TestCase):
    def test_first_last_name(self):
        formatted_name = get_formatted_name('janis', 'joplin')
        self.assertEqual(formatted_name, 'Janis Joplin')

unittest.main()

我們導(dǎo)入了模塊unittest和要測(cè)試的函數(shù)get_formatted_ name()。我們創(chuàng)建 了一個(gè)名為NamesTestCase的類,用于包含一系列針對(duì)get_formatted_name()的單元測(cè)試。這個(gè)類必須繼承 unittest.TestCase類,這樣Python才知道如何運(yùn)行你編寫的測(cè)試。 NamesTestCase只包含一個(gè)方法,用于測(cè)試get_formatted_name()的一個(gè)方面。我們將這個(gè)方 法命名為test_first_last_name(),因?yàn)槲覀円藢?shí)的是只有名和姓的姓名能否被正確地格式化。 我們運(yùn)行test_name_function.py時(shí),所有以test_打頭的方法都將自動(dòng)運(yùn)行。在這個(gè)方法中,我們調(diào)用了要測(cè)試的函數(shù),并存儲(chǔ)了要測(cè)試的返回值。在這個(gè)示例中,我們使用實(shí)參'janis'和'joplin' 調(diào)用get_formatted_name(),并將結(jié)果存儲(chǔ)到變量formatted_name中。
另外,上例中使用了一個(gè)斷言方法,代碼行self.assertEqual(formatted_name, 'Janis Joplin')的意思是說: 將formatted_name的值同字符串'Janis Joplin'進(jìn)行比較,判斷是否相等。代碼行unittest.main()讓Python運(yùn)行這個(gè)文件中的測(cè)試。

測(cè)試類

unnittest Module中的斷言方法.png

測(cè)試過程類似于對(duì)函數(shù)的測(cè)試:

'''survey.py'''
class AnonymousSurvey():

    def __init__(self, question):
        self.question = question
        self.responses = []

    def show_question(self):
        print(self.question)

    def store_response(self, new_response):
        self.responses.append(new_response)

    def show_results(self):
        print("Survey results: ")
        for response in self.responses:
            print("- " + response)
'''language_survey.py'''
from survey import 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':
        break
    my_survey.store_response(response)

print("\nThank you to everyone who participated in the survey!")
my_survey.show_results()
'''test_survey.py'''
import unittest
from survey import AnonymousSurvey

class TestAnonmyousSurvey(unittest.TestCase):

    def test_store_single_response(self):
        question = "What language did you first learn to speak?"
        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', 'Spanish', 'Mandarin']
        for response in responses:
            my_survey.store_response(response)
        for response in responses:
            self.assertIn(response, my_survey.responses)

unittest.main()

方法setUp()

unittest.TestCase類包含方法setUp(),讓我們只需創(chuàng)建這些對(duì)象一 次,并在每個(gè)測(cè)試方法中使用它們。如果你在TestCase類中包含了方法setUp(),Python將先運(yùn)行 它,再運(yùn)行各個(gè)以test_打頭的方法。這樣,在你編寫的每個(gè)測(cè)試方法中都可使用在方法setUp() 中創(chuàng)建的對(duì)象了。

import unittest
from survey import AnonymousSurvey

class TestAnonmyousSurvey(unittest.TestCase):
    def setUp(self):
        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)建一個(gè)調(diào)查對(duì)象;創(chuàng)建一個(gè)答案列表。存儲(chǔ)這 兩樣?xùn)|西的變量名包含前綴self(即存儲(chǔ)在屬性中),因此可在這個(gè)類的任何地方使用。這讓兩 個(gè)測(cè)試方法都更簡(jiǎn)單,因?yàn)樗鼈兌疾挥脛?chuàng)建調(diào)查對(duì)象和答案。方法test_store_three_response() 核實(shí)self.responses中的第一個(gè)答案——self.responses[0]——被妥善地存儲(chǔ),而方法 test_store_three_response()核實(shí)self.responses中的全部三個(gè)答案都被妥善地存儲(chǔ)。
運(yùn)行測(cè)試用例時(shí),每完成一個(gè)單元測(cè)試,Python都打印一個(gè)字符:測(cè)試通過時(shí)打印一個(gè) 句點(diǎn);測(cè)試引發(fā)錯(cuò)誤時(shí)打印一個(gè)E;測(cè)試導(dǎo)致斷言失敗時(shí)打印一個(gè)F。這就是你運(yùn)行測(cè)試 用例時(shí),在輸出的第一行中看到的句點(diǎn)和字符數(shù)量各不相同的原因。如果測(cè)試用例包含 很多單元測(cè)試,需要運(yùn)行很長(zhǎng)時(shí)間,就可通過觀察這些結(jié)果來獲悉有多少個(gè)測(cè)試通過了。

在本章中,你學(xué)習(xí)了:如何使用模塊unittest中的工具來為函數(shù)和類編寫測(cè)試;如何編寫繼 承unittest.TestCase的類,以及如何編寫測(cè)試方法,以核實(shí)函數(shù)和類的行為符合預(yù)期;如何使用 方法setUp()來根據(jù)類高效地創(chuàng)建實(shí)例并設(shè)置其屬性,以便在類的所有測(cè)試方法中都可使用它們。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容