5

I am writing an application which makes use of the current time (via datetime.datetime.now())

Is there a way, for debugging purposes, to override this call so that it returns a specific timestamp?

As a fallback I could write a function which would be called instead of datetime.datetime.now() and return whatever is needed (the actual current time in producton and the required test time when debugging) but there may be a more pythonic way to perform these kind of actions?

WoJ
  • 27,165
  • 48
  • 180
  • 345
  • You can always create your own timestamp, with `datetime.datetime(year, month, day, hour, minute, second)`, is this what you need? – Burhan Khalid Jun 29 '14 at 07:29
  • @BurhanKhalid: no. I mentioned in my question that I can write a function which replaces `datetime.datetime.now()` and returns whatever is needed. But I want to keep `datetime.datetime.now()` in the code and override it elsewhere in the code. – WoJ Jun 29 '14 at 07:32
  • @WoJ alternatively, change your design to not call `now()` within your functions/methods, and have the caller responsible for passing the time. This essentially uses a core idea from functional programming - [there is even an article about functional programming](https://docs.python.org/2/howto/functional.html) on the Python site. This is mostly the reason: "Functions don’t depend on system state that needs to be replicated before running a test; instead you only have to synthesize the right input and then check that the output matches expectations." – metatoaster Jun 29 '14 at 07:48

2 Answers2

7

Broadly, your options are:

  • Use the unittest.mock library, which can replace the function on the fly with a dummy function that always gives the same results (or use another mocking library that does the same thing). This means you don't have to modify your function; however, reasonable people can disagree on whether monkey patching with mock is good practice, even for debugging. I think this is the most widely used solution to this problem in Python.
  • Modify your function to do something different depending on its environment (the actual environment variables on your system, or global state, or something else). This is the easiest way, but also the crudest and most fragile way, so you'll have to be sure to change it back after your debugging is finished.
  • Modify your function to accept a function itself as a parameter, and pass in datetime.datetime.now as that function in normal operation, but pass in something different (for instance a stub) for testing.
Andrew Gorcester
  • 19,595
  • 7
  • 57
  • 73
  • I opted for a version of the 3rd option (passing the value `datetime.datetime.now()` instead of the function itself) and stumbled upon this behavior: https://stackoverflow.com/q/52511405 The answer there is good, just wanted to post here in case anyone else tries the same thing. – victorlin May 18 '22 at 18:33
1

You can use the mock library to mock the datetime.datetime.now() usage:

import mock

def my_test():
    my_mock = mock.Mock(return_value=your_desired_timestamp)

    with mock.patch('mymodule.datetime.datetime.now', my_mock):
        # Here, all calls to `datetime.datetime.now` referenced by `datetime.datetime`
        # defined in `my_module` will be mocked to return `your_desired_timestamp`.
Maciej Gol
  • 15,394
  • 4
  • 33
  • 51