I am having a function with the a default value of a param as datetime.now()
. method is something like below,
def as_standard_format(p_date=datetime.now(), fmt=sdk_constants.DEFAULT_DATE_TIME_FORMAT):
return p_date.strftime(fmt)
And I am having a test method something like below,
@freeze_time(datetime(year=2018, month=9, day=25, hour=15, minute=46, second=36))
def testNowWithDefaultFormat(self):
# The below method gives the frozen time
print(datetime.now())
# But the below test fails
assert utils.format_date(
datetime.now()) == "20180925T154636Z", "Default call not giving current time in " \
"standard format \"%Y%m%dT%H%M%SZ\""
Why is the freeze_time
not working with default param value?
You're being victim of a common gotcha in Python related to mutable default value parameters and not specific only to freeze_time
.
For the explanation, consider the following code:
import time from datetime import datetime
def what_time_is_it(p_date=datetime.now()):
return p_date.strftime('"%Y-%m-%d %X"')
if __name__ == '__main__':
print(what_time_is_it())
time.sleep(10)
print(what_time_is_it())
"2019-02-28 13:47:24"
"2019-02-28 13:47:34" # This line showing a datetime 10 seconds after the first one
A new datetime.now()
is called on every call to what_time_is_it()
"2019-02-28 13:47:24"
"2019-02-28 13:47:24" # EXACTLY the same time in both lines!
A new datetime.now()
is created once when the function is defined, and the same value is used in each successive call.
Create a new object each time the function is called, by using a default arg to signal that no argument was provided (None is often a good choice):
def as_standard_format(p_date=None, fmt=sdk_constants.DEFAULT_DATE_TIME_FORMAT):
if p_date is None:
return datetime.now().strftime(fmt)
else:
return p_date.strftime(fmt)