Ho bisogno di testare funzioni che utilizzano datetime.datetime.now()
. Qual è il modo più semplice per farlo?Come monkeypatch python's datetime.datetime.now con py.test?
risposta
È necessario eseguire il monkeypatch della funzione datetime.now. Nell'esempio qui di seguito, sto creando apparecchio che posso riutilizzare successivamente in altri test:
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
Questo è il dispositivo che uso per superiori ora(), ma mantenendo il resto del datetime di lavoro (RE: la domanda di Satoru).
Non viene testato estesamente, ma risolve i problemi in cui viene utilizzato datetime in altri contesti. Per me è stato importante mantenere il Django ORM lavorando con questi valori datetime (in particolare 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
Forse fuori tema, ma potrebbe tornare utile ad altre persone che arrivano a questa domanda. Questo dispositivo permette di "congelare" il tempo, e poi si spostano avanti e indietro a piacimento entro i test:
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
C'è 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()
potrebbe essere utilizzato anche come un contesto manager. Il supporto del modulo che specifica l'offset UTC del fuso orario locale.
Adattato dalle altre risposte:
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
Usato come:
def test_now():
with mocked_now(dt.datetime(2017, 10, 21)):
assert dt.datetime.now() == dt.datetime(2017, 10, 21)
Dove 'patch' è venuto a partire dal? Hai perso un'importazione? – sashk
- 1. Come monkeypatch builtin function datetime.datetime.now?
- 2. Mocking con Flexmock datetime.datetime.now
- 3. RICERCA PRIMA/DOPO con Pythons imaplib
- 4. Timezone.now() vs datetime.datetime.now()
- 5. Come utilizzare più core con py.test?
- 6. Come velocizzare py.test
- 7. py.test con Python2 e Python3
- 8. Esecuzione py.test con Xvfb conduzione
- 9. django 1.4 timezone.now (vs) datetime.datetime.now()
- 10. Pytest monkeypatch non funziona sulla funzione importata
- 11. È possibile sostituire (monkeypatch) le funzioni PHP?
- 12. py.test test parametrizing classes
- 13. Come combinare gli impianti py.test con Flask-SQLAlchemy e PostgreSQL?
- 14. Progetti che utilizzano py.test
- 15. py.test con test non python (in particolare, con cxxtest)
- 16. Come disabilitare un test usando py.test?
- 17. Come mostrare gli avvisi in py.test
- 18. Come e dove py.test trova i fari
- 19. registrazione all'interno di test py.test
- 20. Esiste un equivalente dell'intervallo Pythons (12) in C#?
- 21. generando py.test test in python
- 22. Utilizzando py.test con una copertura non include le importazioni
- 23. determinazione della copertura di prova con py.test + gevent
- 24. Pythons modo più veloce di caso casualità di una stringa
- 25. can py.test supporta più opzioni -k?
- 26. Come eseguire py.test contro diverse versioni di python?
- 27. Eseguire py.test in un contenitore mobile come servizio
- 28. Come configurare PyCharm per eseguire py.test con le opzioni della riga di comando come -s?
- 29. Django py.test non trova il modulo impostazioni
- 30. Come testare la funzione viene chiamata con gli argomenti corretti con pytest?
E 'possibile sostituire solo il metodo 'now'? – satoru
Funziona, ma non se lo si fa "da datetime import datetime". Dai un'occhiata qui per detais: http://stackoverflow.com/questions/35431476/why-pythons-monkeypatch-doesnt-work-when-importing-a-class-instead-of-a-module – rgargente