freezegun icon indicating copy to clipboard operation
freezegun copied to clipboard

Datetime and Time packages do not have the same behavior when being frozen

Open folkvir opened this issue 2 years ago • 4 comments

Hello! A few days ago a bug occured and we discover that the time were not frozen correctly in our tests. We reported the issue in pytest-freezer (https://github.com/pytest-dev/pytest-freezer/issues/14) but after deeper investigations it seems that the function _should_use_real_time reports that we should use realtime when it should'nt. When using the 2 additional ignore elements freezegun.configure("_pytest.runner", "_pytest.terminal") (which are added to mitigate the bug on the pytest --durations option) time functions return real time in teardown fixtures while datetime functions return correct mocked time. @wimglenn tracked this here https://github.com/pytest-dev/pytest-freezer/issues/14#issuecomment-1975007416 More precisely; the guilty ignore option is _pytest.runner. I see 3 possibilities (maybe more?):

  • Fix the _should_use_real_time; don't know if it is the right solution
  • Or try to deeply identity which element in the _pytest.runner package we need to ignore; to work with the current code without breaking the --durations option.
  • Use a plain Fake object for the time package; just like the datetime package

folkvir avatar Mar 04 '24 09:03 folkvir

Hi @folkvir! I created a standalone test case in #537 - if I'm understanding the problem correctly, that demonstrates the fact that there is indeed a bug here.

I think the appropriate fix is to extend all FakeDatetime methods to use should_use_real_time, but I don't have a lot of time to look into this - so PR's are welcome.

bblommers avatar Mar 17 '24 20:03 bblommers

I'll try to look into it and create a pull request as soon as possible but I don't have a lot of time to spend outside my family and job. So if someone has more free time then go!

folkvir avatar Mar 18 '24 14:03 folkvir

@bblommers Ok after investigations I found calling print(_should_use_real_time()) in the beginning of FakeDatetime.now return "False" because the module name returned by: frame.f_globals.get('__name__') is never listed in ignore_lists[-1]. The ignore_list[-1] is ('tests.another_module', 'nose.plugins', 'six.moves', 'django.utils.six.moves', 'google.gax', 'threading', 'multiprocessing', 'queue', 'selenium', '_pytest.terminal.', '_pytest.runner.', 'gi', 'prompt_toolkit') but the module_name(s) are just:

freezegun.api
tests.test_configure
_pytest.python
pluggy._callers
pluggy._manager

Increasing the call_stack_inspection_limit does not change anything. So even if we patch FakeDateTime.now with a usage of _should_use_real_time then we won't get the real_time because the function always return false!

folkvir avatar Mar 18 '24 15:03 folkvir

Update: I think I found the core of the bug; but it may be an artefact of the test setup because we locally import the another_module module. The bug should be reproductible if you comment my changes in freezegun.api. Changes: https://github.com/spulec/freezegun/compare/master...folkvir:freezegun:bug/ignore-fakedatetime-bug

folkvir avatar Mar 26 '24 00:03 folkvir