Dependency injection is another way to do it - just passing in something that gives you the time (e.g. a function).
Here are some example tests:
import datetime
from greeter import greet
def test_it_returns_good_morning_before_12():
def get_time():
return datetime.datetime(2024, 12, 8, hour=5, minute=0, second=0)
greeting = greet(get_time)
assert greeting == "Good morning!"
def test_it_returns_good_afternoon_after_12():
def get_time():
return datetime.datetime(2024, 12, 8, hour=14, minute=0, second=0)
greeting = greet(get_time)
assert greeting == "Good afternoon!"
The greet
function then calls the function it is passed to obtain the time:
def greet(get_time):
hour = get_time().hour
if hour < 12:
return "Good morning!"
else:
return "Good afternoon!"
In the production code where I need to use greet
, I'd simply pass the function that provides the system time:
greeting = greet(datetime.datetime.now)
I did write a tutorial about this over on python-forum: https://python-forum.io/thread-38222.html. That does include a link to a repo on GitHub with a more complete example (https://github.com/ndc85430/controlling-date-and-time-in-tests).