Python 測試驅動開發讀書筆記(二)使用unittest框架擴展功能測試

使用功能測試驅動開發一個最簡可用的應用

上一節,我們啓用了Django,並且用Selenium驅動瀏覽器,測試了本地地址http://127.0.0.1,因爲只是啓動了首頁,並沒有做任何的頁面內容,所以首頁顯示爲空白

這節,我們要在Django框架裏開發一個Web應用——“一個代辦事項清單的網站”,它是一個很簡單的由文本字符串組成的列表,可以使用各種方式擴展功能,如使用持久模型、添加最後期限、提醒和分享功能,還可以改進客戶端UI

通過這個代辦事項,我們學習如何應用TDD理念

在這裏插入圖片描述
使用功能測試驅動開發一個最簡可用的應用

使用Selenium 實現了測試驅動瀏覽器,讓我們能從用戶的角度查看應用是如何運作的。因此,我們把這類測試叫作功能測試。這意味着,功能測試在某種程度上可以作爲應用的說明書。功能測試的作用是跟蹤用戶故事(User Story),模擬用戶使用某個功能的過程,以及應用應該如何響應用戶的操作。

功能測試應該可讀、容易理解的故事。爲了敘事清楚,可以把測試代碼和代碼 註釋結合起來使用。編寫新功能測試時,可以先寫註釋,勾勒出用戶故事的重點。這樣寫出的測試用例可讀,甚至可以作爲一種討論應用需求和功能的方式分享給非程序員看。

TDD 常與敏捷軟件開發方法結合在一起使用,我們經常提到的一個概念是“最簡可用的應用”,即我們能開發出來的最簡單的而且可以使用的應用。下面我們就來開發一個最簡可用的應用,儘早試水。

最簡可用的待辦事項清單其實只要能讓用戶輸入一些待辦事項,並且用戶下次訪問應用時 這些事項還在即可
打開functional_tests.py,開始編寫下面的故事

from selenium import webdriver
browser = webdriver.Firefox()

# 小明聽說有一個很酷的在線待辦事項應用
# 她去看了這個應用的首頁
browser.get('http://localhost:8000')

# 她注意到網頁的標題和頭部都包含“To-Do”這個詞
assert 'To-Do' in browser.title

# 應用邀請她輸入一個待辦事項
# 她在一個文本框中輸入了“Buy peacock feathers”(購買孔雀羽毛)
# 伊迪絲的愛好是使用假蠅做餌釣魚
# 她按回車鍵後,頁面更新了
# 待辦事項表格中顯示了“1: Buy peacock feathers”
# 頁面中又顯示了一個文本框,可以輸入其他的待辦事項
# 她輸入了“Use peacock feathers to make a fly”(使用孔雀羽毛做假蠅)
# 伊迪絲做事很有條理
# 頁面再次更新,她的清單中顯示了這兩個待辦事項
# 伊迪絲想知道這個網站是否會記住她的清單
# 她看到網站爲她生成了一個唯一的URL
# 而且頁面中有一些文字解說這個功能
# 她訪問那個URL,發現她的待辦事項列表還在
# 她很滿意,去睡覺了
browser.quit()

除了在測試中加入註釋之外,還修改了assert 這行代碼,讓其查找單詞“To-Do”,而不是“Django”。這意味着現在我們期望title返回的是“To-Do”。
啓動服務器:

$ python manage.py runserver

然後在另一個shell 中運行測試代碼,運行結果報錯,

python functional_tests.py 

在這裏插入圖片描述

Python標準庫中的unittest模塊

注意: Unittest框架使用方法大家可以參考官方文檔或者去介紹Unittest,有簡單的框架方法和實例
(Python語言Unitest框架的使用(一)準備工作:https://blog.csdn.net/sevensolo/article/details/98202271)

通過剛纔運行,我們發現斷言錯誤
我們需要修改測試代碼,使用assert 關鍵字的第二個參數

assert ‘To-Do’ in browser.title, "Browser title was " + browser.title

這裏使用了unittest 框架,代碼後面有具體解釋

from selenium import webdriver
import unittest


class NewVisitorTest(unittest.TestCase): 
	# 執行之前執行
    def setUp(self):
        self.brower = webdriver.Firefox() # 這裏注意Firefox首字母大小寫
        
	# 執行完之後執行
    def tearDown(self):
        self.brower.quit()

	# 測試用例
    def test_can_start_a_list_and_retrieve_it_later(self):
        # 伊迪絲聽說有一個很酷的在線待辦事項應用
        # 她去看了這個應用的首頁
        self.brower.get('http://localhost:8000')
        
        # 她注意到網頁的標題和頭部都包含“To-Do”這個詞
        self.assertIn('To-Do', self.brower.title)
        self.fail('Finish the test!')
        
        # 應用邀請她輸入一個待辦事項
        


if __name__ == '__main__':
        unittest.main(warnings='ignore')

你可能注意到以下幾個地方了。
➊ 測試組織成類的形式,繼承自unittest.TestCase。
➋ 測試的主要代碼寫在名爲test_can_start_a_list_and_retrieve_it_later 的方法中。名字以test_ 開頭的方法都是測試方法,由測試運行程序運行。類中可以定義多個測試方法。爲測試方法起個有意義的名字是個好主意。
➌ setUp 和tearDown 是特殊的方法,分別在各個測試方法之前和之後運行。我使用這兩個方法打開和關閉瀏覽器。注意,這兩個方法有點類似try/except 語句,就算測試中出錯了,也會運行tearDown 方法。1 測試結束後,Firefox 窗口不會一直停留在桌面上了。
➍ 使用self.assertIn 代替assert 編寫測試斷言。unittest 提供了很多這種用於編寫測試斷言的輔助函數,如assertEqual、assertTrue 和assertFalse 等。更多斷言輔助函數參見unittest 的文檔。
➎ 不管怎樣,self.fail 都會失敗,生成指定的錯誤消息。我使用這個方法提醒測試結束了。
➏ 最後是if name == ‘main’ 分句(如果你之前沒見過這種用法,我告訴你,Python 腳本使用這個語句檢查自己是否在命令行中運行,而不是在其他腳本中導入)。我們調用unittest.main() 啓動unittest 的測試運行程序,這個程序會在文件中自動查找測試類和方法,然後運行。
➐ warnings=‘ignore’ 的作用是禁止拋出ResourceWarning 異常。寫作本書時這個異常會拋出,但你閱讀時我可能已經把這個參數去掉了。你可以把這個參數刪掉,看一下效果。

繼續運行,報錯如下圖,斷言提示未找到”To-Do“,錯誤先放下
在這裏插入圖片描述

這樣是不是更好了?這個測試清理了Firefox 窗口,顯示了一個排版精美的報告,指出運行了幾個測試,其中有幾個測試失敗了,而且assertIn 還顯示了一個有利於調試的錯誤消息。

提交代碼

現在是提交代碼的好時機,因爲已經做了一次完整的修改。我們擴展了功能測試,加入註釋說明我們要在最簡可用的待辦事項清單應用中執行哪些操作。我們還使用Python 中的
unittest 模塊及其提供的各種測試輔助函數重寫了測試。

執行git status 命令,你會發現只有functional_tests.py 文件的內容變化了

$git status

在這裏插入圖片描述
執行git diff命令,查看上一次提交和當前硬盤中保存內容之間的差異,你會發現functional_tests.py 文 件的變動很大
$ git diff
在這裏插入圖片描述
git commit提代碼,-a 的意思是:自動添加已跟蹤文件(即已經提交的各文件)中的改動

 $ git commit -a

第一行輸入本次提交的備註後:wq!保存退出

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章