Skip to content

Commit 96bbe19

Browse files
HayaoSuzukicsernazs
authored andcommitted
Fix HTTPServer.start() and add tests
1 parent b937308 commit 96bbe19

File tree

2 files changed

+106
-3
lines changed

2 files changed

+106
-3
lines changed

pytest_httpserver/httpserver.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -982,10 +982,13 @@ def __init__(
982982
self._readiness_check_pending = False
983983

984984
def start(self) -> None:
985-
self._readiness_check_pending = self.startup_timeout is not None
986-
987985
super().start()
988-
self.wait_for_server_ready()
986+
self._readiness_check_pending = self.startup_timeout is not None
987+
try:
988+
self.wait_for_server_ready()
989+
except Exception:
990+
self.stop()
991+
raise
989992

990993
def wait_for_server_ready(self) -> None:
991994
"""

tests/test_readiness.py

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
from collections.abc import Generator
2+
from typing import Any
23

34
import pytest
45
import requests
56

67
from pytest_httpserver.httpserver import HTTPServer
8+
from pytest_httpserver.httpserver import HTTPServerError
79

810

911
@pytest.fixture
@@ -22,3 +24,101 @@ def test_httpserver_readiness(httpserver: HTTPServer):
2224
resp = requests.get(httpserver.url_for("/"))
2325
assert resp.status_code == 200
2426
assert resp.text == "Hello, world!"
27+
28+
29+
class RecordingHTTPServer(HTTPServer):
30+
"""HTTPServer subclass that records wait_for_server_ready() calls."""
31+
32+
def __init__(self, **kwargs: Any) -> None:
33+
super().__init__(**kwargs)
34+
self.wait_for_ready_call_count = 0
35+
self.readiness_pending_before_wait: list[bool] = []
36+
self.readiness_pending_after_wait: list[bool] = []
37+
38+
def wait_for_server_ready(self) -> None:
39+
self.wait_for_ready_call_count += 1
40+
self.readiness_pending_before_wait.append(self._readiness_check_pending)
41+
super().wait_for_server_ready()
42+
self.readiness_pending_after_wait.append(self._readiness_check_pending)
43+
44+
45+
@pytest.fixture
46+
def recording_server_with_timeout() -> Generator[RecordingHTTPServer]:
47+
with RecordingHTTPServer(startup_timeout=10) as server:
48+
yield server
49+
50+
51+
@pytest.fixture
52+
def recording_server_without_timeout() -> Generator[RecordingHTTPServer]:
53+
with RecordingHTTPServer() as server:
54+
yield server
55+
56+
57+
def test_wait_for_server_ready_called_with_timeout(
58+
recording_server_with_timeout: RecordingHTTPServer,
59+
) -> None:
60+
assert recording_server_with_timeout.wait_for_ready_call_count == 1
61+
assert recording_server_with_timeout.readiness_pending_before_wait == [True]
62+
assert recording_server_with_timeout.readiness_pending_after_wait == [False]
63+
64+
65+
def test_wait_for_server_ready_called_without_timeout(
66+
recording_server_without_timeout: RecordingHTTPServer,
67+
) -> None:
68+
assert recording_server_without_timeout.wait_for_ready_call_count == 1
69+
assert recording_server_without_timeout.readiness_pending_before_wait == [False]
70+
assert recording_server_without_timeout.readiness_pending_after_wait == [False]
71+
72+
73+
def test_wait_for_server_ready_called_each_start_stop_cycle() -> None:
74+
server = RecordingHTTPServer(startup_timeout=5)
75+
try:
76+
for i in range(3):
77+
server.start()
78+
assert server.wait_for_ready_call_count == i + 1
79+
server.clear()
80+
server.stop()
81+
finally:
82+
if server.is_running():
83+
server.clear()
84+
server.stop()
85+
86+
assert server.readiness_pending_before_wait == [True, True, True]
87+
assert server.readiness_pending_after_wait == [False, False, False]
88+
89+
90+
def test_double_start_does_not_poison_readiness_flag() -> None:
91+
server = HTTPServer(startup_timeout=5)
92+
server.start()
93+
try:
94+
with pytest.raises(HTTPServerError, match="already running"):
95+
server.start()
96+
97+
assert server._readiness_check_pending is False # noqa: SLF001
98+
99+
server.expect_request("/test").respond_with_data("normal response")
100+
resp = requests.get(server.url_for("/test"))
101+
assert resp.status_code == 200
102+
assert resp.text == "normal response"
103+
finally:
104+
server.clear()
105+
if server.is_running():
106+
server.stop()
107+
108+
109+
class FailingReadinessServer(HTTPServer):
110+
"""HTTPServer subclass whose readiness check always fails."""
111+
112+
def __init__(self, **kwargs: Any) -> None:
113+
super().__init__(**kwargs)
114+
115+
def wait_for_server_ready(self) -> None:
116+
raise HTTPServerError("Simulated readiness failure")
117+
118+
119+
def test_readiness_failure_stops_server() -> None:
120+
server = FailingReadinessServer(startup_timeout=5)
121+
with pytest.raises(HTTPServerError, match="Simulated readiness failure"):
122+
server.start()
123+
124+
assert not server.is_running()

0 commit comments

Comments
 (0)