而不是僞造時鐘,您可以以不同的方式測試此代碼。
顯然你可以爲job()
函數編寫單元測試(即確保它正在做它應該做的)。這可能很明顯。您可能想知道如何測試主腳本將正確調用您的函數,但在運行測試時無法確保它是10:30。
輸入着名的「猴子補丁」。由於Python具有頭等功能,因此可以簡單地將名稱綁定到函數。我不打算進入的單元測試框架以及如何使用mock
庫,但這裏的你可能會尋找一個簡單的例子:
import schedule
import time
def mock_run_pending():
job()
def mock_time_sleep(num):
exit()
schedule.run_pending = mock_run_pending
time.sleep = mock_time_sleep
def job():
print("I'm working...")
schedule.every(3).days.at("10:30").do(job)
while True:
schedule.run_pending()
time.sleep(1)
所以這是怎麼回事呢?如果您運行代碼片段,您會注意到job
函數實際上被稱爲!它只被調用一次,然後程序退出。原因是,我們只是將time
和schedule
模塊中的函數名稱重新命名爲我們的「模擬」版本(以使它們更易於測試)。
編輯:我們可以去更瘋狂和測試,我們通過在適當的參數傳遞給調度程序(我情不自禁):
import schedule
import time
class MockEvery(object):
def __init__(self, num):
assert(num == 3)
self.days = MockDays()
class MockDays(object):
def __init__(self):
pass
def at(self, time):
assert(time == "10:30")
return MockAt()
class MockAt(object):
def __init__(self):
pass
def do(self, func):
assert(func == job)
def mock_every(num):
return MockEvery(num)
def mock_run_pending():
job()
def mock_time_sleep(num):
exit()
schedule.run_pending = mock_run_pending
time.sleep = mock_time_sleep
schedule.every = mock_every
def job():
print("I'm working...")
schedule.every(3).days.at("10:30").do(job)
while True:
schedule.run_pending()
time.sleep(1)
附: (這與您的問題有些不相干,但您可能會發現它很有用):如果您希望將其納入測試框架,請查看mock
包,特別是@patch
裝飾器。它允許你在一個單元測試(或任何功能)中使用補丁函數。如果您有其他測試,您也不想撥打exit()
。使用pytest
退出特定測試很容易,但使用內置的unittest
有點困難,但當然可以。但是,我離題了。
HTH。