pytest
pytest copied to clipboard
datetime and timedelta suport for approx
this is to follow up after a initial proposal by @brianmaissy in #4760 and #4736
key issues to decide on/highlight
- [ ] new internal helper classes for date times and time deltas
- [ ] meaning of relative for time-deltas
- [ ] decision on whether timestamps can have a meaningful rel at all ( i currently lean on no)
- [ ] documentation of the explicit requirements for declaring approximate date-times in nested structures (no implication as we don't have sane defaults for abs/rel)
FWIW, this is what I'm currently using:
class approx_datetime(ApproxBase):
"""
Perform approximate comparisons where the expected value is a datetime or timedelta.
"""
def __init__(self, expected, abs: timedelta = timedelta(seconds=10)):
if abs < timedelta(0):
raise ValueError(f"absolute tolerance can't be negative: {abs}")
super().__init__(expected, abs=abs)
def __repr__(self):
return f"approx_datetime({self.expected!r} \u00b1 {self.abs!r})"
def __eq__(self, actual):
return abs(self.expected - actual) <= self.abs
Thanks for the reference, thats a good start point
Would love to see this feature added!
Is there any way to get the time that the current test was started from pytest? Most of the time when I'm doing these approx date comparisons, it's when the result of a test might be out by the length of time that something in the test took to run. If you could say assert abs(expected - actual) <= time_this_test_has_been_running that would catch most of my use cases without having to concoct a sensible default tolerance... :woman_shrugging:
Came to me as I was bumbling around the task myself, so thought I would capture here as part of the discussion. Great library :raised_hands:
@bentilley one way to do that would be to create a function-scoped fixture which returns the current time. The fixture will be initialized with the current time immediately before each test runs:
@pytest.fixture
def test_start_time():
return datetime.now()
def test_my_stuff(test_start_time):
....
@brianmaissy That is a great shout 🙏 thank you
Supporting approx for datetime and timedelta sounds very interesting. Any idea why it is not already merged? Is there technical issues?
Oups, i though it was a PR, not an issue.
BTW, i don't know if it is useful, but this can be reduced as float comparison:
epsilon = datetime.timedelta(seconds=2)
now = datetime.datetime.now()
assert mydate.timestamp() == pytest.approx(now.timestamp(), abs=epsilon.total_seconds())
Just FYI, a related helper I've been using:
import time, pytest
def approx_now(abs=10):
"""Pytest based checker for whether a unix epoch/timestamp is approximately 'now' (within some tolerance)."""
return pytest.approx(time.time(), abs=abs)
def test_something():
# ....
assert metadata == {"status": "running", "timestamp": approx_now()}
This is still a very much needed feature, is there any news on this ?