監控程序如何編寫單元測試?

我現在在用Python開發一個日誌監控程序。

使用pyinotify去監控文件的變動。

然後執行對應callback。

但是對監控邏輯的單元測試非常難寫。

首先監控是非同步的,我在測試用例中對文件進行了操作,需要等待監控發現了文件的變動,然後處理了之後才能驗證邏輯有效性。

但是這個等待監控發現的過程不可控,因為由於虛擬機磁碟IO或者CPU的原因導致等待時間不確定,於是用例錯誤。

並且也嘗試在監控線程中增加event,來確保文件變更事件被觸發之後,測試用例等待時間執行完畢再進行檢測,但是偶爾會有失敗的情況。

如何能編寫持續有效的單元測試?

或者類似的邏輯如何覆蓋,確保代碼質量?


有效的單元測試的邏輯應該簡單清晰,避免在描述用例的過程中增加更多的複雜度。

況且單元測試本來就是為了測試模塊本身的邏輯,除此之外的性能問題,甚至於是底層系統問題都不是單元測試關心的點。

可以參考 google 對 python-fanotify 寫的單元測試:python-fanotify/fanotify_test.py at master · google/python-fanotify · GitHub


謝邀。這個事情還真沒幹過。依經驗答一下,估計大有錯漏,還請行家指正。

如果我做,大概會採用「階段信任」(自己瞎扯的術語)的方式吧,比如認為pyinotify是沒有問題的,然後手動調用自己的callback來進行測試,嗯,肯定要進行mock了。


簡單來說,該軟體(腳本)涉及到網路, 文件系統,而對於單元測試,是不允許接觸網路和文件系統的, 編寫單元測試步驟如下

  • 拆分

把邏輯單元從函數和類里拆分成更小的單元,注意把涉及網路和文件的部分和業務邏輯部分進行隔離, 為這些不需要文件,網路的部分編寫單元測試

  • Test Doubles

比較常用的算是Mock, Fake 和 Stub, 在標準庫里已經有mock模塊了,下面是簡單用法

以下代碼為憑印象手打,如有紕漏請見諒

簡單來說, 比如你有一文件, 是去獲取某網路資源的,比如文件名為resource.py

import requests

def retrieve_text_from_url(url):
response = requests.get(url)
if response.status_code == 200:
return request.text
else:
# 拋出自定義異常
raise ResoucesNotFoundException()

那麼你可以在測試文件resource_test.py里使用mock,該模塊已經集成在unittest 模塊里

from module_name.resouce import retrieve_text_from_url
from unittest.mock import patch
import unittest

class ResourceTest(unittest.TestCase):
@patch("module_name.resource.requests")
# requests 在 resource模塊里已經被mock了
def test_can_throw_exception(self, mock_requests):
mock_requests.return_value.status_code = 401
with self.assertraise(ResoucesNotFoundException):
retrieve_text_from_url(r"http://www.google.com")

if __name__ == "__main__":
unittest.main()

相信這個例子已經能讓你知道如何使用mock了, 如果某個函數依賴了retrieve_text_from_url, 你只需要把這個函數也mock掉了,可以替換成你平時處理的正常的內容,這樣,你的單元測試就徹底脫離了對於文件和網路的依賴。

另外對於一些無返回值的函數,你甚至可以直接assert_called_with(somewhat_parameters)來測試。

  • Mock並不是銀彈

Mock並不是軟體測試的銀彈,並不是說通過mock做出的單元測試,所有測試都通過,覆蓋率達到90%以上,軟體就不會出Bug了,軟體測試本身也只能提高軟體的質量,而不能夠確保軟體運行無誤,要測試生產環境的所有可能,老老實實搭建測試環境,進行黑盒測試是非常必要的,不過根據你的描述,你的程序(腳本)似乎不太可能能用得著黑盒測試

以上為個人經驗,歡迎指正


只要過程中有不可控因素的,我不認為這是單元測試,我的觀點是單元測試必須過程是完全可控的。

操作系統咱沒精力深入,就認為它完全可靠,但不使用奇技淫巧等。

開發平台咱沒精力,也認為它完全可靠,也不使用旁門左道。

剩下的咱自己寫的代碼,咱才考慮充分的測試,追求儘可能多,也不求完全。

首先代碼結構劃分要合理模塊化,考慮測試的話,把不便於單元測試的代碼和便於單元測試的代碼合理區隔。然後就各顯神通進行單元測試和集成測試吧,mock是個好方法。


沒有用mock么?

可以使用mock來模擬外部事件 屏蔽調不可控因素 獲取返回結果 把單元測試的注意力放到業務本身


不會python,但為何加了你說的event還會偶爾失敗?


推薦閱讀:

王垠當年提倡「完全用 linux 工作」,然而最近又發文挺 windows 噴 unix,這中間究竟經歷了什麼?
windows10內置的ubuntu怎麼樣?
如何將Windows的C:user像Linux的/home一樣單獨掛載一塊硬碟?
微軟為什麼用帶 BOM 的 UTF-8,造成和多數系統的不兼容?
關於 llvm/clang 在 Ubuntu 下的安裝?

TAG:編程語言 | Python | 編程 | Linux | 單元測試 |