クロックをフェイクアウトする代わりに、このコードを別の方法でテストできます。
明らかに、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
関数が呼び出されます。それはちょうど1回呼ばれ、プログラムは終了します。その理由は、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)
P.S. (これはあなたの質問には関係ありませんが、役に立つかもしれません):これをテストフレームワークに組み込む場合は、mock
パッケージ、特に@patch
デコレータをチェックしてください。これは単体テスト(またはそれに関する任意の関数)内のサルパッチ関数にすることを可能にします。他のテストがある場合はexit()
に電話することも望ましくありません。 pytest
で特定のテストを終了するのは簡単ですが、組み込みのunittest
で行うのは少し難しくなりますが、確かに可能です。しかし、私は逃げる。
HTH。