2013-12-10 5 views

答えて

19

datetime.now関数をmonkeypatchする必要があります。これは私が(今オーバーライドに使用する治具である

import datetime 
import pytest 

FAKE_TIME = datetime.datetime(2020, 12, 25, 17, 05, 55) 

@pytest.fixture 
def patch_datetime_now(monkeypatch): 

    class mydatetime: 
     @classmethod 
     def now(cls): 
      return FAKE_TIME 

    monkeypatch.setattr(datetime, 'datetime', mydatetime) 


def test_patch_datetime(patch_datetime_now): 
    assert datetime.datetime.now() == FAKE_TIME 
+0

はそれだけで 'now'方法を交換することは可能ですか? – satoru

+0

これは機能しますが、 "from datetime import datetime"を実行した場合は無効です。ここでdetaisを見てみましょう:http://stackoverflow.com/questions/35431476/why-pythons-monkeypatch-doesnt-work-when-importing-a-class-instead-of-a-module – rgargente

3

)が、(RE作業日時の残りの部分を維持する:下の例では、私は他のテストの後半を再利用することができますフィクスチャを作成してい悟さんの質問)。

これは広範にテストされていませんが、datetimeが他のコンテキストで使用されている問題を回避します。私にとっては、Django ORMをこれらの日時の値(特にisinstance(Freeze.now(), datetime.datetime) == True)で使用することが重要でした。

@pytest.fixture 
def freeze(monkeypatch): 
    """ Now() manager patches datetime return a fixed, settable, value 
     (freezes time) 
    """ 
    import datetime 
    original = datetime.datetime 

    class FreezeMeta(type): 
     def __instancecheck__(self, instance): 
      if type(instance) == original or type(instance) == Freeze: 
       return True 

    class Freeze(datetime.datetime): 
     __metaclass__ = FreezeMeta 

     @classmethod 
     def freeze(cls, val): 
      cls.frozen = val 

     @classmethod 
     def now(cls): 
      return cls.frozen 

     @classmethod 
     def delta(cls, timedelta=None, **kwargs): 
      """ Moves time fwd/bwd by the delta""" 
      from datetime import timedelta as td 
      if not timedelta: 
       timedelta = td(**kwargs) 
      cls.frozen += timedelta 

    monkeypatch.setattr(datetime, 'datetime', Freeze) 
    Freeze.freeze(original.now()) 
    return Freeze 

おそらくトピックはありませんが、この質問に到着した他の人には便利かもしれません。このフィクスチャは、「凍結」の時間を可能にして、あなたのテスト内の意志で前後に移動:

def test_timesensitive(freeze): 
    freeze.freeze(2015, 1, 1) 
    foo.prepare() # Uses datetime.now() to prepare its state 
    freeze.delta(days=2) 
    # Does something that takes in consideration that 2 days have passed 
    # i.e. datetime.now() returns a date 2 days in the future 
    foo.do_something() 
    assert foo.result == expected_result_after_2_days 
11

freezegun moduleがあります:

from datetime import datetime 
from freezegun import freeze_time # $ pip install freezegun 

@freeze_time("Jan 14th, 2012") 
def test_nice_datetime(): 
    assert datetime.now() == datetime(2012, 1, 14) 

freeze_time()は、コンテキストマネージャとして使用することができます。モジュールは、ローカルタイムゾーンUTCオフセットを指定します。同じように使用

import datetime as dt 

@contextmanager 
def mocked_now(now): 
    class MockedDatetime(dt.datetime): 
     @classmethod 
     def now(cls): 
      return now 

    with patch("datetime.datetime", MockedDatetime): 
     yield 

::他の回答から適応

1

def test_now(): 
    with mocked_now(dt.datetime(2017, 10, 21)): 
     assert dt.datetime.now() == dt.datetime(2017, 10, 21) 
+0

ここで 'patch'が来ましたから?あなたは輸入を逃しましたか? – sashk

関連する問題