1. 程式人生 > 其它 >Python自動化測試基礎(二)

Python自動化測試基礎(二)

技術標籤:python自動化基礎

Python自動化測試基礎(二)

19.測試程式碼

編寫函式或類時,還可為其編寫測試。通過測試,可確定程式碼面對各種輸入都能夠按要求的那樣工作。測試讓你信心滿滿,深信即便有更多的人使用你的程式,它也 能正確地工作。在程式中新增新程式碼時,你也可以對其進行測試,確認它們不會破壞程式既有的行為。程式設計師都會犯錯,因此每個程式設計師都必須經常測試其程式碼,在 使用者發現問題前找出它們。

19.1 測試函式

要學習測試,得有要測試的程式碼。下面是一個簡單的函式,它接受名和姓並返回整潔的姓名

def get_fromatted_name(first,last):
    full_name=first+' '+last
    return full_name.title()

函式get_formatted_name() 將名和姓合併成姓名,在名和姓之間加上一個空格,並將它們的首字母都大寫,再返回結果。為核實get_formatted_name() 像期望的那樣 工作,我們來編寫一個使用這個函式的程式。程式names.py讓使用者輸入名和姓,並顯示整潔的全名:

def get_fromatted_name(first,last):
    full_name=first+' '+last
    return full_name.title()
print('輸入q進行退出!')
while True:
    first=input('請輸入你的姓:')
    if first=='q':
        break
    last=input('請輸入你的名:')
    if last=='q':
        break
    from_name=get_fromatted_name(first,last)
    print('你的名字是:'+from_name)

從上述輸出可知,合併得到的姓名正確無誤。現在假設我們要修改get_formatted_name() ,使其還能夠處理中間名。這樣做時,我們要確保不破壞這個函式處理只有名和 姓的姓名的方式。為此,我們可以在每次修改get_formatted_name() 後都進行測試:執行程式names.py,並輸入像Janis Joplin 這樣的姓名,但這太煩瑣了。所幸 Python提供了一種自動測試函式輸出的高效方式。倘若我們對get_formatted_name() 進行自動測試,就能始終信心滿滿,確信給這個函式提供我們測試過的姓名時,它都能 正確地工作。

19.1.1 單元測試和測試用例

Python標準庫中的模組unittest 提供了程式碼測試工具。單元測試 用於核實函式的某個方面沒有問題;測試用例 是一組單元測試,這些單元測試一起核實函式在各種情形下的 行為都符合要求。良好的測試用例考慮到了函式可能收到的各種輸入,包含針對所有這些情形的測試。全覆蓋式測試 用例包含一整套單元測試,涵蓋了各種可能的函式使用方 式。對於大型專案,要實現全覆蓋可能很難。通常,最初只要針對程式碼的重要行為編寫測試即可,等專案被廣泛使用時再考慮全覆蓋。

19.1.2 可通過的測試

建立測試用例的語法需要一段時間才能習慣,但測試用例建立後,再新增針對函式的單元測試就很簡單了。要為函式編寫測試用例,可先匯入模組unittest 以及要測試的函 數,再建立一個繼承unittest.TestCase 的類,並編寫一系列方法對函式行為的不同方面進行測試。

import unittest
from name_function import get_fromatted_name#匯入該函式
class NameTestCase(unittest.TestCase):#建立一個類 必須繼承unittest.TestCase類
    """測試get_fromatted_name方法"""
    def test_first_last_name(self):#測試類包含一個方法
        fromatted_name=get_fromatted_name('long','wenjie')#呼叫函式方法
        self.assertEqual(fromatted_name,'long wenjie')#呼叫assertEqual()斷言方法,並向它傳遞formatted_name 和'Janis Joplin'
        """程式碼行self.assertEqual(formatted_name, 'Janis Joplin') 的意思是
說:“將formatted_name 的值同字串'Janis Joplin' 進行比較,如果它們相等,就萬事大吉,如果它們不相等,跟我說一聲!”"""
unittest.main()

結果:

19.1.3 不能通過的測試

測試未通過時結果是什麼樣的呢?我們來修改get_formatted_name() ,使其能夠處理中間名,但這樣做時,故意讓這個函式無法正確地處理像Janis Joplin這樣只有名和姓的 姓名。

def get_fromatted_name(first,middle,last):
    full_name=first+' '+middle+' '+last
    return full_name

再次執行測試程式碼時會發現

其中包含的資訊很多,因為測試未通過時,需要讓你知道的事情可能有很多。第1行輸出只有一個字母E (見❶),它指出測試用例中有一個單元測試導致了錯誤。接下來,我們 看到NamesTestCase 中的test_first_last_name() 導致了錯誤(見❷)。測試用例包含眾多單元測試時,知道哪個測試未通過至關重要。在❸處,我們看到了一個標準 的traceback,它指出函式呼叫get_formatted_name('janis', 'joplin') 有問題,因為它缺少一個必不可少的位置實參。

19.1.4 測試未通過時怎麼辦

測試未通過時怎麼辦呢?如果你檢查的條件沒錯,測試通過了意味著函式的行為是對的,而測試未通過意味著你編寫的新程式碼有錯。因此,測試未通過時,不要修改測試,而應 修復導致測試不能通過的程式碼:檢查剛對函式所做的修改,找出導致函式行為不符合預期的修改。

19.1.5 新增新測試

確定get_formatted_name() 又能正確地處理簡單的姓名後,我們再編寫一個測試,用於測試包含中間名的姓名。為此,我們在NamesTestCase 類中再新增一個方法:

import unittest
from name_function import get_fromatted_name#匯入該函式
class NameTestCase(unittest.TestCase):#建立一個類 必須繼承unittest.TestCase類
    """測試get_fromatted_name方法"""
    def test_first_last_name(self):#測試類包含一個方法
        fromatted_name=get_fromatted_name('long','wenjie')#呼叫函式方法
        self.assertEqual(fromatted_name,'long wenjie')#呼叫assertEqual()斷言方法,並向它傳遞formatted_name 和'Janis Joplin'
        """程式碼行self.assertEqual(formatted_name, 'Janis Joplin') 的意思是
說:“將formatted_name 的值同字串'Janis Joplin' 進行比較,如果它們相等,就萬事大吉,如果它們不相等,跟我說一聲!”"""
    def test_first_last_middle_name(self):
        fromatted_name=get_fromatted_name('long','wen','jie')
        self.assertEqual(fromatted_name,'long wen jie')
unittest.main()

我們將這個方法命名為test_first_last_middle_name() 。方法名必須以test_打頭,這樣它才會在我們執行test_name_function.py時自動執行。