From 6d50cb03ea8e19b8fc9ae6816a8f893979ae03d4 Mon Sep 17 00:00:00 2001 From: Andy Staples Date: Wed, 29 Jul 2026 12:15:17 -0600 Subject: [PATCH] Stabilize Azure Functions E2E tests Keep history export output outside the watched Function app and quarantine Azurite-dependent delayed visibility tests. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: cb2d68a5-0184-45af-bb9c-4def2afe8e8a --- tests/azure-functions-durable/e2e/_markers.py | 14 ++++++++++++++ .../e2e/apps/dtask_style/history_export_routes.py | 11 +++++++---- .../e2e/test_dtask_entities_advanced_e2e.py | 4 ++++ .../e2e/test_dtask_patterns_e2e.py | 3 +++ .../e2e/test_dtask_scheduled_e2e.py | 7 ++++++- .../e2e/test_v1_patterns_e2e.py | 3 +++ 6 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 tests/azure-functions-durable/e2e/_markers.py diff --git a/tests/azure-functions-durable/e2e/_markers.py b/tests/azure-functions-durable/e2e/_markers.py new file mode 100644 index 00000000..0835c457 --- /dev/null +++ b/tests/azure-functions-durable/e2e/_markers.py @@ -0,0 +1,14 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +"""Shared markers for the Azure Functions Durable E2E suite.""" + +import pytest + + +azurite_delayed_visibility = pytest.mark.skip( + reason=( + "Azurite intermittently fails to return queue messages after an initial " + "visibility delay; see https://github.com/Azure/Azurite/issues/2343." + ), +) diff --git a/tests/azure-functions-durable/e2e/apps/dtask_style/history_export_routes.py b/tests/azure-functions-durable/e2e/apps/dtask_style/history_export_routes.py index 6e324877..eeedd316 100644 --- a/tests/azure-functions-durable/e2e/apps/dtask_style/history_export_routes.py +++ b/tests/azure-functions-durable/e2e/apps/dtask_style/history_export_routes.py @@ -14,10 +14,11 @@ ``configure_history_export`` time, so this route no longer binds a process-wide context. The route only builds an ``ExportHistoryClient`` for the job-management surface (create / get job). A local-filesystem writer sends exported history to -``/_export_output`` where the test can read it back. +a temporary directory outside the function app where the test can read it back. """ import json +import tempfile from collections.abc import Mapping from datetime import datetime, timedelta, timezone from pathlib import Path @@ -44,9 +45,11 @@ bp = df.Blueprint() -# Exported history is written under the app directory so the E2E test (running -# on the same machine) can read it back and assert on the contents. -EXPORT_ROOT = Path(__file__).parent / "_export_output" +# Keep generated files outside the function app. Writing beneath the app root +# triggers the Functions host's file watcher and restarts the host mid-suite. +EXPORT_ROOT = ( + Path(tempfile.gettempdir()) / "durabletask-python-e2e" / "history-export" +) class _FileSystemHistoryWriter: diff --git a/tests/azure-functions-durable/e2e/test_dtask_entities_advanced_e2e.py b/tests/azure-functions-durable/e2e/test_dtask_entities_advanced_e2e.py index 2077d978..69f470f1 100644 --- a/tests/azure-functions-durable/e2e/test_dtask_entities_advanced_e2e.py +++ b/tests/azure-functions-durable/e2e/test_dtask_entities_advanced_e2e.py @@ -14,6 +14,8 @@ import pytest +from ._markers import azurite_delayed_visibility + pytestmark = pytest.mark.functions_e2e @@ -80,6 +82,7 @@ def test_call_failing_entity_handled(dtask_app): assert status["output"]["caught"] is True +@azurite_delayed_visibility def test_client_delayed_signal_is_deferred(dtask_app): key = f"client-delay-{int(time.time() * 1000)}" dtask_app.signal_entity("counter", key, "add", input=9, delay_seconds=3.0) @@ -96,6 +99,7 @@ def test_client_delayed_signal_is_deferred(dtask_app): assert payload["state"] == 9 +@azurite_delayed_visibility def test_orchestration_delayed_signal_is_deferred(dtask_app): key = f"orch-delay-{int(time.time() * 1000)}" instance_id = dtask_app.start_orchestration("signal_counter_delayed", body=key) diff --git a/tests/azure-functions-durable/e2e/test_dtask_patterns_e2e.py b/tests/azure-functions-durable/e2e/test_dtask_patterns_e2e.py index 14280e24..b8be0fff 100644 --- a/tests/azure-functions-durable/e2e/test_dtask_patterns_e2e.py +++ b/tests/azure-functions-durable/e2e/test_dtask_patterns_e2e.py @@ -13,9 +13,12 @@ import pytest +from ._markers import azurite_delayed_visibility + pytestmark = pytest.mark.functions_e2e +@azurite_delayed_visibility def test_timer(dtask_app): instance_id = dtask_app.start_orchestration("timer_wait") status = dtask_app.wait_for_completion(instance_id) diff --git a/tests/azure-functions-durable/e2e/test_dtask_scheduled_e2e.py b/tests/azure-functions-durable/e2e/test_dtask_scheduled_e2e.py index 5d00221d..13f36d88 100644 --- a/tests/azure-functions-durable/e2e/test_dtask_scheduled_e2e.py +++ b/tests/azure-functions-durable/e2e/test_dtask_scheduled_e2e.py @@ -13,7 +13,12 @@ import pytest -pytestmark = pytest.mark.functions_e2e +from ._markers import azurite_delayed_visibility + +pytestmark = [ + pytest.mark.functions_e2e, + azurite_delayed_visibility, +] def test_scheduled_orchestration_fires_repeatedly(dtask_app): diff --git a/tests/azure-functions-durable/e2e/test_v1_patterns_e2e.py b/tests/azure-functions-durable/e2e/test_v1_patterns_e2e.py index 4ba2ae64..0da0555f 100644 --- a/tests/azure-functions-durable/e2e/test_v1_patterns_e2e.py +++ b/tests/azure-functions-durable/e2e/test_v1_patterns_e2e.py @@ -13,9 +13,12 @@ import pytest +from ._markers import azurite_delayed_visibility + pytestmark = pytest.mark.functions_e2e +@azurite_delayed_visibility def test_timer(v1_app): instance_id = v1_app.start_orchestration("timer_wait") status = v1_app.wait_for_completion(instance_id)