Skip to content

Commit a6236a2

Browse files
committed
fix: Replace remaining manual server polling with wait_for_server helper
This change completes the work started in PR #1527 by fixing the remaining test fixtures that were still using manual socket polling loops to wait for server startup. ## Changes Fixed 4 test fixtures that were missed in the previous PR: - tests/server/fastmcp/test_integration.py: server_transport fixture - tests/client/test_notification_response.py: non_sdk_server fixture - tests/client/test_http_unicode.py: running_unicode_server fixture - tests/shared/test_sse.py: mounted_server and context_server fixtures All now use the centralized wait_for_server() helper which: - Actively polls for TCP connection readiness - Returns immediately when server is ready - Has clear timeout behavior (5s default) - Eliminates race conditions from arbitrary sleeps ## Impact - Removes 49 lines of duplicate manual polling code - Makes tests more deterministic and reliable - Reduces wasted time from fixed delays (tests return as soon as ready) - Follows the patterns documented in FLAKY_TESTS.md
1 parent c44e68f commit a6236a2

File tree

4 files changed

+12
-61
lines changed

4 files changed

+12
-61
lines changed

tests/client/test_http_unicode.py

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77

88
import multiprocessing
99
import socket
10-
import time
1110
from collections.abc import Generator
1211

1312
import pytest
1413

1514
from mcp.client.session import ClientSession
1615
from mcp.client.streamable_http import streamablehttp_client
16+
from tests.test_helpers import wait_for_server
1717

1818
# Test constants with various Unicode characters
1919
UNICODE_TEST_STRINGS = {
@@ -158,19 +158,8 @@ def running_unicode_server(unicode_server_port: int) -> Generator[str, None, Non
158158
proc = multiprocessing.Process(target=run_unicode_server, kwargs={"port": unicode_server_port}, daemon=True)
159159
proc.start()
160160

161-
# Wait for server to be running
162-
max_attempts = 20
163-
attempt = 0
164-
while attempt < max_attempts:
165-
try:
166-
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
167-
s.connect(("127.0.0.1", unicode_server_port))
168-
break
169-
except ConnectionRefusedError:
170-
time.sleep(0.1)
171-
attempt += 1
172-
else:
173-
raise RuntimeError(f"Server failed to start after {max_attempts} attempts")
161+
# Wait for server to be ready
162+
wait_for_server(unicode_server_port)
174163

175164
try:
176165
yield f"http://127.0.0.1:{unicode_server_port}"

tests/client/test_notification_response.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import json
99
import multiprocessing
1010
import socket
11-
import time
1211
from collections.abc import Generator
1312

1413
import pytest
@@ -22,6 +21,7 @@
2221
from mcp.client.streamable_http import streamablehttp_client
2322
from mcp.shared.session import RequestResponder
2423
from mcp.types import ClientNotification, RootsListChangedNotification
24+
from tests.test_helpers import wait_for_server
2525

2626

2727
def create_non_sdk_server_app() -> Starlette:
@@ -95,14 +95,9 @@ def non_sdk_server(non_sdk_server_port: int) -> Generator[None, None, None]:
9595
proc.start()
9696

9797
# Wait for server to be ready
98-
start_time = time.time()
99-
while time.time() - start_time < 10:
100-
try:
101-
with socket.create_connection(("127.0.0.1", non_sdk_server_port), timeout=0.1):
102-
break
103-
except (TimeoutError, ConnectionRefusedError):
104-
time.sleep(0.1)
105-
else:
98+
try:
99+
wait_for_server(non_sdk_server_port, timeout=10.0)
100+
except TimeoutError:
106101
proc.kill()
107102
proc.join(timeout=2)
108103
pytest.fail("Server failed to start within 10 seconds")

tests/server/fastmcp/test_integration.py

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
import json
1414
import multiprocessing
1515
import socket
16-
import time
1716
from collections.abc import Generator
1817

1918
import pytest
@@ -60,6 +59,7 @@
6059
TextResourceContents,
6160
ToolListChangedNotification,
6261
)
62+
from tests.test_helpers import wait_for_server
6363

6464

6565
class NotificationCollector:
@@ -160,19 +160,8 @@ def server_transport(request: pytest.FixtureRequest, server_port: int) -> Genera
160160
)
161161
proc.start()
162162

163-
# Wait for server to be running
164-
max_attempts = 20
165-
attempt = 0
166-
while attempt < max_attempts:
167-
try:
168-
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
169-
s.connect(("127.0.0.1", server_port))
170-
break
171-
except ConnectionRefusedError:
172-
time.sleep(0.1)
173-
attempt += 1
174-
else:
175-
raise RuntimeError(f"Server failed to start after {max_attempts} attempts")
163+
# Wait for server to be ready
164+
wait_for_server(server_port)
176165

177166
yield transport
178167

tests/shared/test_sse.py

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -252,19 +252,8 @@ def mounted_server(server_port: int) -> Generator[None, None, None]:
252252
proc.start()
253253

254254
# Wait for server to be running
255-
max_attempts = 20
256-
attempt = 0
257255
print("waiting for server to start")
258-
while attempt < max_attempts:
259-
try:
260-
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
261-
s.connect(("127.0.0.1", server_port))
262-
break
263-
except ConnectionRefusedError:
264-
time.sleep(0.1)
265-
attempt += 1
266-
else:
267-
raise RuntimeError(f"Server failed to start after {max_attempts} attempts")
256+
wait_for_server(server_port)
268257

269258
yield
270259

@@ -367,19 +356,8 @@ def context_server(server_port: int) -> Generator[None, None, None]:
367356
proc.start()
368357

369358
# Wait for server to be running
370-
max_attempts = 20
371-
attempt = 0
372359
print("waiting for context server to start")
373-
while attempt < max_attempts:
374-
try:
375-
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
376-
s.connect(("127.0.0.1", server_port))
377-
break
378-
except ConnectionRefusedError:
379-
time.sleep(0.1)
380-
attempt += 1
381-
else:
382-
raise RuntimeError(f"Context server failed to start after {max_attempts} attempts")
360+
wait_for_server(server_port)
383361

384362
yield
385363

0 commit comments

Comments
 (0)