Skip to content
This repository was archived by the owner on Sep 1, 2024. It is now read-only.

Commit 7108cf2

Browse files
committed
Add freezegun test
A user reported an issue in which freezegun (specifically, the `@freeze_time()` decorator) was impacting the test start and end timestamps reported to Unflakable. It turns out that this issue was fixed in freezegun 1.2.2. This change adds a new test case and checks timestamp consistency for every test case.
1 parent 71f5edc commit 7108cf2

File tree

3 files changed

+86
-0
lines changed

3 files changed

+86
-0
lines changed

setup.cfg

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ install_requires =
4343

4444
[options.extras_require]
4545
dev =
46+
# freezegun 1.2.2 fixed pytest timing interference.
47+
freezegun>=1.2.2
4648
requests-mock[fixture]
4749

4850
[options.entry_points]

tests/common.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import os
99
import re
1010
import subprocess
11+
import time
12+
from datetime import datetime, timezone
1113
from enum import Enum
1214
from pathlib import Path
1315
from typing import (TYPE_CHECKING, Callable, Dict, Iterable, List, Optional,
@@ -404,6 +406,8 @@ def run_test_case(
404406
) + list(extra_args)
405407
)
406408

409+
start_time = datetime.fromtimestamp(time.time(), timezone.utc).isoformat('T', 'microseconds')
410+
407411
__pytest_current_test = os.environ['PYTEST_CURRENT_TEST']
408412
if monkeypatch is not None:
409413
with monkeypatch.context() as mp:
@@ -414,6 +418,10 @@ def run_test_case(
414418
else:
415419
result = pytester.runpytest(*pytest_args)
416420

421+
end_time = datetime.fromtimestamp(time.time(), timezone.utc).isoformat('T', 'microseconds')
422+
423+
assert end_time >= start_time
424+
417425
# pytester clears PYTEST_CURRENT_TEST for some reason.
418426
os.environ['PYTEST_CURRENT_TEST'] = __pytest_current_test
419427

@@ -649,7 +657,12 @@ def run_test_case(
649657
)
650658

651659
assert_regex(TIMESTAMP_REGEX, upload_body['start_time'])
660+
assert upload_body['start_time'] >= start_time
661+
652662
assert_regex(TIMESTAMP_REGEX, upload_body['end_time'])
663+
assert upload_body['end_time'] <= end_time
664+
665+
assert upload_body['end_time'] >= upload_body['start_time']
653666

654667
actual_test_runs = {
655668
(test_run_record['filename'], tuple(test_run_record['name'])): [
@@ -659,6 +672,23 @@ def run_test_case(
659672
}
660673
assert actual_test_runs == expected_uploaded_test_runs
661674

675+
for test_run_record in upload_body['test_runs']:
676+
for attempt in test_run_record['attempts']:
677+
attempt_start_time = attempt['start_time']
678+
assert isinstance(attempt_start_time, str)
679+
assert_regex(TIMESTAMP_REGEX, attempt_start_time)
680+
# Check for timestamp interference (e.g., from freezetime).
681+
assert attempt_start_time >= start_time
682+
683+
attempt_end_time = attempt['end_time']
684+
assert isinstance(attempt_end_time, str)
685+
assert_regex(TIMESTAMP_REGEX, attempt_end_time)
686+
assert attempt_end_time <= end_time
687+
688+
assert attempt_end_time >= attempt_start_time
689+
690+
assert isinstance(attempt['duration_ms'], int)
691+
662692
# Make sure there aren't any duplicate test keys.
663693
assert len(upload_body['test_runs']) == len(actual_test_runs)
664694

tests/test_unflakable.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2255,3 +2255,57 @@ def test_pass():
22552255
extra_args=XDIST_ARGS if xdist else [],
22562256
failed_upload_requests=1,
22572257
)
2258+
2259+
2260+
@pytest.mark.parametrize(TEST_PARAMS_VERBOSE_XDIST_ARG_NAMES,
2261+
TEST_PARAMS_VERBOSE_XDIST_ARG_VALUES)
2262+
def test_freeze_time(
2263+
pytester: pytest.Pytester,
2264+
subprocess_mock: GitMock,
2265+
verbose: bool,
2266+
xdist: bool,
2267+
) -> None:
2268+
pytester.makepyfile(test_input="""
2269+
from freezegun import freeze_time
2270+
import unittest
2271+
2272+
@freeze_time("2023-02-04")
2273+
class FrozenTimeTests(unittest.TestCase):
2274+
@freeze_time("2024-01-01")
2275+
def test_pass(self):
2276+
pass
2277+
2278+
@freeze_time("2024-01-02")
2279+
def test_pass2(self):
2280+
pass
2281+
2282+
@freeze_time("2024-01-03")
2283+
def test_pass3(self):
2284+
pass
2285+
""")
2286+
2287+
subprocess_mock.update(branch=None, commit=None)
2288+
2289+
run_test_case(
2290+
pytester,
2291+
manifest={'quarantined_tests': []},
2292+
expected_test_file_outcomes=[
2293+
('test_input.py', [
2294+
(('FrozenTimeTests', 'test_pass'), [_TestAttemptOutcome.PASSED]),
2295+
(('FrozenTimeTests', 'test_pass2'), [_TestAttemptOutcome.PASSED]),
2296+
(('FrozenTimeTests', 'test_pass3'), [_TestAttemptOutcome.PASSED]),
2297+
])
2298+
],
2299+
expected_test_result_counts=_TestResultCounts(num_passed=3),
2300+
expected_uploaded_test_runs={
2301+
('test_input.py', ('FrozenTimeTests', 'test_pass')): ['pass'],
2302+
('test_input.py', ('FrozenTimeTests', 'test_pass2')): ['pass'],
2303+
('test_input.py', ('FrozenTimeTests', 'test_pass3')): ['pass'],
2304+
},
2305+
expected_exit_code=ExitCode.OK,
2306+
expected_branch=None,
2307+
expected_commit=None,
2308+
expect_xdist=xdist,
2309+
extra_args=XDIST_ARGS if xdist else [],
2310+
verbose=verbose,
2311+
)

0 commit comments

Comments
 (0)