Skip to content

Commit 822429b

Browse files
committed
chore: unleash integration test stability issues
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
1 parent 7e18bc1 commit 822429b

File tree

1 file changed

+68
-2
lines changed

1 file changed

+68
-2
lines changed

providers/openfeature-provider-unleash/tests/test_integration.py

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,46 @@ def enable_flag(flag_name: str, headers: dict):
255255
logger.error(f"Error enabling flag '{flag_name}': {e}")
256256

257257

258+
EXPECTED_FLAGS = {
259+
"integration-boolean-flag",
260+
"integration-string-flag",
261+
"integration-float-flag",
262+
"integration-object-flag",
263+
"integration-integer-flag",
264+
"integration-targeting-flag",
265+
}
266+
267+
268+
def wait_for_flags_visible(timeout=30, interval=2):
269+
"""Poll the client features endpoint until all expected flags are visible.
270+
271+
After flags are created via the Admin API, there is a short propagation
272+
delay before they appear on the Client API. Without this wait the
273+
provider's initial fetch may return stale data, causing flaky tests.
274+
"""
275+
headers = {"Authorization": API_TOKEN}
276+
start = time.time()
277+
while time.time() - start < timeout:
278+
try:
279+
resp = requests.get(
280+
f"{UNLEASH_URL}/api/client/features",
281+
headers=headers,
282+
timeout=5,
283+
)
284+
if resp.status_code == 200:
285+
names = {f["name"] for f in resp.json().get("features", [])}
286+
if EXPECTED_FLAGS.issubset(names):
287+
logger.info("All flags visible via client API")
288+
return
289+
logger.info(
290+
f"Waiting for flags; have {len(names)}/{len(EXPECTED_FLAGS)}"
291+
)
292+
except Exception as e:
293+
logger.warning(f"Polling client features: {e}")
294+
time.sleep(interval)
295+
raise TimeoutError(f"Flags not visible via client API within {timeout}s")
296+
297+
258298
@pytest.fixture(scope="session")
259299
def postgres_container():
260300
"""Create and start PostgreSQL container."""
@@ -291,7 +331,7 @@ def unleash_container(postgres_container): # noqa: PLR0915
291331

292332
# Wait for health check to pass
293333
logger.info("Waiting for Unleash container to be healthy...")
294-
max_wait_time = 60 # 1 minute max wait
334+
max_wait_time = 120 # 2 minutes; Unleash DB migrations can be slow in CI
295335
start_time = time.time()
296336

297337
while time.time() - start_time < max_wait_time:
@@ -301,6 +341,16 @@ def unleash_container(postgres_container): # noqa: PLR0915
301341
unleash_url = f"http://localhost:{exposed_port}"
302342
logger.info(f"Trying health check at: {unleash_url}")
303343
except Exception as port_error:
344+
# if the container exited, fail fast with its logs
345+
docker_container = container.get_wrapped_container()
346+
if docker_container:
347+
docker_container.reload()
348+
if docker_container.status in ("exited", "dead"):
349+
logs = docker_container.logs().decode(errors="replace")
350+
raise RuntimeError(
351+
f"Unleash container died ({docker_container.status}).\n"
352+
f"Logs:\n{logs}"
353+
) from port_error
304354
logger.error(f"Port not ready yet: {port_error}")
305355
time.sleep(2)
306356
continue
@@ -313,10 +363,24 @@ def unleash_container(postgres_container): # noqa: PLR0915
313363
logger.error(f"Health check failed, status: {response.status_code}")
314364
time.sleep(2)
315365

366+
except RuntimeError:
367+
raise
316368
except Exception as e:
317369
logger.error(f"Health check error: {e}")
318370
time.sleep(2)
319371
else:
372+
# timeout; dump container logs for debugging
373+
try:
374+
docker_container = container.get_wrapped_container()
375+
if docker_container:
376+
docker_container.reload()
377+
logs = docker_container.logs().decode(errors="replace")
378+
logger.error(
379+
f"Unleash container status: {docker_container.status}\n"
380+
f"Logs:\n{logs}"
381+
)
382+
except Exception:
383+
pass
320384
raise Exception("Unleash container did not become healthy within timeout")
321385

322386
# Get the exposed port and set global URL
@@ -331,9 +395,11 @@ def unleash_container(postgres_container): # noqa: PLR0915
331395

332396
@pytest.fixture(scope="session", autouse=True)
333397
def setup_test_flags(unleash_container):
334-
"""Setup test flags before running any tests."""
398+
"""Setup test flags and wait for them to be visible via the client API."""
335399
logger.info("Creating test flags in Unleash...")
336400
create_test_flags()
401+
logger.info("Waiting for flags to propagate to client API...")
402+
wait_for_flags_visible()
337403
logger.info("Test flags setup completed")
338404

339405

0 commit comments

Comments
 (0)