11from collections .abc import Generator
2+ from typing import Any
23
34import pytest
45import requests
56
67from 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