02.28 Django 博客單元測試:測試評論應用

Django 博客單元測試:測試評論應用

作者:HelloGitHub-追夢人物

文中所涉及的示例代碼,已同步更新到 HelloGitHub-Team 倉庫

評論應用的測試和博客應用測試的套路是一樣的。

先來建立測試文件的目錄結構。首先在 comments 應用的目錄下建立一個名為 tests 的 Python 包,然後刪除 comments 應用下 django 自動生成的 tests.py 文件,防止和 tests 包衝突,再根據需要測試的內容,創建相應的 Python 模塊。最終 tests 目錄結構如下:

<code>comments\\templatetags\\models.py...tests\\__init__.pybase.pytest_models.pytest_templatetags.pytest_views.py/<code>

其中 base.py 用於存放各個測試用例的公共的數據初始化基類。

數據基類

由於評論必須和文章關聯,因此我們首先來寫一個數據基類,用於初始化生成文章數據,其它測試類繼承這個數據基類,從而不用在每個測試類裡都寫一遍創建文章數據的代碼了。

數據基類寫在 base.py 模塊裡:

Django 博客單元測試:測試評論應用


要注意創建文章數據時,使用 apps.get_app_config('haystack').signal_processor.teardown() 斷開創建索引的信號。

測試 Comment Model

Comment Model 的代碼邏輯比較簡單,測試起來也很簡單:

Django 博客單元測試:測試評論應用


測試視圖函數

我們只有一個發表評論的視圖函數,根據視圖函數的邏輯,需要測試以下幾點:

  1. 只處理 POST 請求,其它請求將返回 405 Method Not Allowed 錯誤碼。
  2. 如果評論的文章不存在,返回 404 錯誤碼。
  3. 如果提交的評論內容有錯誤(例如 email 格式不正確),將渲染 preview.html 預覽頁面,並且預覽頁面顯示評論出錯的消息提醒和評論表單中包含的錯誤。
  4. 提交的內容合法,則創建評論,用戶被重定向回被評論文章的詳情頁,頁面中包含評論成功的消息提醒。

具體代碼如下(省略掉了一些簡單的一看就懂的測試用例):

Django 博客單元測試:測試評論應用


首先看到 test_invalid_comment_data 測試用例。這個測試用例中,我們構造了一個缺失評論內容、評論人名字且郵箱格式不正確的數據,然後將其提交了評論。接著就是對預期結果的斷言。這裡關鍵的一點是,渲染的預覽頁面應該包含提示用戶的表單錯誤。所以我們從響應的上下文變量中取得表單 form 這個模板變量。接著使用如下代碼獲取表單的錯誤並斷言響應中是否包含了這些錯誤:

<code>for field_name, errors in form.errors.items():    for err in errors:        self.assertContains(response, err)/<code>

一旦表單綁定了數據,並且 is_valid 方法被調用,就會有一個 errors 屬性(參考評論視圖函數中表單的處理邏輯)。errors 屬性是一個類字典對象,如果表單數據不包含錯誤,則為空;如果包含錯誤數據,則其鍵為包含錯誤數據的字段名稱,值為該字段錯誤提示構成的列表(一個字段可能包含多個錯誤,所以是一個列表)。例如這裡的 form.errors,如果將其打印出來(使用 print(repr(form.errors)),str 方法返回的內容是經渲染的 ul 列表),可以看到它的內容如下:

<code>{'name': ['這個字段是必填項。'], 'email': ['輸入一個有效的 Email 地址。'], 'text': ['這個字段是必填項。']}/<code>

test_valid_comment_data 中,我們構造合法的評論內容並提交,預期結果是評論提交成功後重定向到被評論文章的詳情頁,所以使用了 assertRedirects 進行斷言。

注意 self.client.post(self.url, valid_data, follow=True) 傳入的 follow=True 參數。由於評論成功後需要重定向,因此傳入 follow=True,表示跟蹤重定向,因此返回的響應,是最終重定向之後返回的響應(即被評論文章的詳情頁),如果傳入 False,則不會追蹤重定向,返回的響應就是一個響應碼為 302 的重定向前響應。

對於重定向響應,使用 assertRedirects 進行斷言,這個斷言方法會對重定向的整個響應的過程進行檢測,默認檢測的是響應碼從 302 變為 200。

測試模板標籤

上一篇中介紹過模板標籤的測試方法。基本套路就是代替 django 視圖函數自動渲染模板內容的過程,手工構造一個包含待測試模板標籤的模板,然後手工渲染其內容,斷言渲染後的內容是否包含預期的內容。具體代碼請看源代碼,這裡不再一一講解,只將涉及的幾個新的表單操作進行一個簡單介紹。

Django 博客單元測試:測試評論應用


看到循環表單 form 的語句:

<code>for field in form:label = '<label>{}:/<label>'.format(field.id_for_label, field.label)/<code>

我們這裡使用了 field 的兩個屬性,id_for_label 和 id_for_label,分別是 django 表單自動生成的表單字段 label 的 id 和 label 名。別的就沒什麼好說的了,就是不停地斷言頁面包含預期的 HTML 內容。

至此,我們完成了對 blog 應用和 comment 應用這兩個核心 app 的測試。現在,我們想知道的是,到底我們的測試效果怎麼樣呢?測試充分嗎?測試全面嗎?還有沒有沒有測到的地方呢?

單憑肉眼觀察難以回答上面的問題,接下來我們就藉助一個工具,從代碼覆蓋率的角度來檢測一下我們的測試效果究竟如何。

Django 博客單元測試:測試評論應用

『講解開源項目系列』——讓對開源項目感興趣的人不再畏懼、讓開源項目的發起者不再孤單。跟著我們的文章,你會發現編程的樂趣、使用和發現參與開源項目如此簡單。歡迎聯繫我(微信:xueweihan,備註:講解)加入我們,讓更多人愛上開源、貢獻開源~


分享到:


相關文章: