From e210d6f14b51a0ebd9cabc9343ba3c24ab3806e5 Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Thu, 9 Oct 2025 15:35:06 -0400 Subject: [PATCH 01/26] Test the hello world agent, and setup fixture for loading the plugin --- tests/conftest.py | 12 ++++-- tests/openai_agents/__init__.py | 0 tests/openai_agents/conftest.py | 15 ++++++++ .../test_hello_world_workflow.py | 38 +++++++++++++++++++ 4 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 tests/openai_agents/__init__.py create mode 100644 tests/openai_agents/conftest.py create mode 100644 tests/openai_agents/test_hello_world_workflow.py diff --git a/tests/conftest.py b/tests/conftest.py index 65de246ea..fdba1f090 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -36,9 +36,14 @@ def event_loop(): yield loop loop.close() +@pytest.fixture(scope="session") +def plugins(): + # By default, no plugins. + # Other tests can override this fixture, such as in tests/openai_agents/conftest.py + return [] @pytest_asyncio.fixture(scope="session") -async def env(request) -> AsyncGenerator[WorkflowEnvironment, None]: +async def env(request, plugins) -> AsyncGenerator[WorkflowEnvironment, None]: env_type = request.config.getoption("--workflow-environment") if env_type == "local": env = await WorkflowEnvironment.start_local( @@ -47,12 +52,13 @@ async def env(request) -> AsyncGenerator[WorkflowEnvironment, None]: "frontend.enableExecuteMultiOperation=true", "--dynamic-config-value", "system.enableEagerWorkflowStart=true", - ] + ], + plugins=plugins ) elif env_type == "time-skipping": env = await WorkflowEnvironment.start_time_skipping() else: - env = WorkflowEnvironment.from_client(await Client.connect(env_type)) + env = WorkflowEnvironment.from_client(await Client.connect(env_type, plugins=plugins)) yield env await env.shutdown() diff --git a/tests/openai_agents/__init__.py b/tests/openai_agents/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/openai_agents/conftest.py b/tests/openai_agents/conftest.py new file mode 100644 index 000000000..4f5a01eda --- /dev/null +++ b/tests/openai_agents/conftest.py @@ -0,0 +1,15 @@ +from datetime import timedelta + +import pytest +from temporalio.contrib.openai_agents import ModelActivityParameters, OpenAIAgentsPlugin + + +@pytest.fixture(scope="session") +def plugins(): + return [ + OpenAIAgentsPlugin( + model_params=ModelActivityParameters( + start_to_close_timeout=timedelta(seconds=30) + ) + ) + ] diff --git a/tests/openai_agents/test_hello_world_workflow.py b/tests/openai_agents/test_hello_world_workflow.py new file mode 100644 index 000000000..038da3f93 --- /dev/null +++ b/tests/openai_agents/test_hello_world_workflow.py @@ -0,0 +1,38 @@ +import uuid +from concurrent.futures import ThreadPoolExecutor + +import pytest +from temporalio import activity +from temporalio.client import Client +from temporalio.worker import Worker + +from openai_agents.basic.activities.get_weather_activity import get_weather +from openai_agents.basic.activities.math_activities import multiply_by_two, random_number +from openai_agents.basic.activities.image_activities import read_image_as_base64 + +from openai_agents.basic.workflows.hello_world_workflow import HelloWorldAgent + + +@pytest.mark.fixt_data(42) +async def test_execute_workflow(client: Client): + task_queue_name = str(uuid.uuid4()) + + async with Worker( + client, + task_queue=task_queue_name, + workflows=[HelloWorldAgent], + activity_executor=ThreadPoolExecutor(5), + activities=[ + get_weather, + multiply_by_two, + random_number, + read_image_as_base64, + ], + ): + await client.execute_workflow( + HelloWorldAgent.run, + "Write a recursive haiku about recursive haikus.", + id=str(uuid.uuid4()), + task_queue=task_queue_name, + ) + From 63c544993dedf496a1ab4b6e809f1f88a1305b31 Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Thu, 9 Oct 2025 15:41:06 -0400 Subject: [PATCH 02/26] Format --- tests/conftest.py | 8 ++++++-- tests/openai_agents/test_hello_world_workflow.py | 6 ++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index fdba1f090..d50c342c3 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -36,12 +36,14 @@ def event_loop(): yield loop loop.close() + @pytest.fixture(scope="session") def plugins(): # By default, no plugins. # Other tests can override this fixture, such as in tests/openai_agents/conftest.py return [] + @pytest_asyncio.fixture(scope="session") async def env(request, plugins) -> AsyncGenerator[WorkflowEnvironment, None]: env_type = request.config.getoption("--workflow-environment") @@ -53,12 +55,14 @@ async def env(request, plugins) -> AsyncGenerator[WorkflowEnvironment, None]: "--dynamic-config-value", "system.enableEagerWorkflowStart=true", ], - plugins=plugins + plugins=plugins, ) elif env_type == "time-skipping": env = await WorkflowEnvironment.start_time_skipping() else: - env = WorkflowEnvironment.from_client(await Client.connect(env_type, plugins=plugins)) + env = WorkflowEnvironment.from_client( + await Client.connect(env_type, plugins=plugins) + ) yield env await env.shutdown() diff --git a/tests/openai_agents/test_hello_world_workflow.py b/tests/openai_agents/test_hello_world_workflow.py index 038da3f93..5c1a8e677 100644 --- a/tests/openai_agents/test_hello_world_workflow.py +++ b/tests/openai_agents/test_hello_world_workflow.py @@ -7,7 +7,10 @@ from temporalio.worker import Worker from openai_agents.basic.activities.get_weather_activity import get_weather -from openai_agents.basic.activities.math_activities import multiply_by_two, random_number +from openai_agents.basic.activities.math_activities import ( + multiply_by_two, + random_number, +) from openai_agents.basic.activities.image_activities import read_image_as_base64 from openai_agents.basic.workflows.hello_world_workflow import HelloWorldAgent @@ -35,4 +38,3 @@ async def test_execute_workflow(client: Client): id=str(uuid.uuid4()), task_queue=task_queue_name, ) - From cafb91705248a8f6c704c10ba1c1765a3855964d Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Thu, 9 Oct 2025 16:04:04 -0400 Subject: [PATCH 03/26] lint --- tests/openai_agents/test_hello_world_workflow.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/openai_agents/test_hello_world_workflow.py b/tests/openai_agents/test_hello_world_workflow.py index 5c1a8e677..c21c4f515 100644 --- a/tests/openai_agents/test_hello_world_workflow.py +++ b/tests/openai_agents/test_hello_world_workflow.py @@ -7,12 +7,11 @@ from temporalio.worker import Worker from openai_agents.basic.activities.get_weather_activity import get_weather +from openai_agents.basic.activities.image_activities import read_image_as_base64 from openai_agents.basic.activities.math_activities import ( multiply_by_two, random_number, ) -from openai_agents.basic.activities.image_activities import read_image_as_base64 - from openai_agents.basic.workflows.hello_world_workflow import HelloWorldAgent From 6554dc606e4298cbcf7e17445dd054c79d6ad9e3 Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Fri, 10 Oct 2025 08:15:39 -0400 Subject: [PATCH 04/26] ignore openai tests for now --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 73007250e..cb008116e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -122,7 +122,7 @@ build-backend = "hatchling.build" format = [{cmd = "uv run black ."}, {cmd = "uv run isort ."}] lint = [{cmd = "uv run black --check ."}, {cmd = "uv run isort --check-only ."}, {ref = "lint-types" }] lint-types = "uv run --all-groups mypy --check-untyped-defs --namespace-packages ." -test = "uv run --all-groups pytest" +test = "uv run --all-groups pytest --ignore=tests/openai_agents" [tool.pytest.ini_options] asyncio_mode = "auto" From 98d8d89fa4c2da883776f97743277d73ae2cc6b2 Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Fri, 10 Oct 2025 14:44:10 -0400 Subject: [PATCH 05/26] remove debug junk --- tests/openai_agents/test_hello_world_workflow.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/openai_agents/test_hello_world_workflow.py b/tests/openai_agents/test_hello_world_workflow.py index c21c4f515..f87956d52 100644 --- a/tests/openai_agents/test_hello_world_workflow.py +++ b/tests/openai_agents/test_hello_world_workflow.py @@ -15,7 +15,6 @@ from openai_agents.basic.workflows.hello_world_workflow import HelloWorldAgent -@pytest.mark.fixt_data(42) async def test_execute_workflow(client: Client): task_queue_name = str(uuid.uuid4()) From 1c93ecbc65547e53bc0b5d7db96f529373f27f88 Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Fri, 10 Oct 2025 14:44:28 -0400 Subject: [PATCH 06/26] Update README with instructions for running OpenAI tests --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index d9ae57a30..3288f85a2 100644 --- a/README.md +++ b/README.md @@ -90,3 +90,7 @@ Some examples require extra dependencies. See each sample's directory for specif To run the tests: uv run poe test + +By default, this won't run the OpenAI SDK sample tests. To run those, set your `OPENAI_API_KEY` in your environment, and run: + + uv run poe test tests/openai_agents From f7429caa1b4ccc93a8e93425d2015805609179e3 Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Fri, 10 Oct 2025 14:47:24 -0400 Subject: [PATCH 07/26] move test file --- tests/openai_agents/{ => basic}/test_hello_world_workflow.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/openai_agents/{ => basic}/test_hello_world_workflow.py (100%) diff --git a/tests/openai_agents/test_hello_world_workflow.py b/tests/openai_agents/basic/test_hello_world_workflow.py similarity index 100% rename from tests/openai_agents/test_hello_world_workflow.py rename to tests/openai_agents/basic/test_hello_world_workflow.py From 090a8bd056a149fe6e82f083d65da939fda8c9e0 Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Fri, 10 Oct 2025 15:07:21 -0400 Subject: [PATCH 08/26] More tests! --- .../basic/test_agent_lifecycle_workflow.py | 35 +++++++++++ .../test_dynamic_system_prompt_workflow.py | 55 +++++++++++++++++ .../basic/test_lifecycle_workflow.py | 33 ++++++++++ .../basic/test_local_image_workflow.py | 54 +++++++++++++++++ .../basic/test_non_strict_output_workflow.py | 46 ++++++++++++++ .../test_previous_response_id_workflow.py | 44 ++++++++++++++ .../basic/test_remote_image_workflow.py | 60 +++++++++++++++++++ .../basic/test_tools_workflow.py | 31 ++++++++++ 8 files changed, 358 insertions(+) create mode 100644 tests/openai_agents/basic/test_agent_lifecycle_workflow.py create mode 100644 tests/openai_agents/basic/test_dynamic_system_prompt_workflow.py create mode 100644 tests/openai_agents/basic/test_lifecycle_workflow.py create mode 100644 tests/openai_agents/basic/test_local_image_workflow.py create mode 100644 tests/openai_agents/basic/test_non_strict_output_workflow.py create mode 100644 tests/openai_agents/basic/test_previous_response_id_workflow.py create mode 100644 tests/openai_agents/basic/test_remote_image_workflow.py create mode 100644 tests/openai_agents/basic/test_tools_workflow.py diff --git a/tests/openai_agents/basic/test_agent_lifecycle_workflow.py b/tests/openai_agents/basic/test_agent_lifecycle_workflow.py new file mode 100644 index 000000000..b9019242d --- /dev/null +++ b/tests/openai_agents/basic/test_agent_lifecycle_workflow.py @@ -0,0 +1,35 @@ +import uuid +from concurrent.futures import ThreadPoolExecutor + +import pytest +from temporalio.client import Client +from temporalio.worker import Worker + +from openai_agents.basic.workflows.agent_lifecycle_workflow import ( + AgentLifecycleWorkflow, +) + + +async def test_execute_workflow(client: Client): + task_queue_name = str(uuid.uuid4()) + + async with Worker( + client, + task_queue=task_queue_name, + workflows=[AgentLifecycleWorkflow], + activity_executor=ThreadPoolExecutor(5), + # No external activities needed - workflow uses function tools + ): + result = await client.execute_workflow( + AgentLifecycleWorkflow.run, + 10, # max_number parameter + id=str(uuid.uuid4()), + task_queue=task_queue_name, + ) + + # Verify the result has the expected structure + assert hasattr(result, "number") + assert isinstance(result.number, int) + assert ( + 0 <= result.number <= 20 + ) # Should be between 0 and max*2 due to multiply operation diff --git a/tests/openai_agents/basic/test_dynamic_system_prompt_workflow.py b/tests/openai_agents/basic/test_dynamic_system_prompt_workflow.py new file mode 100644 index 000000000..7b86310e4 --- /dev/null +++ b/tests/openai_agents/basic/test_dynamic_system_prompt_workflow.py @@ -0,0 +1,55 @@ +import uuid +from concurrent.futures import ThreadPoolExecutor + +import pytest +from temporalio.client import Client +from temporalio.worker import Worker + +from openai_agents.basic.workflows.dynamic_system_prompt_workflow import ( + DynamicSystemPromptWorkflow, +) + + +async def test_execute_workflow_with_random_style(client: Client): + task_queue_name = str(uuid.uuid4()) + + async with Worker( + client, + task_queue=task_queue_name, + workflows=[DynamicSystemPromptWorkflow], + activity_executor=ThreadPoolExecutor(5), + # No external activities needed + ): + result = await client.execute_workflow( + DynamicSystemPromptWorkflow.run, + "Tell me about the weather today.", + id=str(uuid.uuid4()), + task_queue=task_queue_name, + ) + + # Verify the result has the expected format + assert "Style:" in result + assert "Response:" in result + assert any(style in result for style in ["haiku", "pirate", "robot"]) + + +async def test_execute_workflow_with_specific_style(client: Client): + task_queue_name = str(uuid.uuid4()) + + async with Worker( + client, + task_queue=task_queue_name, + workflows=[DynamicSystemPromptWorkflow], + activity_executor=ThreadPoolExecutor(5), + # No external activities needed + ): + result = await client.execute_workflow( + DynamicSystemPromptWorkflow.run, + args=["Tell me about the weather today.", "haiku"], + id=str(uuid.uuid4()), + task_queue=task_queue_name, + ) + + # Verify the result has the expected format and style + assert "Style: haiku" in result + assert "Response:" in result diff --git a/tests/openai_agents/basic/test_lifecycle_workflow.py b/tests/openai_agents/basic/test_lifecycle_workflow.py new file mode 100644 index 000000000..84dc0d78b --- /dev/null +++ b/tests/openai_agents/basic/test_lifecycle_workflow.py @@ -0,0 +1,33 @@ +import uuid +from concurrent.futures import ThreadPoolExecutor + +import pytest +from temporalio.client import Client +from temporalio.worker import Worker + +from openai_agents.basic.workflows.lifecycle_workflow import LifecycleWorkflow + + +async def test_execute_workflow(client: Client): + task_queue_name = str(uuid.uuid4()) + + async with Worker( + client, + task_queue=task_queue_name, + workflows=[LifecycleWorkflow], + activity_executor=ThreadPoolExecutor(5), + # No external activities needed - workflow uses function tools + ): + result = await client.execute_workflow( + LifecycleWorkflow.run, + 10, # max_number parameter + id=str(uuid.uuid4()), + task_queue=task_queue_name, + ) + + # Verify the result has the expected structure + assert hasattr(result, "number") + assert isinstance(result.number, int) + assert ( + 0 <= result.number <= 20 + ) # Should be between 0 and max*2 due to multiply operation diff --git a/tests/openai_agents/basic/test_local_image_workflow.py b/tests/openai_agents/basic/test_local_image_workflow.py new file mode 100644 index 000000000..b61f47a75 --- /dev/null +++ b/tests/openai_agents/basic/test_local_image_workflow.py @@ -0,0 +1,54 @@ +import uuid +from concurrent.futures import ThreadPoolExecutor + +import pytest +from temporalio.client import Client +from temporalio.worker import Worker + +from openai_agents.basic.activities.image_activities import read_image_as_base64 +from openai_agents.basic.workflows.local_image_workflow import LocalImageWorkflow + + +async def test_execute_workflow_default_question(client: Client): + task_queue_name = str(uuid.uuid4()) + + async with Worker( + client, + task_queue=task_queue_name, + workflows=[LocalImageWorkflow], + activity_executor=ThreadPoolExecutor(5), + activities=[read_image_as_base64], + ): + result = await client.execute_workflow( + LocalImageWorkflow.run, + "openai_agents/basic/media/image_bison.jpg", # Path to test image + id=str(uuid.uuid4()), + task_queue=task_queue_name, + ) + + # Verify the result is a string response + assert isinstance(result, str) + assert len(result) > 0 + + +async def test_execute_workflow_custom_question(client: Client): + task_queue_name = str(uuid.uuid4()) + + async with Worker( + client, + task_queue=task_queue_name, + workflows=[LocalImageWorkflow], + activity_executor=ThreadPoolExecutor(5), + activities=[read_image_as_base64], + ): + custom_question = "What animals do you see in this image?" + result = await client.execute_workflow( + LocalImageWorkflow.run, + args=["openai_agents/basic/media/image_bison.jpg", custom_question], + id=str(uuid.uuid4()), + task_queue=task_queue_name, + ) + + # Verify the result is a string response + assert isinstance(result, str) + assert len(result) > 0 diff --git a/tests/openai_agents/basic/test_non_strict_output_workflow.py b/tests/openai_agents/basic/test_non_strict_output_workflow.py new file mode 100644 index 000000000..cdd4f561e --- /dev/null +++ b/tests/openai_agents/basic/test_non_strict_output_workflow.py @@ -0,0 +1,46 @@ +import uuid +from concurrent.futures import ThreadPoolExecutor + +import pytest +from temporalio.client import Client +from temporalio.worker import Worker + +from openai_agents.basic.workflows.non_strict_output_workflow import ( + NonStrictOutputWorkflow, +) + + +async def test_execute_workflow(client: Client): + task_queue_name = str(uuid.uuid4()) + + async with Worker( + client, + task_queue=task_queue_name, + workflows=[NonStrictOutputWorkflow], + activity_executor=ThreadPoolExecutor(5), + # No external activities needed + ): + result = await client.execute_workflow( + NonStrictOutputWorkflow.run, + "Tell me 3 funny jokes about programming.", + id=str(uuid.uuid4()), + task_queue=task_queue_name, + ) + + # Verify the result has the expected structure + assert isinstance(result, dict) + + # Should have either strict_result or strict_error + assert "strict_result" in result or "strict_error" in result + + # Should have either non_strict_result or non_strict_error + assert "non_strict_result" in result or "non_strict_error" in result + + # If there's a strict_error, it should be a string + if "strict_error" in result: + assert isinstance(result["strict_error"], str) + assert len(result["strict_error"]) > 0 + + # If there's a non_strict_result, verify it's valid + if "non_strict_result" in result: + assert result["non_strict_result"] is not None diff --git a/tests/openai_agents/basic/test_previous_response_id_workflow.py b/tests/openai_agents/basic/test_previous_response_id_workflow.py new file mode 100644 index 000000000..c339dbeee --- /dev/null +++ b/tests/openai_agents/basic/test_previous_response_id_workflow.py @@ -0,0 +1,44 @@ +import uuid +from concurrent.futures import ThreadPoolExecutor + +import pytest +from temporalio.client import Client +from temporalio.worker import Worker + +from openai_agents.basic.workflows.previous_response_id_workflow import ( + PreviousResponseIdWorkflow, +) + + +async def test_execute_workflow(client: Client): + task_queue_name = str(uuid.uuid4()) + + async with Worker( + client, + task_queue=task_queue_name, + workflows=[PreviousResponseIdWorkflow], + activity_executor=ThreadPoolExecutor(5), + # No external activities needed + ): + first_question = "What is the capital of France?" + follow_up_question = "What is the population of that city?" + + result = await client.execute_workflow( + PreviousResponseIdWorkflow.run, + args=[first_question, follow_up_question], + id=str(uuid.uuid4()), + task_queue=task_queue_name, + ) + + # Verify the result is a tuple with two string responses + assert isinstance(result, tuple) + assert len(result) == 2 + + first_response, second_response = result + assert isinstance(first_response, str) + assert isinstance(second_response, str) + assert len(first_response) > 0 + assert len(second_response) > 0 + + # The responses should be different (not identical) + assert first_response != second_response diff --git a/tests/openai_agents/basic/test_remote_image_workflow.py b/tests/openai_agents/basic/test_remote_image_workflow.py new file mode 100644 index 000000000..098ae2364 --- /dev/null +++ b/tests/openai_agents/basic/test_remote_image_workflow.py @@ -0,0 +1,60 @@ +import uuid +from concurrent.futures import ThreadPoolExecutor + +import pytest +from temporalio.client import Client +from temporalio.worker import Worker + +from openai_agents.basic.workflows.remote_image_workflow import RemoteImageWorkflow + +# TODO(@donald-pinckney): debug this test +# async def test_execute_workflow_default_question(client: Client): +# task_queue_name = str(uuid.uuid4()) + +# async with Worker( +# client, +# task_queue=task_queue_name, +# workflows=[RemoteImageWorkflow], +# activity_executor=ThreadPoolExecutor(5), +# # No external activities needed - uses remote URL directly +# ): +# # Using a reliable test image URL +# test_image_url = "https://httpbin.org/image/jpeg" + +# result = await client.execute_workflow( +# RemoteImageWorkflow.run, +# test_image_url, +# id=str(uuid.uuid4()), +# task_queue=task_queue_name, +# ) + +# # Verify the result is a string response +# assert isinstance(result, str) +# assert len(result) > 0 + + +# TODO(@donald-pinckney): debug this test +# async def test_execute_workflow_custom_question(client: Client): +# task_queue_name = str(uuid.uuid4()) + +# async with Worker( +# client, +# task_queue=task_queue_name, +# workflows=[RemoteImageWorkflow], +# activity_executor=ThreadPoolExecutor(5), +# # No external activities needed - uses remote URL directly +# ): +# # Using a reliable test image URL +# test_image_url = "https://httpbin.org/image/png" +# custom_question = "What do you see in this image?" + +# result = await client.execute_workflow( +# RemoteImageWorkflow.run, +# args=[test_image_url, custom_question], +# id=str(uuid.uuid4()), +# task_queue=task_queue_name, +# ) + +# # Verify the result is a string response +# assert isinstance(result, str) +# assert len(result) > 0 diff --git a/tests/openai_agents/basic/test_tools_workflow.py b/tests/openai_agents/basic/test_tools_workflow.py new file mode 100644 index 000000000..1f97542ed --- /dev/null +++ b/tests/openai_agents/basic/test_tools_workflow.py @@ -0,0 +1,31 @@ +import uuid +from concurrent.futures import ThreadPoolExecutor + +import pytest +from temporalio.client import Client +from temporalio.worker import Worker + +from openai_agents.basic.activities.get_weather_activity import get_weather +from openai_agents.basic.workflows.tools_workflow import ToolsWorkflow + + +async def test_execute_workflow(client: Client): + task_queue_name = str(uuid.uuid4()) + + async with Worker( + client, + task_queue=task_queue_name, + workflows=[ToolsWorkflow], + activity_executor=ThreadPoolExecutor(5), + activities=[get_weather], + ): + result = await client.execute_workflow( + ToolsWorkflow.run, + "What's the weather like in New York?", + id=str(uuid.uuid4()), + task_queue=task_queue_name, + ) + + # Verify the result is a string response + assert isinstance(result, str) + assert len(result) > 0 From 186f6e4757e1876a2400dfb5949d3cd052958d83 Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Tue, 14 Oct 2025 11:46:29 -0400 Subject: [PATCH 09/26] fix a test --- .../basic/test_remote_image_workflow.py | 95 ++++++++++--------- 1 file changed, 48 insertions(+), 47 deletions(-) diff --git a/tests/openai_agents/basic/test_remote_image_workflow.py b/tests/openai_agents/basic/test_remote_image_workflow.py index 098ae2364..760e24a82 100644 --- a/tests/openai_agents/basic/test_remote_image_workflow.py +++ b/tests/openai_agents/basic/test_remote_image_workflow.py @@ -7,54 +7,55 @@ from openai_agents.basic.workflows.remote_image_workflow import RemoteImageWorkflow + # TODO(@donald-pinckney): debug this test -# async def test_execute_workflow_default_question(client: Client): -# task_queue_name = str(uuid.uuid4()) - -# async with Worker( -# client, -# task_queue=task_queue_name, -# workflows=[RemoteImageWorkflow], -# activity_executor=ThreadPoolExecutor(5), -# # No external activities needed - uses remote URL directly -# ): -# # Using a reliable test image URL -# test_image_url = "https://httpbin.org/image/jpeg" - -# result = await client.execute_workflow( -# RemoteImageWorkflow.run, -# test_image_url, -# id=str(uuid.uuid4()), -# task_queue=task_queue_name, -# ) - -# # Verify the result is a string response -# assert isinstance(result, str) -# assert len(result) > 0 +async def test_execute_workflow_default_question(client: Client): + task_queue_name = str(uuid.uuid4()) + + async with Worker( + client, + task_queue=task_queue_name, + workflows=[RemoteImageWorkflow], + activity_executor=ThreadPoolExecutor(5), + # No external activities needed - uses remote URL directly + ): + # Using a reliable test image URL + test_image_url = "https://upload.wikimedia.org/wikipedia/commons/0/0c/GoldenGateBridge-001.jpg" + + result = await client.execute_workflow( + RemoteImageWorkflow.run, + test_image_url, + id=str(uuid.uuid4()), + task_queue=task_queue_name, + ) + + # Verify the result is a string response + assert isinstance(result, str) + assert len(result) > 0 # TODO(@donald-pinckney): debug this test -# async def test_execute_workflow_custom_question(client: Client): -# task_queue_name = str(uuid.uuid4()) - -# async with Worker( -# client, -# task_queue=task_queue_name, -# workflows=[RemoteImageWorkflow], -# activity_executor=ThreadPoolExecutor(5), -# # No external activities needed - uses remote URL directly -# ): -# # Using a reliable test image URL -# test_image_url = "https://httpbin.org/image/png" -# custom_question = "What do you see in this image?" - -# result = await client.execute_workflow( -# RemoteImageWorkflow.run, -# args=[test_image_url, custom_question], -# id=str(uuid.uuid4()), -# task_queue=task_queue_name, -# ) - -# # Verify the result is a string response -# assert isinstance(result, str) -# assert len(result) > 0 +async def test_execute_workflow_custom_question(client: Client): + task_queue_name = str(uuid.uuid4()) + + async with Worker( + client, + task_queue=task_queue_name, + workflows=[RemoteImageWorkflow], + activity_executor=ThreadPoolExecutor(5), + # No external activities needed - uses remote URL directly + ): + # Using a reliable test image URL + test_image_url = "https://upload.wikimedia.org/wikipedia/commons/0/0c/GoldenGateBridge-001.jpg" + custom_question = "What do you see in this image?" + + result = await client.execute_workflow( + RemoteImageWorkflow.run, + args=[test_image_url, custom_question], + id=str(uuid.uuid4()), + task_queue=task_queue_name, + ) + + # Verify the result is a string response + assert isinstance(result, str) + assert len(result) > 0 From 6c07d56eccc2d54a350f8245d6344ac16fc1d6ac Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Tue, 14 Oct 2025 12:24:59 -0400 Subject: [PATCH 10/26] cleanup tests --- .../basic/test_agent_lifecycle_workflow.py | 3 --- .../test_dynamic_system_prompt_workflow.py | 3 --- .../basic/test_hello_world_workflow.py | 18 +++--------------- .../basic/test_lifecycle_workflow.py | 3 --- .../basic/test_local_image_workflow.py | 1 - .../basic/test_non_strict_output_workflow.py | 14 +++++--------- .../test_previous_response_id_workflow.py | 2 -- .../basic/test_remote_image_workflow.py | 7 ------- .../openai_agents/basic/test_tools_workflow.py | 1 - 9 files changed, 8 insertions(+), 44 deletions(-) diff --git a/tests/openai_agents/basic/test_agent_lifecycle_workflow.py b/tests/openai_agents/basic/test_agent_lifecycle_workflow.py index b9019242d..97621ea0a 100644 --- a/tests/openai_agents/basic/test_agent_lifecycle_workflow.py +++ b/tests/openai_agents/basic/test_agent_lifecycle_workflow.py @@ -1,7 +1,6 @@ import uuid from concurrent.futures import ThreadPoolExecutor -import pytest from temporalio.client import Client from temporalio.worker import Worker @@ -18,7 +17,6 @@ async def test_execute_workflow(client: Client): task_queue=task_queue_name, workflows=[AgentLifecycleWorkflow], activity_executor=ThreadPoolExecutor(5), - # No external activities needed - workflow uses function tools ): result = await client.execute_workflow( AgentLifecycleWorkflow.run, @@ -28,7 +26,6 @@ async def test_execute_workflow(client: Client): ) # Verify the result has the expected structure - assert hasattr(result, "number") assert isinstance(result.number, int) assert ( 0 <= result.number <= 20 diff --git a/tests/openai_agents/basic/test_dynamic_system_prompt_workflow.py b/tests/openai_agents/basic/test_dynamic_system_prompt_workflow.py index 7b86310e4..424bd7d6f 100644 --- a/tests/openai_agents/basic/test_dynamic_system_prompt_workflow.py +++ b/tests/openai_agents/basic/test_dynamic_system_prompt_workflow.py @@ -1,7 +1,6 @@ import uuid from concurrent.futures import ThreadPoolExecutor -import pytest from temporalio.client import Client from temporalio.worker import Worker @@ -18,7 +17,6 @@ async def test_execute_workflow_with_random_style(client: Client): task_queue=task_queue_name, workflows=[DynamicSystemPromptWorkflow], activity_executor=ThreadPoolExecutor(5), - # No external activities needed ): result = await client.execute_workflow( DynamicSystemPromptWorkflow.run, @@ -41,7 +39,6 @@ async def test_execute_workflow_with_specific_style(client: Client): task_queue=task_queue_name, workflows=[DynamicSystemPromptWorkflow], activity_executor=ThreadPoolExecutor(5), - # No external activities needed ): result = await client.execute_workflow( DynamicSystemPromptWorkflow.run, diff --git a/tests/openai_agents/basic/test_hello_world_workflow.py b/tests/openai_agents/basic/test_hello_world_workflow.py index f87956d52..9aa16f5df 100644 --- a/tests/openai_agents/basic/test_hello_world_workflow.py +++ b/tests/openai_agents/basic/test_hello_world_workflow.py @@ -1,17 +1,9 @@ import uuid from concurrent.futures import ThreadPoolExecutor -import pytest -from temporalio import activity from temporalio.client import Client from temporalio.worker import Worker -from openai_agents.basic.activities.get_weather_activity import get_weather -from openai_agents.basic.activities.image_activities import read_image_as_base64 -from openai_agents.basic.activities.math_activities import ( - multiply_by_two, - random_number, -) from openai_agents.basic.workflows.hello_world_workflow import HelloWorldAgent @@ -23,16 +15,12 @@ async def test_execute_workflow(client: Client): task_queue=task_queue_name, workflows=[HelloWorldAgent], activity_executor=ThreadPoolExecutor(5), - activities=[ - get_weather, - multiply_by_two, - random_number, - read_image_as_base64, - ], ): - await client.execute_workflow( + result = await client.execute_workflow( HelloWorldAgent.run, "Write a recursive haiku about recursive haikus.", id=str(uuid.uuid4()), task_queue=task_queue_name, ) + assert isinstance(result, str) + assert len(result) > 0 diff --git a/tests/openai_agents/basic/test_lifecycle_workflow.py b/tests/openai_agents/basic/test_lifecycle_workflow.py index 84dc0d78b..b115ac571 100644 --- a/tests/openai_agents/basic/test_lifecycle_workflow.py +++ b/tests/openai_agents/basic/test_lifecycle_workflow.py @@ -1,7 +1,6 @@ import uuid from concurrent.futures import ThreadPoolExecutor -import pytest from temporalio.client import Client from temporalio.worker import Worker @@ -16,7 +15,6 @@ async def test_execute_workflow(client: Client): task_queue=task_queue_name, workflows=[LifecycleWorkflow], activity_executor=ThreadPoolExecutor(5), - # No external activities needed - workflow uses function tools ): result = await client.execute_workflow( LifecycleWorkflow.run, @@ -26,7 +24,6 @@ async def test_execute_workflow(client: Client): ) # Verify the result has the expected structure - assert hasattr(result, "number") assert isinstance(result.number, int) assert ( 0 <= result.number <= 20 diff --git a/tests/openai_agents/basic/test_local_image_workflow.py b/tests/openai_agents/basic/test_local_image_workflow.py index b61f47a75..7062becc3 100644 --- a/tests/openai_agents/basic/test_local_image_workflow.py +++ b/tests/openai_agents/basic/test_local_image_workflow.py @@ -1,7 +1,6 @@ import uuid from concurrent.futures import ThreadPoolExecutor -import pytest from temporalio.client import Client from temporalio.worker import Worker diff --git a/tests/openai_agents/basic/test_non_strict_output_workflow.py b/tests/openai_agents/basic/test_non_strict_output_workflow.py index cdd4f561e..5b5ec8446 100644 --- a/tests/openai_agents/basic/test_non_strict_output_workflow.py +++ b/tests/openai_agents/basic/test_non_strict_output_workflow.py @@ -1,7 +1,6 @@ import uuid from concurrent.futures import ThreadPoolExecutor -import pytest from temporalio.client import Client from temporalio.worker import Worker @@ -30,17 +29,14 @@ async def test_execute_workflow(client: Client): # Verify the result has the expected structure assert isinstance(result, dict) - # Should have either strict_result or strict_error - assert "strict_result" in result or "strict_error" in result - - # Should have either non_strict_result or non_strict_error - assert "non_strict_result" in result or "non_strict_error" in result + assert "strict_error" in result + assert "non_strict_result" in result # If there's a strict_error, it should be a string if "strict_error" in result: assert isinstance(result["strict_error"], str) assert len(result["strict_error"]) > 0 - # If there's a non_strict_result, verify it's valid - if "non_strict_result" in result: - assert result["non_strict_result"] is not None + jokes = result["non_strict_result"]["jokes"] + assert isinstance(jokes, dict) + assert isinstance(jokes[list(jokes.keys())[0]], str) diff --git a/tests/openai_agents/basic/test_previous_response_id_workflow.py b/tests/openai_agents/basic/test_previous_response_id_workflow.py index c339dbeee..80e311f57 100644 --- a/tests/openai_agents/basic/test_previous_response_id_workflow.py +++ b/tests/openai_agents/basic/test_previous_response_id_workflow.py @@ -1,7 +1,6 @@ import uuid from concurrent.futures import ThreadPoolExecutor -import pytest from temporalio.client import Client from temporalio.worker import Worker @@ -18,7 +17,6 @@ async def test_execute_workflow(client: Client): task_queue=task_queue_name, workflows=[PreviousResponseIdWorkflow], activity_executor=ThreadPoolExecutor(5), - # No external activities needed ): first_question = "What is the capital of France?" follow_up_question = "What is the population of that city?" diff --git a/tests/openai_agents/basic/test_remote_image_workflow.py b/tests/openai_agents/basic/test_remote_image_workflow.py index 760e24a82..0f1cb24e1 100644 --- a/tests/openai_agents/basic/test_remote_image_workflow.py +++ b/tests/openai_agents/basic/test_remote_image_workflow.py @@ -1,14 +1,12 @@ import uuid from concurrent.futures import ThreadPoolExecutor -import pytest from temporalio.client import Client from temporalio.worker import Worker from openai_agents.basic.workflows.remote_image_workflow import RemoteImageWorkflow -# TODO(@donald-pinckney): debug this test async def test_execute_workflow_default_question(client: Client): task_queue_name = str(uuid.uuid4()) @@ -17,9 +15,7 @@ async def test_execute_workflow_default_question(client: Client): task_queue=task_queue_name, workflows=[RemoteImageWorkflow], activity_executor=ThreadPoolExecutor(5), - # No external activities needed - uses remote URL directly ): - # Using a reliable test image URL test_image_url = "https://upload.wikimedia.org/wikipedia/commons/0/0c/GoldenGateBridge-001.jpg" result = await client.execute_workflow( @@ -34,7 +30,6 @@ async def test_execute_workflow_default_question(client: Client): assert len(result) > 0 -# TODO(@donald-pinckney): debug this test async def test_execute_workflow_custom_question(client: Client): task_queue_name = str(uuid.uuid4()) @@ -43,9 +38,7 @@ async def test_execute_workflow_custom_question(client: Client): task_queue=task_queue_name, workflows=[RemoteImageWorkflow], activity_executor=ThreadPoolExecutor(5), - # No external activities needed - uses remote URL directly ): - # Using a reliable test image URL test_image_url = "https://upload.wikimedia.org/wikipedia/commons/0/0c/GoldenGateBridge-001.jpg" custom_question = "What do you see in this image?" diff --git a/tests/openai_agents/basic/test_tools_workflow.py b/tests/openai_agents/basic/test_tools_workflow.py index 1f97542ed..591ca7fdc 100644 --- a/tests/openai_agents/basic/test_tools_workflow.py +++ b/tests/openai_agents/basic/test_tools_workflow.py @@ -1,7 +1,6 @@ import uuid from concurrent.futures import ThreadPoolExecutor -import pytest from temporalio.client import Client from temporalio.worker import Worker From 46b0bb15e9ccc0301fb3ff28e904bc002614ef21 Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Tue, 14 Oct 2025 17:56:25 -0400 Subject: [PATCH 11/26] Figure out mocks for one test --- pyproject.toml | 1 + tests/conftest.py | 4 +-- .../basic/test_hello_world_workflow.py | 31 +++++++++++++++++++ tests/openai_agents/conftest.py | 22 +++++++++++-- tests/openai_agents/e2e/conftest.py | 9 ++++++ .../e2e/test_hello_world_workflow_e2e.py | 26 ++++++++++++++++ uv.lock | 16 +++++++++- 7 files changed, 103 insertions(+), 6 deletions(-) create mode 100644 tests/openai_agents/e2e/conftest.py create mode 100644 tests/openai_agents/e2e/test_hello_world_workflow_e2e.py diff --git a/pyproject.toml b/pyproject.toml index cb008116e..14a04e34b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,6 +26,7 @@ dev = [ "types-pyyaml>=6.0.12.20241230,<7", "pytest-pretty>=1.3.0", "poethepoet>=0.36.0", + "pytest-mock>=3.15.1", ] bedrock = ["boto3>=1.34.92,<2"] dsl = [ diff --git a/tests/conftest.py b/tests/conftest.py index d50c342c3..44645c6f3 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -37,14 +37,14 @@ def event_loop(): loop.close() -@pytest.fixture(scope="session") +@pytest.fixture def plugins(): # By default, no plugins. # Other tests can override this fixture, such as in tests/openai_agents/conftest.py return [] -@pytest_asyncio.fixture(scope="session") +@pytest_asyncio.fixture async def env(request, plugins) -> AsyncGenerator[WorkflowEnvironment, None]: env_type = request.config.getoption("--workflow-environment") if env_type == "local": diff --git a/tests/openai_agents/basic/test_hello_world_workflow.py b/tests/openai_agents/basic/test_hello_world_workflow.py index 9aa16f5df..9f40aceeb 100644 --- a/tests/openai_agents/basic/test_hello_world_workflow.py +++ b/tests/openai_agents/basic/test_hello_world_workflow.py @@ -1,12 +1,43 @@ import uuid from concurrent.futures import ThreadPoolExecutor +import pytest +from agents import ModelResponse, Usage +from openai.types.responses import ResponseOutputMessage, ResponseOutputText from temporalio.client import Client from temporalio.worker import Worker from openai_agents.basic.workflows.hello_world_workflow import HelloWorldAgent +@pytest.fixture +def mocked_model(mocker): + mock = mocker.AsyncMock() + mock.get_response.side_effect = [ + ModelResponse( + output=[ + ResponseOutputMessage( + id="1", + content=[ + ResponseOutputText( + annotations=[], + text="This is a haiku (not really)", + type="output_text", + ) + ], + role="assistant", + status="completed", + type="message", + ) + ], + usage=Usage(requests=1, input_tokens=1, output_tokens=1, total_tokens=1), + response_id="1", + ) + ] + + return mock + + async def test_execute_workflow(client: Client): task_queue_name = str(uuid.uuid4()) diff --git a/tests/openai_agents/conftest.py b/tests/openai_agents/conftest.py index 4f5a01eda..1a29bf4e3 100644 --- a/tests/openai_agents/conftest.py +++ b/tests/openai_agents/conftest.py @@ -1,15 +1,31 @@ from datetime import timedelta +from typing import Optional import pytest +from agents import Model, ModelProvider from temporalio.contrib.openai_agents import ModelActivityParameters, OpenAIAgentsPlugin -@pytest.fixture(scope="session") -def plugins(): +class MockedModelProvider(ModelProvider): + def __init__(self, mocked_model): + self.mocked_model = mocked_model + + def get_model(self, model_name: str | None) -> Model: + return self.mocked_model + + +@pytest.fixture +def model_provider(mocked_model): + return MockedModelProvider(mocked_model) + + +@pytest.fixture +def plugins(model_provider: Optional[ModelProvider]): return [ OpenAIAgentsPlugin( model_params=ModelActivityParameters( start_to_close_timeout=timedelta(seconds=30) - ) + ), + model_provider=model_provider, ) ] diff --git a/tests/openai_agents/e2e/conftest.py b/tests/openai_agents/e2e/conftest.py new file mode 100644 index 000000000..a111e9923 --- /dev/null +++ b/tests/openai_agents/e2e/conftest.py @@ -0,0 +1,9 @@ +from datetime import timedelta + +import pytest +from temporalio.contrib.openai_agents import ModelActivityParameters, OpenAIAgentsPlugin + + +@pytest.fixture +def model_provider(): + return None diff --git a/tests/openai_agents/e2e/test_hello_world_workflow_e2e.py b/tests/openai_agents/e2e/test_hello_world_workflow_e2e.py new file mode 100644 index 000000000..9aa16f5df --- /dev/null +++ b/tests/openai_agents/e2e/test_hello_world_workflow_e2e.py @@ -0,0 +1,26 @@ +import uuid +from concurrent.futures import ThreadPoolExecutor + +from temporalio.client import Client +from temporalio.worker import Worker + +from openai_agents.basic.workflows.hello_world_workflow import HelloWorldAgent + + +async def test_execute_workflow(client: Client): + task_queue_name = str(uuid.uuid4()) + + async with Worker( + client, + task_queue=task_queue_name, + workflows=[HelloWorldAgent], + activity_executor=ThreadPoolExecutor(5), + ): + result = await client.execute_workflow( + HelloWorldAgent.run, + "Write a recursive haiku about recursive haikus.", + id=str(uuid.uuid4()), + task_queue=task_queue_name, + ) + assert isinstance(result, str) + assert len(result) > 0 diff --git a/uv.lock b/uv.lock index 73424b77c..594bd343d 100644 --- a/uv.lock +++ b/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 2 +revision = 3 requires-python = ">=3.10" resolution-markers = [ "python_full_version >= '3.13'", @@ -2098,6 +2098,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ac/4b/7c400506ec484ec999b10133aa8e31af39dfc727042dc6944cd45fd927d0/pytest_asyncio-0.18.3-py3-none-any.whl", hash = "sha256:8fafa6c52161addfd41ee7ab35f11836c5a16ec208f93ee388f752bea3493a84", size = 14597, upload-time = "2022-03-25T09:43:57.106Z" }, ] +[[package]] +name = "pytest-mock" +version = "3.15.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/68/14/eb014d26be205d38ad5ad20d9a80f7d201472e08167f0bb4361e251084a9/pytest_mock-3.15.1.tar.gz", hash = "sha256:1849a238f6f396da19762269de72cb1814ab44416fa73a8686deac10b0d87a0f", size = 34036, upload-time = "2025-09-16T16:37:27.081Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/cc/06253936f4a7fa2e0f48dfe6d851d9c56df896a9ab09ac019d70b760619c/pytest_mock-3.15.1-py3-none-any.whl", hash = "sha256:0a25e2eb88fe5168d535041d09a4529a188176ae608a6d249ee65abc0949630d", size = 10095, upload-time = "2025-09-16T16:37:25.734Z" }, +] + [[package]] name = "pytest-pretty" version = "1.3.0" @@ -2651,6 +2663,7 @@ dev = [ { name = "pyright" }, { name = "pytest" }, { name = "pytest-asyncio" }, + { name = "pytest-mock" }, { name = "pytest-pretty" }, { name = "types-pyyaml" }, ] @@ -2718,6 +2731,7 @@ dev = [ { name = "pyright", specifier = ">=1.1.394" }, { name = "pytest", specifier = ">=7.1.2,<8" }, { name = "pytest-asyncio", specifier = ">=0.18.3,<0.19" }, + { name = "pytest-mock", specifier = ">=3.15.1" }, { name = "pytest-pretty", specifier = ">=1.3.0" }, { name = "types-pyyaml", specifier = ">=6.0.12.20241230,<7" }, ] From 85f0c61c976703c60a9fc017dc50d27b463a6890 Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Thu, 23 Oct 2025 14:58:32 -0400 Subject: [PATCH 12/26] hacking --- .../basic/test_hello_world_workflow.py | 57 +++++++++++-------- tests/openai_agents/conftest.py | 22 +++---- 2 files changed, 45 insertions(+), 34 deletions(-) diff --git a/tests/openai_agents/basic/test_hello_world_workflow.py b/tests/openai_agents/basic/test_hello_world_workflow.py index 9f40aceeb..09ef2933f 100644 --- a/tests/openai_agents/basic/test_hello_world_workflow.py +++ b/tests/openai_agents/basic/test_hello_world_workflow.py @@ -8,34 +8,43 @@ from temporalio.worker import Worker from openai_agents.basic.workflows.hello_world_workflow import HelloWorldAgent +from tests.openai_agents.conftest import sequential_test_model @pytest.fixture -def mocked_model(mocker): - mock = mocker.AsyncMock() - mock.get_response.side_effect = [ - ModelResponse( - output=[ - ResponseOutputMessage( - id="1", - content=[ - ResponseOutputText( - annotations=[], - text="This is a haiku (not really)", - type="output_text", - ) - ], - role="assistant", - status="completed", - type="message", - ) - ], - usage=Usage(requests=1, input_tokens=1, output_tokens=1, total_tokens=1), - response_id="1", - ) - ] +def test_model(): + return sequential_test_model( + [ + ModelResponse( + output=[ + ResponseOutputMessage( + id="1", + content=[ + ResponseOutputText( + annotations=[], + text="This is a haiku (not really)", + type="output_text", + ) + ], + role="assistant", + status="completed", + type="message", + ) + ], + usage=Usage( + requests=1, input_tokens=1, output_tokens=1, total_tokens=1 + ), + response_id="1", + ) + ] + ) + - return mock +@pytest.fixture +def test_model(): + return TestModel.returning_responses( + [ResponseBuilders.output_message("This is a haiku (not really)")] + ) async def test_execute_workflow(client: Client): diff --git a/tests/openai_agents/conftest.py b/tests/openai_agents/conftest.py index 1a29bf4e3..ac16d07f5 100644 --- a/tests/openai_agents/conftest.py +++ b/tests/openai_agents/conftest.py @@ -2,21 +2,23 @@ from typing import Optional import pytest -from agents import Model, ModelProvider -from temporalio.contrib.openai_agents import ModelActivityParameters, OpenAIAgentsPlugin +from agents import ModelProvider, ModelResponse +from temporalio.contrib.openai_agents import ( + ModelActivityParameters, + OpenAIAgentsPlugin, + TestModel, + TestModelProvider, +) -class MockedModelProvider(ModelProvider): - def __init__(self, mocked_model): - self.mocked_model = mocked_model - - def get_model(self, model_name: str | None) -> Model: - return self.mocked_model +def sequential_test_model(responses: list[ModelResponse]) -> TestModel: + responses = iter(responses) + return TestModel(lambda: next(responses)) @pytest.fixture -def model_provider(mocked_model): - return MockedModelProvider(mocked_model) +def model_provider(test_model): + return TestModelProvider(test_model) @pytest.fixture From f5b95f1dc1cbfefaee2ce78ce76a3f0cabc77cf4 Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Mon, 27 Oct 2025 17:27:48 -0400 Subject: [PATCH 13/26] cleanup fixture spaghetti --- tests/conftest.py | 18 ++--- .../basic/test_hello_world_workflow.py | 69 ++++++------------- tests/openai_agents/conftest.py | 33 --------- tests/openai_agents/e2e/conftest.py | 9 --- 4 files changed, 25 insertions(+), 104 deletions(-) delete mode 100644 tests/openai_agents/conftest.py delete mode 100644 tests/openai_agents/e2e/conftest.py diff --git a/tests/conftest.py b/tests/conftest.py index 44645c6f3..65de246ea 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -37,15 +37,8 @@ def event_loop(): loop.close() -@pytest.fixture -def plugins(): - # By default, no plugins. - # Other tests can override this fixture, such as in tests/openai_agents/conftest.py - return [] - - -@pytest_asyncio.fixture -async def env(request, plugins) -> AsyncGenerator[WorkflowEnvironment, None]: +@pytest_asyncio.fixture(scope="session") +async def env(request) -> AsyncGenerator[WorkflowEnvironment, None]: env_type = request.config.getoption("--workflow-environment") if env_type == "local": env = await WorkflowEnvironment.start_local( @@ -54,15 +47,12 @@ async def env(request, plugins) -> AsyncGenerator[WorkflowEnvironment, None]: "frontend.enableExecuteMultiOperation=true", "--dynamic-config-value", "system.enableEagerWorkflowStart=true", - ], - plugins=plugins, + ] ) elif env_type == "time-skipping": env = await WorkflowEnvironment.start_time_skipping() else: - env = WorkflowEnvironment.from_client( - await Client.connect(env_type, plugins=plugins) - ) + env = WorkflowEnvironment.from_client(await Client.connect(env_type)) yield env await env.shutdown() diff --git a/tests/openai_agents/basic/test_hello_world_workflow.py b/tests/openai_agents/basic/test_hello_world_workflow.py index 09ef2933f..634b60743 100644 --- a/tests/openai_agents/basic/test_hello_world_workflow.py +++ b/tests/openai_agents/basic/test_hello_world_workflow.py @@ -1,47 +1,18 @@ import uuid from concurrent.futures import ThreadPoolExecutor -import pytest -from agents import ModelResponse, Usage -from openai.types.responses import ResponseOutputMessage, ResponseOutputText from temporalio.client import Client from temporalio.worker import Worker +from temporalio.contrib.openai_agents.testing import ( + AgentEnvironment, + ResponseBuilders, + TestModel, +) from openai_agents.basic.workflows.hello_world_workflow import HelloWorldAgent -from tests.openai_agents.conftest import sequential_test_model -@pytest.fixture -def test_model(): - return sequential_test_model( - [ - ModelResponse( - output=[ - ResponseOutputMessage( - id="1", - content=[ - ResponseOutputText( - annotations=[], - text="This is a haiku (not really)", - type="output_text", - ) - ], - role="assistant", - status="completed", - type="message", - ) - ], - usage=Usage( - requests=1, input_tokens=1, output_tokens=1, total_tokens=1 - ), - response_id="1", - ) - ] - ) - - -@pytest.fixture -def test_model(): +def haiku_test_model(): return TestModel.returning_responses( [ResponseBuilders.output_message("This is a haiku (not really)")] ) @@ -50,17 +21,19 @@ def test_model(): async def test_execute_workflow(client: Client): task_queue_name = str(uuid.uuid4()) - async with Worker( - client, - task_queue=task_queue_name, - workflows=[HelloWorldAgent], - activity_executor=ThreadPoolExecutor(5), - ): - result = await client.execute_workflow( - HelloWorldAgent.run, - "Write a recursive haiku about recursive haikus.", - id=str(uuid.uuid4()), + async with AgentEnvironment(model=haiku_test_model()) as agent_env: + client = agent_env.applied_on_client(client) + async with Worker( + client, task_queue=task_queue_name, - ) - assert isinstance(result, str) - assert len(result) > 0 + workflows=[HelloWorldAgent], + activity_executor=ThreadPoolExecutor(5), + ): + result = await client.execute_workflow( + HelloWorldAgent.run, + "Write a recursive haiku about recursive haikus.", + id=str(uuid.uuid4()), + task_queue=task_queue_name, + ) + assert isinstance(result, str) + assert len(result) > 0 diff --git a/tests/openai_agents/conftest.py b/tests/openai_agents/conftest.py deleted file mode 100644 index ac16d07f5..000000000 --- a/tests/openai_agents/conftest.py +++ /dev/null @@ -1,33 +0,0 @@ -from datetime import timedelta -from typing import Optional - -import pytest -from agents import ModelProvider, ModelResponse -from temporalio.contrib.openai_agents import ( - ModelActivityParameters, - OpenAIAgentsPlugin, - TestModel, - TestModelProvider, -) - - -def sequential_test_model(responses: list[ModelResponse]) -> TestModel: - responses = iter(responses) - return TestModel(lambda: next(responses)) - - -@pytest.fixture -def model_provider(test_model): - return TestModelProvider(test_model) - - -@pytest.fixture -def plugins(model_provider: Optional[ModelProvider]): - return [ - OpenAIAgentsPlugin( - model_params=ModelActivityParameters( - start_to_close_timeout=timedelta(seconds=30) - ), - model_provider=model_provider, - ) - ] diff --git a/tests/openai_agents/e2e/conftest.py b/tests/openai_agents/e2e/conftest.py deleted file mode 100644 index a111e9923..000000000 --- a/tests/openai_agents/e2e/conftest.py +++ /dev/null @@ -1,9 +0,0 @@ -from datetime import timedelta - -import pytest -from temporalio.contrib.openai_agents import ModelActivityParameters, OpenAIAgentsPlugin - - -@pytest.fixture -def model_provider(): - return None From bcf97fa5cf215e5b7ce3c440d9de0f85d23617d3 Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Mon, 27 Oct 2025 17:29:35 -0400 Subject: [PATCH 14/26] Assert real equality on mock test --- tests/openai_agents/basic/test_hello_world_workflow.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/openai_agents/basic/test_hello_world_workflow.py b/tests/openai_agents/basic/test_hello_world_workflow.py index 634b60743..a7004b5e0 100644 --- a/tests/openai_agents/basic/test_hello_world_workflow.py +++ b/tests/openai_agents/basic/test_hello_world_workflow.py @@ -35,5 +35,4 @@ async def test_execute_workflow(client: Client): id=str(uuid.uuid4()), task_queue=task_queue_name, ) - assert isinstance(result, str) - assert len(result) > 0 + assert result == "This is a haiku (not really)" From fd8f26a2abb47cd076901accae4071bd0298a9bb Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Mon, 27 Oct 2025 17:31:40 -0400 Subject: [PATCH 15/26] rename --- tests/openai_agents/basic/test_hello_world_workflow.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/openai_agents/basic/test_hello_world_workflow.py b/tests/openai_agents/basic/test_hello_world_workflow.py index a7004b5e0..4406a1de5 100644 --- a/tests/openai_agents/basic/test_hello_world_workflow.py +++ b/tests/openai_agents/basic/test_hello_world_workflow.py @@ -12,7 +12,7 @@ from openai_agents.basic.workflows.hello_world_workflow import HelloWorldAgent -def haiku_test_model(): +def hello_world_test_model(): return TestModel.returning_responses( [ResponseBuilders.output_message("This is a haiku (not really)")] ) @@ -21,7 +21,7 @@ def haiku_test_model(): async def test_execute_workflow(client: Client): task_queue_name = str(uuid.uuid4()) - async with AgentEnvironment(model=haiku_test_model()) as agent_env: + async with AgentEnvironment(model=hello_world_test_model()) as agent_env: client = agent_env.applied_on_client(client) async with Worker( client, From cd11f78055604055504d89a2ec17e84f50a991ae Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Mon, 27 Oct 2025 17:43:50 -0400 Subject: [PATCH 16/26] upgrade more tests --- .../basic/test_agent_lifecycle_workflow.py | 41 ++++++---- .../test_dynamic_system_prompt_workflow.py | 73 ++++++++++-------- .../basic/test_lifecycle_workflow.py | 41 ++++++---- .../basic/test_local_image_workflow.py | 73 ++++++++++-------- .../basic/test_non_strict_output_workflow.py | 64 ++++++++------- .../test_previous_response_id_workflow.py | 66 +++++++++------- .../basic/test_remote_image_workflow.py | 77 +++++++++++-------- .../basic/test_tools_workflow.py | 40 ++++++---- 8 files changed, 279 insertions(+), 196 deletions(-) diff --git a/tests/openai_agents/basic/test_agent_lifecycle_workflow.py b/tests/openai_agents/basic/test_agent_lifecycle_workflow.py index 97621ea0a..ad2c3f5dc 100644 --- a/tests/openai_agents/basic/test_agent_lifecycle_workflow.py +++ b/tests/openai_agents/basic/test_agent_lifecycle_workflow.py @@ -2,6 +2,7 @@ from concurrent.futures import ThreadPoolExecutor from temporalio.client import Client +from temporalio.contrib.openai_agents.testing import AgentEnvironment, ResponseBuilders, TestModel from temporalio.worker import Worker from openai_agents.basic.workflows.agent_lifecycle_workflow import ( @@ -9,24 +10,32 @@ ) +def agent_lifecycle_test_model(): + return TestModel.returning_responses( + [ResponseBuilders.output_message('{"number": 10}')] + ) + + async def test_execute_workflow(client: Client): task_queue_name = str(uuid.uuid4()) - async with Worker( - client, - task_queue=task_queue_name, - workflows=[AgentLifecycleWorkflow], - activity_executor=ThreadPoolExecutor(5), - ): - result = await client.execute_workflow( - AgentLifecycleWorkflow.run, - 10, # max_number parameter - id=str(uuid.uuid4()), + async with AgentEnvironment(model=agent_lifecycle_test_model()) as agent_env: + client = agent_env.applied_on_client(client) + async with Worker( + client, task_queue=task_queue_name, - ) + workflows=[AgentLifecycleWorkflow], + activity_executor=ThreadPoolExecutor(5), + ): + result = await client.execute_workflow( + AgentLifecycleWorkflow.run, + 10, # max_number parameter + id=str(uuid.uuid4()), + task_queue=task_queue_name, + ) - # Verify the result has the expected structure - assert isinstance(result.number, int) - assert ( - 0 <= result.number <= 20 - ) # Should be between 0 and max*2 due to multiply operation + # Verify the result has the expected structure + assert isinstance(result.number, int) + assert ( + 0 <= result.number <= 20 + ) # Should be between 0 and max*2 due to multiply operation diff --git a/tests/openai_agents/basic/test_dynamic_system_prompt_workflow.py b/tests/openai_agents/basic/test_dynamic_system_prompt_workflow.py index 424bd7d6f..912a89838 100644 --- a/tests/openai_agents/basic/test_dynamic_system_prompt_workflow.py +++ b/tests/openai_agents/basic/test_dynamic_system_prompt_workflow.py @@ -2,6 +2,7 @@ from concurrent.futures import ThreadPoolExecutor from temporalio.client import Client +from temporalio.contrib.openai_agents.testing import AgentEnvironment, ResponseBuilders, TestModel from temporalio.worker import Worker from openai_agents.basic.workflows.dynamic_system_prompt_workflow import ( @@ -9,44 +10,54 @@ ) +def dynamic_system_prompt_test_model(): + return TestModel.returning_responses( + [ResponseBuilders.output_message("Style: haiku\nResponse: The weather is cloudy with a chance of meatballs.")] + ) + + async def test_execute_workflow_with_random_style(client: Client): task_queue_name = str(uuid.uuid4()) - async with Worker( - client, - task_queue=task_queue_name, - workflows=[DynamicSystemPromptWorkflow], - activity_executor=ThreadPoolExecutor(5), - ): - result = await client.execute_workflow( - DynamicSystemPromptWorkflow.run, - "Tell me about the weather today.", - id=str(uuid.uuid4()), + async with AgentEnvironment(model=dynamic_system_prompt_test_model()) as agent_env: + client = agent_env.applied_on_client(client) + async with Worker( + client, task_queue=task_queue_name, - ) - - # Verify the result has the expected format - assert "Style:" in result - assert "Response:" in result - assert any(style in result for style in ["haiku", "pirate", "robot"]) + workflows=[DynamicSystemPromptWorkflow], + activity_executor=ThreadPoolExecutor(5), + ): + result = await client.execute_workflow( + DynamicSystemPromptWorkflow.run, + "Tell me about the weather today.", + id=str(uuid.uuid4()), + task_queue=task_queue_name, + ) + + # Verify the result has the expected format + assert "Style:" in result + assert "Response:" in result + assert any(style in result for style in ["haiku", "pirate", "robot"]) async def test_execute_workflow_with_specific_style(client: Client): task_queue_name = str(uuid.uuid4()) - async with Worker( - client, - task_queue=task_queue_name, - workflows=[DynamicSystemPromptWorkflow], - activity_executor=ThreadPoolExecutor(5), - ): - result = await client.execute_workflow( - DynamicSystemPromptWorkflow.run, - args=["Tell me about the weather today.", "haiku"], - id=str(uuid.uuid4()), + async with AgentEnvironment(model=dynamic_system_prompt_test_model()) as agent_env: + client = agent_env.applied_on_client(client) + async with Worker( + client, task_queue=task_queue_name, - ) - - # Verify the result has the expected format and style - assert "Style: haiku" in result - assert "Response:" in result + workflows=[DynamicSystemPromptWorkflow], + activity_executor=ThreadPoolExecutor(5), + ): + result = await client.execute_workflow( + DynamicSystemPromptWorkflow.run, + args=["Tell me about the weather today.", "haiku"], + id=str(uuid.uuid4()), + task_queue=task_queue_name, + ) + + # Verify the result has the expected format and style + assert "Style: haiku" in result + assert "Response:" in result diff --git a/tests/openai_agents/basic/test_lifecycle_workflow.py b/tests/openai_agents/basic/test_lifecycle_workflow.py index b115ac571..920500964 100644 --- a/tests/openai_agents/basic/test_lifecycle_workflow.py +++ b/tests/openai_agents/basic/test_lifecycle_workflow.py @@ -2,29 +2,38 @@ from concurrent.futures import ThreadPoolExecutor from temporalio.client import Client +from temporalio.contrib.openai_agents.testing import AgentEnvironment, ResponseBuilders, TestModel from temporalio.worker import Worker from openai_agents.basic.workflows.lifecycle_workflow import LifecycleWorkflow +def lifecycle_test_model(): + return TestModel.returning_responses( + [ResponseBuilders.output_message('{"number": 10}')] + ) + + async def test_execute_workflow(client: Client): task_queue_name = str(uuid.uuid4()) - async with Worker( - client, - task_queue=task_queue_name, - workflows=[LifecycleWorkflow], - activity_executor=ThreadPoolExecutor(5), - ): - result = await client.execute_workflow( - LifecycleWorkflow.run, - 10, # max_number parameter - id=str(uuid.uuid4()), + async with AgentEnvironment(model=lifecycle_test_model()) as agent_env: + client = agent_env.applied_on_client(client) + async with Worker( + client, task_queue=task_queue_name, - ) + workflows=[LifecycleWorkflow], + activity_executor=ThreadPoolExecutor(5), + ): + result = await client.execute_workflow( + LifecycleWorkflow.run, + 10, # max_number parameter + id=str(uuid.uuid4()), + task_queue=task_queue_name, + ) - # Verify the result has the expected structure - assert isinstance(result.number, int) - assert ( - 0 <= result.number <= 20 - ) # Should be between 0 and max*2 due to multiply operation + # Verify the result has the expected structure + assert isinstance(result.number, int) + assert ( + 0 <= result.number <= 20 + ) # Should be between 0 and max*2 due to multiply operation diff --git a/tests/openai_agents/basic/test_local_image_workflow.py b/tests/openai_agents/basic/test_local_image_workflow.py index 7062becc3..5a8d44136 100644 --- a/tests/openai_agents/basic/test_local_image_workflow.py +++ b/tests/openai_agents/basic/test_local_image_workflow.py @@ -2,52 +2,63 @@ from concurrent.futures import ThreadPoolExecutor from temporalio.client import Client +from temporalio.contrib.openai_agents.testing import AgentEnvironment, ResponseBuilders, TestModel from temporalio.worker import Worker from openai_agents.basic.activities.image_activities import read_image_as_base64 from openai_agents.basic.workflows.local_image_workflow import LocalImageWorkflow +def local_image_test_model(): + return TestModel.returning_responses( + [ResponseBuilders.output_message("I can see a bison in the image.")] + ) + + async def test_execute_workflow_default_question(client: Client): task_queue_name = str(uuid.uuid4()) - async with Worker( - client, - task_queue=task_queue_name, - workflows=[LocalImageWorkflow], - activity_executor=ThreadPoolExecutor(5), - activities=[read_image_as_base64], - ): - result = await client.execute_workflow( - LocalImageWorkflow.run, - "openai_agents/basic/media/image_bison.jpg", # Path to test image - id=str(uuid.uuid4()), + async with AgentEnvironment(model=local_image_test_model()) as agent_env: + client = agent_env.applied_on_client(client) + async with Worker( + client, task_queue=task_queue_name, - ) + workflows=[LocalImageWorkflow], + activity_executor=ThreadPoolExecutor(5), + activities=[read_image_as_base64], + ): + result = await client.execute_workflow( + LocalImageWorkflow.run, + "openai_agents/basic/media/image_bison.jpg", # Path to test image + id=str(uuid.uuid4()), + task_queue=task_queue_name, + ) - # Verify the result is a string response - assert isinstance(result, str) - assert len(result) > 0 + # Verify the result is a string response + assert isinstance(result, str) + assert len(result) > 0 async def test_execute_workflow_custom_question(client: Client): task_queue_name = str(uuid.uuid4()) - async with Worker( - client, - task_queue=task_queue_name, - workflows=[LocalImageWorkflow], - activity_executor=ThreadPoolExecutor(5), - activities=[read_image_as_base64], - ): - custom_question = "What animals do you see in this image?" - result = await client.execute_workflow( - LocalImageWorkflow.run, - args=["openai_agents/basic/media/image_bison.jpg", custom_question], - id=str(uuid.uuid4()), + async with AgentEnvironment(model=local_image_test_model()) as agent_env: + client = agent_env.applied_on_client(client) + async with Worker( + client, task_queue=task_queue_name, - ) + workflows=[LocalImageWorkflow], + activity_executor=ThreadPoolExecutor(5), + activities=[read_image_as_base64], + ): + custom_question = "What animals do you see in this image?" + result = await client.execute_workflow( + LocalImageWorkflow.run, + args=["openai_agents/basic/media/image_bison.jpg", custom_question], + id=str(uuid.uuid4()), + task_queue=task_queue_name, + ) - # Verify the result is a string response - assert isinstance(result, str) - assert len(result) > 0 + # Verify the result is a string response + assert isinstance(result, str) + assert len(result) > 0 diff --git a/tests/openai_agents/basic/test_non_strict_output_workflow.py b/tests/openai_agents/basic/test_non_strict_output_workflow.py index 5b5ec8446..85689adf2 100644 --- a/tests/openai_agents/basic/test_non_strict_output_workflow.py +++ b/tests/openai_agents/basic/test_non_strict_output_workflow.py @@ -2,6 +2,7 @@ from concurrent.futures import ThreadPoolExecutor from temporalio.client import Client +from temporalio.contrib.openai_agents.testing import AgentEnvironment, ResponseBuilders, TestModel from temporalio.worker import Worker from openai_agents.basic.workflows.non_strict_output_workflow import ( @@ -9,34 +10,43 @@ ) +def non_strict_output_test_model(): + return TestModel.returning_responses( + [ResponseBuilders.output_message('{"jokes": {"1": "Why do programmers prefer dark mode? Because light attracts bugs!", "2": "How many programmers does it take to change a light bulb? None, that\'s a hardware problem.", "3": "Why do Java developers wear glasses? Because they can\'t C#!"}}') + ] + ) + + async def test_execute_workflow(client: Client): task_queue_name = str(uuid.uuid4()) - async with Worker( - client, - task_queue=task_queue_name, - workflows=[NonStrictOutputWorkflow], - activity_executor=ThreadPoolExecutor(5), - # No external activities needed - ): - result = await client.execute_workflow( - NonStrictOutputWorkflow.run, - "Tell me 3 funny jokes about programming.", - id=str(uuid.uuid4()), + async with AgentEnvironment(model=non_strict_output_test_model()) as agent_env: + client = agent_env.applied_on_client(client) + async with Worker( + client, task_queue=task_queue_name, - ) - - # Verify the result has the expected structure - assert isinstance(result, dict) - - assert "strict_error" in result - assert "non_strict_result" in result - - # If there's a strict_error, it should be a string - if "strict_error" in result: - assert isinstance(result["strict_error"], str) - assert len(result["strict_error"]) > 0 - - jokes = result["non_strict_result"]["jokes"] - assert isinstance(jokes, dict) - assert isinstance(jokes[list(jokes.keys())[0]], str) + workflows=[NonStrictOutputWorkflow], + activity_executor=ThreadPoolExecutor(5), + # No external activities needed + ): + result = await client.execute_workflow( + NonStrictOutputWorkflow.run, + "Tell me 3 funny jokes about programming.", + id=str(uuid.uuid4()), + task_queue=task_queue_name, + ) + + # Verify the result has the expected structure + assert isinstance(result, dict) + + assert "strict_error" in result + assert "non_strict_result" in result + + # If there's a strict_error, it should be a string + if "strict_error" in result: + assert isinstance(result["strict_error"], str) + assert len(result["strict_error"]) > 0 + + jokes = result["non_strict_result"]["jokes"] + assert isinstance(jokes, dict) + assert isinstance(jokes[list(jokes.keys())[0]], str) diff --git a/tests/openai_agents/basic/test_previous_response_id_workflow.py b/tests/openai_agents/basic/test_previous_response_id_workflow.py index 80e311f57..5d962d276 100644 --- a/tests/openai_agents/basic/test_previous_response_id_workflow.py +++ b/tests/openai_agents/basic/test_previous_response_id_workflow.py @@ -2,6 +2,7 @@ from concurrent.futures import ThreadPoolExecutor from temporalio.client import Client +from temporalio.contrib.openai_agents.testing import AgentEnvironment, ResponseBuilders, TestModel from temporalio.worker import Worker from openai_agents.basic.workflows.previous_response_id_workflow import ( @@ -9,34 +10,45 @@ ) +def previous_response_id_test_model(): + return TestModel.returning_responses( + [ + ResponseBuilders.output_message("The capital of France is Paris."), + ResponseBuilders.output_message("Paris has a population of approximately 2.1 million people within the city proper.") + ] + ) + + async def test_execute_workflow(client: Client): task_queue_name = str(uuid.uuid4()) - async with Worker( - client, - task_queue=task_queue_name, - workflows=[PreviousResponseIdWorkflow], - activity_executor=ThreadPoolExecutor(5), - ): - first_question = "What is the capital of France?" - follow_up_question = "What is the population of that city?" - - result = await client.execute_workflow( - PreviousResponseIdWorkflow.run, - args=[first_question, follow_up_question], - id=str(uuid.uuid4()), + async with AgentEnvironment(model=previous_response_id_test_model()) as agent_env: + client = agent_env.applied_on_client(client) + async with Worker( + client, task_queue=task_queue_name, - ) - - # Verify the result is a tuple with two string responses - assert isinstance(result, tuple) - assert len(result) == 2 - - first_response, second_response = result - assert isinstance(first_response, str) - assert isinstance(second_response, str) - assert len(first_response) > 0 - assert len(second_response) > 0 - - # The responses should be different (not identical) - assert first_response != second_response + workflows=[PreviousResponseIdWorkflow], + activity_executor=ThreadPoolExecutor(5), + ): + first_question = "What is the capital of France?" + follow_up_question = "What is the population of that city?" + + result = await client.execute_workflow( + PreviousResponseIdWorkflow.run, + args=[first_question, follow_up_question], + id=str(uuid.uuid4()), + task_queue=task_queue_name, + ) + + # Verify the result is a tuple with two string responses + assert isinstance(result, tuple) + assert len(result) == 2 + + first_response, second_response = result + assert isinstance(first_response, str) + assert isinstance(second_response, str) + assert len(first_response) > 0 + assert len(second_response) > 0 + + # The responses should be different (not identical) + assert first_response != second_response diff --git a/tests/openai_agents/basic/test_remote_image_workflow.py b/tests/openai_agents/basic/test_remote_image_workflow.py index 0f1cb24e1..12505b66a 100644 --- a/tests/openai_agents/basic/test_remote_image_workflow.py +++ b/tests/openai_agents/basic/test_remote_image_workflow.py @@ -2,53 +2,64 @@ from concurrent.futures import ThreadPoolExecutor from temporalio.client import Client +from temporalio.contrib.openai_agents.testing import AgentEnvironment, ResponseBuilders, TestModel from temporalio.worker import Worker from openai_agents.basic.workflows.remote_image_workflow import RemoteImageWorkflow +def remote_image_test_model(): + return TestModel.returning_responses( + [ResponseBuilders.output_message("I can see the Golden Gate Bridge, a beautiful suspension bridge in San Francisco.")] + ) + + async def test_execute_workflow_default_question(client: Client): task_queue_name = str(uuid.uuid4()) - async with Worker( - client, - task_queue=task_queue_name, - workflows=[RemoteImageWorkflow], - activity_executor=ThreadPoolExecutor(5), - ): - test_image_url = "https://upload.wikimedia.org/wikipedia/commons/0/0c/GoldenGateBridge-001.jpg" - - result = await client.execute_workflow( - RemoteImageWorkflow.run, - test_image_url, - id=str(uuid.uuid4()), + async with AgentEnvironment(model=remote_image_test_model()) as agent_env: + client = agent_env.applied_on_client(client) + async with Worker( + client, task_queue=task_queue_name, - ) + workflows=[RemoteImageWorkflow], + activity_executor=ThreadPoolExecutor(5), + ): + test_image_url = "https://upload.wikimedia.org/wikipedia/commons/0/0c/GoldenGateBridge-001.jpg" - # Verify the result is a string response - assert isinstance(result, str) - assert len(result) > 0 + result = await client.execute_workflow( + RemoteImageWorkflow.run, + test_image_url, + id=str(uuid.uuid4()), + task_queue=task_queue_name, + ) + + # Verify the result is a string response + assert isinstance(result, str) + assert len(result) > 0 async def test_execute_workflow_custom_question(client: Client): task_queue_name = str(uuid.uuid4()) - async with Worker( - client, - task_queue=task_queue_name, - workflows=[RemoteImageWorkflow], - activity_executor=ThreadPoolExecutor(5), - ): - test_image_url = "https://upload.wikimedia.org/wikipedia/commons/0/0c/GoldenGateBridge-001.jpg" - custom_question = "What do you see in this image?" - - result = await client.execute_workflow( - RemoteImageWorkflow.run, - args=[test_image_url, custom_question], - id=str(uuid.uuid4()), + async with AgentEnvironment(model=remote_image_test_model()) as agent_env: + client = agent_env.applied_on_client(client) + async with Worker( + client, task_queue=task_queue_name, - ) + workflows=[RemoteImageWorkflow], + activity_executor=ThreadPoolExecutor(5), + ): + test_image_url = "https://upload.wikimedia.org/wikipedia/commons/0/0c/GoldenGateBridge-001.jpg" + custom_question = "What do you see in this image?" + + result = await client.execute_workflow( + RemoteImageWorkflow.run, + args=[test_image_url, custom_question], + id=str(uuid.uuid4()), + task_queue=task_queue_name, + ) - # Verify the result is a string response - assert isinstance(result, str) - assert len(result) > 0 + # Verify the result is a string response + assert isinstance(result, str) + assert len(result) > 0 diff --git a/tests/openai_agents/basic/test_tools_workflow.py b/tests/openai_agents/basic/test_tools_workflow.py index 591ca7fdc..1875e0361 100644 --- a/tests/openai_agents/basic/test_tools_workflow.py +++ b/tests/openai_agents/basic/test_tools_workflow.py @@ -2,29 +2,39 @@ from concurrent.futures import ThreadPoolExecutor from temporalio.client import Client +from temporalio.contrib.openai_agents.testing import AgentEnvironment, ResponseBuilders, TestModel from temporalio.worker import Worker from openai_agents.basic.activities.get_weather_activity import get_weather from openai_agents.basic.workflows.tools_workflow import ToolsWorkflow +def tools_test_model(): + return TestModel.returning_responses( + [ResponseBuilders.tool_call_message("get_weather", {"city": "New York"}), + ResponseBuilders.output_message("The weather in New York is sunny with a temperature of 75°F.")] + ) + + async def test_execute_workflow(client: Client): task_queue_name = str(uuid.uuid4()) - async with Worker( - client, - task_queue=task_queue_name, - workflows=[ToolsWorkflow], - activity_executor=ThreadPoolExecutor(5), - activities=[get_weather], - ): - result = await client.execute_workflow( - ToolsWorkflow.run, - "What's the weather like in New York?", - id=str(uuid.uuid4()), + async with AgentEnvironment(model=tools_test_model()) as agent_env: + client = agent_env.applied_on_client(client) + async with Worker( + client, task_queue=task_queue_name, - ) + workflows=[ToolsWorkflow], + activity_executor=ThreadPoolExecutor(5), + activities=[get_weather], + ): + result = await client.execute_workflow( + ToolsWorkflow.run, + "What's the weather like in New York?", + id=str(uuid.uuid4()), + task_queue=task_queue_name, + ) - # Verify the result is a string response - assert isinstance(result, str) - assert len(result) > 0 + # Verify the result is a string response + assert isinstance(result, str) + assert len(result) > 0 From 094072b0dd74ce9fdd5f7a537d1fe335d07bc48b Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Mon, 27 Oct 2025 17:45:49 -0400 Subject: [PATCH 17/26] fix tools test --- tests/openai_agents/basic/test_tools_workflow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/openai_agents/basic/test_tools_workflow.py b/tests/openai_agents/basic/test_tools_workflow.py index 1875e0361..ee2d8a79a 100644 --- a/tests/openai_agents/basic/test_tools_workflow.py +++ b/tests/openai_agents/basic/test_tools_workflow.py @@ -11,7 +11,7 @@ def tools_test_model(): return TestModel.returning_responses( - [ResponseBuilders.tool_call_message("get_weather", {"city": "New York"}), + [ResponseBuilders.tool_call('{"city": "New York"}', "get_weather"), ResponseBuilders.output_message("The weather in New York is sunny with a temperature of 75°F.")] ) From 842a6a07f4324d3f668d324d24f54e763bfe04e7 Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Thu, 30 Oct 2025 14:00:04 -0400 Subject: [PATCH 18/26] format --- .../basic/test_agent_lifecycle_workflow.py | 6 +++++- .../basic/test_dynamic_system_prompt_workflow.py | 12 ++++++++++-- .../basic/test_hello_world_workflow.py | 2 +- .../openai_agents/basic/test_lifecycle_workflow.py | 6 +++++- .../basic/test_local_image_workflow.py | 6 +++++- .../basic/test_non_strict_output_workflow.py | 11 +++++++++-- .../basic/test_previous_response_id_workflow.py | 10 ++++++++-- .../basic/test_remote_image_workflow.py | 12 ++++++++++-- tests/openai_agents/basic/test_tools_workflow.py | 14 +++++++++++--- 9 files changed, 64 insertions(+), 15 deletions(-) diff --git a/tests/openai_agents/basic/test_agent_lifecycle_workflow.py b/tests/openai_agents/basic/test_agent_lifecycle_workflow.py index ad2c3f5dc..8537f0f7f 100644 --- a/tests/openai_agents/basic/test_agent_lifecycle_workflow.py +++ b/tests/openai_agents/basic/test_agent_lifecycle_workflow.py @@ -2,7 +2,11 @@ from concurrent.futures import ThreadPoolExecutor from temporalio.client import Client -from temporalio.contrib.openai_agents.testing import AgentEnvironment, ResponseBuilders, TestModel +from temporalio.contrib.openai_agents.testing import ( + AgentEnvironment, + ResponseBuilders, + TestModel, +) from temporalio.worker import Worker from openai_agents.basic.workflows.agent_lifecycle_workflow import ( diff --git a/tests/openai_agents/basic/test_dynamic_system_prompt_workflow.py b/tests/openai_agents/basic/test_dynamic_system_prompt_workflow.py index 912a89838..fb4f564b6 100644 --- a/tests/openai_agents/basic/test_dynamic_system_prompt_workflow.py +++ b/tests/openai_agents/basic/test_dynamic_system_prompt_workflow.py @@ -2,7 +2,11 @@ from concurrent.futures import ThreadPoolExecutor from temporalio.client import Client -from temporalio.contrib.openai_agents.testing import AgentEnvironment, ResponseBuilders, TestModel +from temporalio.contrib.openai_agents.testing import ( + AgentEnvironment, + ResponseBuilders, + TestModel, +) from temporalio.worker import Worker from openai_agents.basic.workflows.dynamic_system_prompt_workflow import ( @@ -12,7 +16,11 @@ def dynamic_system_prompt_test_model(): return TestModel.returning_responses( - [ResponseBuilders.output_message("Style: haiku\nResponse: The weather is cloudy with a chance of meatballs.")] + [ + ResponseBuilders.output_message( + "Style: haiku\nResponse: The weather is cloudy with a chance of meatballs." + ) + ] ) diff --git a/tests/openai_agents/basic/test_hello_world_workflow.py b/tests/openai_agents/basic/test_hello_world_workflow.py index 4406a1de5..3c2463ae8 100644 --- a/tests/openai_agents/basic/test_hello_world_workflow.py +++ b/tests/openai_agents/basic/test_hello_world_workflow.py @@ -2,12 +2,12 @@ from concurrent.futures import ThreadPoolExecutor from temporalio.client import Client -from temporalio.worker import Worker from temporalio.contrib.openai_agents.testing import ( AgentEnvironment, ResponseBuilders, TestModel, ) +from temporalio.worker import Worker from openai_agents.basic.workflows.hello_world_workflow import HelloWorldAgent diff --git a/tests/openai_agents/basic/test_lifecycle_workflow.py b/tests/openai_agents/basic/test_lifecycle_workflow.py index 920500964..a40b314fe 100644 --- a/tests/openai_agents/basic/test_lifecycle_workflow.py +++ b/tests/openai_agents/basic/test_lifecycle_workflow.py @@ -2,7 +2,11 @@ from concurrent.futures import ThreadPoolExecutor from temporalio.client import Client -from temporalio.contrib.openai_agents.testing import AgentEnvironment, ResponseBuilders, TestModel +from temporalio.contrib.openai_agents.testing import ( + AgentEnvironment, + ResponseBuilders, + TestModel, +) from temporalio.worker import Worker from openai_agents.basic.workflows.lifecycle_workflow import LifecycleWorkflow diff --git a/tests/openai_agents/basic/test_local_image_workflow.py b/tests/openai_agents/basic/test_local_image_workflow.py index 5a8d44136..926ac0164 100644 --- a/tests/openai_agents/basic/test_local_image_workflow.py +++ b/tests/openai_agents/basic/test_local_image_workflow.py @@ -2,7 +2,11 @@ from concurrent.futures import ThreadPoolExecutor from temporalio.client import Client -from temporalio.contrib.openai_agents.testing import AgentEnvironment, ResponseBuilders, TestModel +from temporalio.contrib.openai_agents.testing import ( + AgentEnvironment, + ResponseBuilders, + TestModel, +) from temporalio.worker import Worker from openai_agents.basic.activities.image_activities import read_image_as_base64 diff --git a/tests/openai_agents/basic/test_non_strict_output_workflow.py b/tests/openai_agents/basic/test_non_strict_output_workflow.py index 85689adf2..f202d3a13 100644 --- a/tests/openai_agents/basic/test_non_strict_output_workflow.py +++ b/tests/openai_agents/basic/test_non_strict_output_workflow.py @@ -2,7 +2,11 @@ from concurrent.futures import ThreadPoolExecutor from temporalio.client import Client -from temporalio.contrib.openai_agents.testing import AgentEnvironment, ResponseBuilders, TestModel +from temporalio.contrib.openai_agents.testing import ( + AgentEnvironment, + ResponseBuilders, + TestModel, +) from temporalio.worker import Worker from openai_agents.basic.workflows.non_strict_output_workflow import ( @@ -12,7 +16,10 @@ def non_strict_output_test_model(): return TestModel.returning_responses( - [ResponseBuilders.output_message('{"jokes": {"1": "Why do programmers prefer dark mode? Because light attracts bugs!", "2": "How many programmers does it take to change a light bulb? None, that\'s a hardware problem.", "3": "Why do Java developers wear glasses? Because they can\'t C#!"}}') + [ + ResponseBuilders.output_message( + '{"jokes": {"1": "Why do programmers prefer dark mode? Because light attracts bugs!", "2": "How many programmers does it take to change a light bulb? None, that\'s a hardware problem.", "3": "Why do Java developers wear glasses? Because they can\'t C#!"}}' + ) ] ) diff --git a/tests/openai_agents/basic/test_previous_response_id_workflow.py b/tests/openai_agents/basic/test_previous_response_id_workflow.py index 5d962d276..1a2b63ff2 100644 --- a/tests/openai_agents/basic/test_previous_response_id_workflow.py +++ b/tests/openai_agents/basic/test_previous_response_id_workflow.py @@ -2,7 +2,11 @@ from concurrent.futures import ThreadPoolExecutor from temporalio.client import Client -from temporalio.contrib.openai_agents.testing import AgentEnvironment, ResponseBuilders, TestModel +from temporalio.contrib.openai_agents.testing import ( + AgentEnvironment, + ResponseBuilders, + TestModel, +) from temporalio.worker import Worker from openai_agents.basic.workflows.previous_response_id_workflow import ( @@ -14,7 +18,9 @@ def previous_response_id_test_model(): return TestModel.returning_responses( [ ResponseBuilders.output_message("The capital of France is Paris."), - ResponseBuilders.output_message("Paris has a population of approximately 2.1 million people within the city proper.") + ResponseBuilders.output_message( + "Paris has a population of approximately 2.1 million people within the city proper." + ), ] ) diff --git a/tests/openai_agents/basic/test_remote_image_workflow.py b/tests/openai_agents/basic/test_remote_image_workflow.py index 12505b66a..f6ee99b52 100644 --- a/tests/openai_agents/basic/test_remote_image_workflow.py +++ b/tests/openai_agents/basic/test_remote_image_workflow.py @@ -2,7 +2,11 @@ from concurrent.futures import ThreadPoolExecutor from temporalio.client import Client -from temporalio.contrib.openai_agents.testing import AgentEnvironment, ResponseBuilders, TestModel +from temporalio.contrib.openai_agents.testing import ( + AgentEnvironment, + ResponseBuilders, + TestModel, +) from temporalio.worker import Worker from openai_agents.basic.workflows.remote_image_workflow import RemoteImageWorkflow @@ -10,7 +14,11 @@ def remote_image_test_model(): return TestModel.returning_responses( - [ResponseBuilders.output_message("I can see the Golden Gate Bridge, a beautiful suspension bridge in San Francisco.")] + [ + ResponseBuilders.output_message( + "I can see the Golden Gate Bridge, a beautiful suspension bridge in San Francisco." + ) + ] ) diff --git a/tests/openai_agents/basic/test_tools_workflow.py b/tests/openai_agents/basic/test_tools_workflow.py index ee2d8a79a..0b28bc787 100644 --- a/tests/openai_agents/basic/test_tools_workflow.py +++ b/tests/openai_agents/basic/test_tools_workflow.py @@ -2,7 +2,11 @@ from concurrent.futures import ThreadPoolExecutor from temporalio.client import Client -from temporalio.contrib.openai_agents.testing import AgentEnvironment, ResponseBuilders, TestModel +from temporalio.contrib.openai_agents.testing import ( + AgentEnvironment, + ResponseBuilders, + TestModel, +) from temporalio.worker import Worker from openai_agents.basic.activities.get_weather_activity import get_weather @@ -11,8 +15,12 @@ def tools_test_model(): return TestModel.returning_responses( - [ResponseBuilders.tool_call('{"city": "New York"}', "get_weather"), - ResponseBuilders.output_message("The weather in New York is sunny with a temperature of 75°F.")] + [ + ResponseBuilders.tool_call('{"city": "New York"}', "get_weather"), + ResponseBuilders.output_message( + "The weather in New York is sunny with a temperature of 75°F." + ), + ] ) From 5536859c806222cf029ac83eaf363d6656c70ad7 Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Thu, 6 Nov 2025 12:02:16 -0500 Subject: [PATCH 19/26] fix non strict test --- tests/openai_agents/basic/test_non_strict_output_workflow.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/openai_agents/basic/test_non_strict_output_workflow.py b/tests/openai_agents/basic/test_non_strict_output_workflow.py index f202d3a13..5bebaa1cb 100644 --- a/tests/openai_agents/basic/test_non_strict_output_workflow.py +++ b/tests/openai_agents/basic/test_non_strict_output_workflow.py @@ -15,10 +15,12 @@ def non_strict_output_test_model(): + # NOTE: AgentOutputSchema (used in the workflow definition), has a schema where the outer + # object must be "response". Therefore, mocked model responses must use "response", just as the real model does. return TestModel.returning_responses( [ ResponseBuilders.output_message( - '{"jokes": {"1": "Why do programmers prefer dark mode? Because light attracts bugs!", "2": "How many programmers does it take to change a light bulb? None, that\'s a hardware problem.", "3": "Why do Java developers wear glasses? Because they can\'t C#!"}}' + '{"response": {"jokes": {"1": "Why do programmers prefer dark mode? Because light attracts bugs!", "2": "How many programmers does it take to change a light bulb? None, that\'s a hardware problem.", "3": "Why do Java developers wear glasses? Because they can\'t C#!"}}}' ) ] ) From eb31be236add80a8307c321121d153fe9b3d4c6b Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Thu, 6 Nov 2025 12:08:54 -0500 Subject: [PATCH 20/26] lint --- tests/openai_agents/basic/test_non_strict_output_workflow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/openai_agents/basic/test_non_strict_output_workflow.py b/tests/openai_agents/basic/test_non_strict_output_workflow.py index 5bebaa1cb..bdd3a5a2a 100644 --- a/tests/openai_agents/basic/test_non_strict_output_workflow.py +++ b/tests/openai_agents/basic/test_non_strict_output_workflow.py @@ -16,7 +16,7 @@ def non_strict_output_test_model(): # NOTE: AgentOutputSchema (used in the workflow definition), has a schema where the outer - # object must be "response". Therefore, mocked model responses must use "response", just as the real model does. + # object must be "response". Therefore, mocked model responses must use "response", just as the real model does. return TestModel.returning_responses( [ ResponseBuilders.output_message( From 84b5eeb0828ad9030e1059416ea5c6235050f850 Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Thu, 6 Nov 2025 12:12:54 -0500 Subject: [PATCH 21/26] run it in CI --- pyproject.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 14a04e34b..73007250e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,7 +26,6 @@ dev = [ "types-pyyaml>=6.0.12.20241230,<7", "pytest-pretty>=1.3.0", "poethepoet>=0.36.0", - "pytest-mock>=3.15.1", ] bedrock = ["boto3>=1.34.92,<2"] dsl = [ @@ -123,7 +122,7 @@ build-backend = "hatchling.build" format = [{cmd = "uv run black ."}, {cmd = "uv run isort ."}] lint = [{cmd = "uv run black --check ."}, {cmd = "uv run isort --check-only ."}, {ref = "lint-types" }] lint-types = "uv run --all-groups mypy --check-untyped-defs --namespace-packages ." -test = "uv run --all-groups pytest --ignore=tests/openai_agents" +test = "uv run --all-groups pytest" [tool.pytest.ini_options] asyncio_mode = "auto" From 151e0d51aa4fb470ff594966b6dac9a0e380a3b5 Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Thu, 6 Nov 2025 12:14:40 -0500 Subject: [PATCH 22/26] readme cleanup --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index 3288f85a2..d9ae57a30 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,3 @@ Some examples require extra dependencies. See each sample's directory for specif To run the tests: uv run poe test - -By default, this won't run the OpenAI SDK sample tests. To run those, set your `OPENAI_API_KEY` in your environment, and run: - - uv run poe test tests/openai_agents From 492dc29aefe34705b1354938e4e8706fdfd7c2ab Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Thu, 6 Nov 2025 12:36:47 -0500 Subject: [PATCH 23/26] add local model parameterization --- README.md | 3 +++ .../basic/test_agent_lifecycle_workflow.py | 10 ++++--- .../test_dynamic_system_prompt_workflow.py | 16 +++++++++--- .../basic/test_hello_world_workflow.py | 9 +++++-- .../basic/test_lifecycle_workflow.py | 9 +++++-- .../basic/test_local_image_workflow.py | 16 +++++++++--- .../basic/test_non_strict_output_workflow.py | 9 +++++-- .../test_previous_response_id_workflow.py | 9 +++++-- .../basic/test_remote_image_workflow.py | 16 +++++++++--- .../basic/test_tools_workflow.py | 9 +++++-- .../e2e/test_hello_world_workflow_e2e.py | 26 ------------------- 11 files changed, 81 insertions(+), 51 deletions(-) delete mode 100644 tests/openai_agents/e2e/test_hello_world_workflow_e2e.py diff --git a/README.md b/README.md index d9ae57a30..13f4bf6bb 100644 --- a/README.md +++ b/README.md @@ -90,3 +90,6 @@ Some examples require extra dependencies. See each sample's directory for specif To run the tests: uv run poe test + +Note that this will skip running `openai_agents` tests against real OpenAI API calls if an API key is not found, and use only mocked models. +To run with real model calls, set `OPENAI_API_KEY` in your environment. diff --git a/tests/openai_agents/basic/test_agent_lifecycle_workflow.py b/tests/openai_agents/basic/test_agent_lifecycle_workflow.py index 8537f0f7f..04ec089f8 100644 --- a/tests/openai_agents/basic/test_agent_lifecycle_workflow.py +++ b/tests/openai_agents/basic/test_agent_lifecycle_workflow.py @@ -1,4 +1,6 @@ import uuid +import pytest +import os from concurrent.futures import ThreadPoolExecutor from temporalio.client import Client @@ -19,11 +21,13 @@ def agent_lifecycle_test_model(): [ResponseBuilders.output_message('{"number": 10}')] ) - -async def test_execute_workflow(client: Client): +@pytest.mark.parametrize("mock_model", [True, False]) +async def test_execute_workflow(client: Client, mock_model: bool): task_queue_name = str(uuid.uuid4()) + if not mock_model and not os.environ.get("OPENAI_API_KEY"): + pytest.skip(f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set") - async with AgentEnvironment(model=agent_lifecycle_test_model()) as agent_env: + async with AgentEnvironment(model=agent_lifecycle_test_model() if mock_model else None) as agent_env: client = agent_env.applied_on_client(client) async with Worker( client, diff --git a/tests/openai_agents/basic/test_dynamic_system_prompt_workflow.py b/tests/openai_agents/basic/test_dynamic_system_prompt_workflow.py index fb4f564b6..0af541496 100644 --- a/tests/openai_agents/basic/test_dynamic_system_prompt_workflow.py +++ b/tests/openai_agents/basic/test_dynamic_system_prompt_workflow.py @@ -1,4 +1,6 @@ import uuid +import pytest +import os from concurrent.futures import ThreadPoolExecutor from temporalio.client import Client @@ -24,10 +26,13 @@ def dynamic_system_prompt_test_model(): ) -async def test_execute_workflow_with_random_style(client: Client): +@pytest.mark.parametrize("mock_model", [True, False]) +async def test_execute_workflow_with_random_style(client: Client, mock_model: bool): task_queue_name = str(uuid.uuid4()) + if not mock_model and not os.environ.get("OPENAI_API_KEY"): + pytest.skip(f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set") - async with AgentEnvironment(model=dynamic_system_prompt_test_model()) as agent_env: + async with AgentEnvironment(model=dynamic_system_prompt_test_model() if mock_model else None) as agent_env: client = agent_env.applied_on_client(client) async with Worker( client, @@ -48,10 +53,13 @@ async def test_execute_workflow_with_random_style(client: Client): assert any(style in result for style in ["haiku", "pirate", "robot"]) -async def test_execute_workflow_with_specific_style(client: Client): +@pytest.mark.parametrize("mock_model", [True, False]) +async def test_execute_workflow_with_specific_style(client: Client, mock_model: bool): task_queue_name = str(uuid.uuid4()) + if not mock_model and not os.environ.get("OPENAI_API_KEY"): + pytest.skip(f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set") - async with AgentEnvironment(model=dynamic_system_prompt_test_model()) as agent_env: + async with AgentEnvironment(model=dynamic_system_prompt_test_model() if mock_model else None) as agent_env: client = agent_env.applied_on_client(client) async with Worker( client, diff --git a/tests/openai_agents/basic/test_hello_world_workflow.py b/tests/openai_agents/basic/test_hello_world_workflow.py index 3c2463ae8..238a61799 100644 --- a/tests/openai_agents/basic/test_hello_world_workflow.py +++ b/tests/openai_agents/basic/test_hello_world_workflow.py @@ -1,4 +1,6 @@ import uuid +import pytest +import os from concurrent.futures import ThreadPoolExecutor from temporalio.client import Client @@ -18,10 +20,13 @@ def hello_world_test_model(): ) -async def test_execute_workflow(client: Client): +@pytest.mark.parametrize("mock_model", [True, False]) +async def test_execute_workflow(client: Client, mock_model: bool): task_queue_name = str(uuid.uuid4()) + if not mock_model and not os.environ.get("OPENAI_API_KEY"): + pytest.skip(f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set") - async with AgentEnvironment(model=hello_world_test_model()) as agent_env: + async with AgentEnvironment(model=hello_world_test_model() if mock_model else None) as agent_env: client = agent_env.applied_on_client(client) async with Worker( client, diff --git a/tests/openai_agents/basic/test_lifecycle_workflow.py b/tests/openai_agents/basic/test_lifecycle_workflow.py index a40b314fe..a4f3a4ea0 100644 --- a/tests/openai_agents/basic/test_lifecycle_workflow.py +++ b/tests/openai_agents/basic/test_lifecycle_workflow.py @@ -1,4 +1,6 @@ import uuid +import pytest +import os from concurrent.futures import ThreadPoolExecutor from temporalio.client import Client @@ -18,10 +20,13 @@ def lifecycle_test_model(): ) -async def test_execute_workflow(client: Client): +@pytest.mark.parametrize("mock_model", [True, False]) +async def test_execute_workflow(client: Client, mock_model: bool): task_queue_name = str(uuid.uuid4()) + if not mock_model and not os.environ.get("OPENAI_API_KEY"): + pytest.skip(f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set") - async with AgentEnvironment(model=lifecycle_test_model()) as agent_env: + async with AgentEnvironment(model=lifecycle_test_model() if mock_model else None) as agent_env: client = agent_env.applied_on_client(client) async with Worker( client, diff --git a/tests/openai_agents/basic/test_local_image_workflow.py b/tests/openai_agents/basic/test_local_image_workflow.py index 926ac0164..8d525b0eb 100644 --- a/tests/openai_agents/basic/test_local_image_workflow.py +++ b/tests/openai_agents/basic/test_local_image_workflow.py @@ -1,4 +1,6 @@ import uuid +import pytest +import os from concurrent.futures import ThreadPoolExecutor from temporalio.client import Client @@ -19,10 +21,13 @@ def local_image_test_model(): ) -async def test_execute_workflow_default_question(client: Client): +@pytest.mark.parametrize("mock_model", [True, False]) +async def test_execute_workflow_default_question(client: Client, mock_model: bool): task_queue_name = str(uuid.uuid4()) + if not mock_model and not os.environ.get("OPENAI_API_KEY"): + pytest.skip(f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set") - async with AgentEnvironment(model=local_image_test_model()) as agent_env: + async with AgentEnvironment(model=local_image_test_model() if mock_model else None) as agent_env: client = agent_env.applied_on_client(client) async with Worker( client, @@ -43,10 +48,13 @@ async def test_execute_workflow_default_question(client: Client): assert len(result) > 0 -async def test_execute_workflow_custom_question(client: Client): +@pytest.mark.parametrize("mock_model", [True, False]) +async def test_execute_workflow_custom_question(client: Client, mock_model: bool): task_queue_name = str(uuid.uuid4()) + if not mock_model and not os.environ.get("OPENAI_API_KEY"): + pytest.skip(f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set") - async with AgentEnvironment(model=local_image_test_model()) as agent_env: + async with AgentEnvironment(model=local_image_test_model() if mock_model else None) as agent_env: client = agent_env.applied_on_client(client) async with Worker( client, diff --git a/tests/openai_agents/basic/test_non_strict_output_workflow.py b/tests/openai_agents/basic/test_non_strict_output_workflow.py index bdd3a5a2a..ab9a3b45e 100644 --- a/tests/openai_agents/basic/test_non_strict_output_workflow.py +++ b/tests/openai_agents/basic/test_non_strict_output_workflow.py @@ -1,4 +1,6 @@ import uuid +import pytest +import os from concurrent.futures import ThreadPoolExecutor from temporalio.client import Client @@ -26,10 +28,13 @@ def non_strict_output_test_model(): ) -async def test_execute_workflow(client: Client): +@pytest.mark.parametrize("mock_model", [True, False]) +async def test_execute_workflow(client: Client, mock_model: bool): task_queue_name = str(uuid.uuid4()) + if not mock_model and not os.environ.get("OPENAI_API_KEY"): + pytest.skip(f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set") - async with AgentEnvironment(model=non_strict_output_test_model()) as agent_env: + async with AgentEnvironment(model=non_strict_output_test_model() if mock_model else None) as agent_env: client = agent_env.applied_on_client(client) async with Worker( client, diff --git a/tests/openai_agents/basic/test_previous_response_id_workflow.py b/tests/openai_agents/basic/test_previous_response_id_workflow.py index 1a2b63ff2..dacf5e3b6 100644 --- a/tests/openai_agents/basic/test_previous_response_id_workflow.py +++ b/tests/openai_agents/basic/test_previous_response_id_workflow.py @@ -1,4 +1,6 @@ import uuid +import pytest +import os from concurrent.futures import ThreadPoolExecutor from temporalio.client import Client @@ -25,10 +27,13 @@ def previous_response_id_test_model(): ) -async def test_execute_workflow(client: Client): +@pytest.mark.parametrize("mock_model", [True, False]) +async def test_execute_workflow(client: Client, mock_model: bool): task_queue_name = str(uuid.uuid4()) + if not mock_model and not os.environ.get("OPENAI_API_KEY"): + pytest.skip(f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set") - async with AgentEnvironment(model=previous_response_id_test_model()) as agent_env: + async with AgentEnvironment(model=previous_response_id_test_model() if mock_model else None) as agent_env: client = agent_env.applied_on_client(client) async with Worker( client, diff --git a/tests/openai_agents/basic/test_remote_image_workflow.py b/tests/openai_agents/basic/test_remote_image_workflow.py index f6ee99b52..dad7ec516 100644 --- a/tests/openai_agents/basic/test_remote_image_workflow.py +++ b/tests/openai_agents/basic/test_remote_image_workflow.py @@ -1,4 +1,6 @@ import uuid +import pytest +import os from concurrent.futures import ThreadPoolExecutor from temporalio.client import Client @@ -22,10 +24,13 @@ def remote_image_test_model(): ) -async def test_execute_workflow_default_question(client: Client): +@pytest.mark.parametrize("mock_model", [True, False]) +async def test_execute_workflow_default_question(client: Client, mock_model: bool): task_queue_name = str(uuid.uuid4()) + if not mock_model and not os.environ.get("OPENAI_API_KEY"): + pytest.skip(f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set") - async with AgentEnvironment(model=remote_image_test_model()) as agent_env: + async with AgentEnvironment(model=remote_image_test_model() if mock_model else None) as agent_env: client = agent_env.applied_on_client(client) async with Worker( client, @@ -47,10 +52,13 @@ async def test_execute_workflow_default_question(client: Client): assert len(result) > 0 -async def test_execute_workflow_custom_question(client: Client): +@pytest.mark.parametrize("mock_model", [True, False]) +async def test_execute_workflow_custom_question(client: Client, mock_model: bool): task_queue_name = str(uuid.uuid4()) + if not mock_model and not os.environ.get("OPENAI_API_KEY"): + pytest.skip(f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set") - async with AgentEnvironment(model=remote_image_test_model()) as agent_env: + async with AgentEnvironment(model=remote_image_test_model() if mock_model else None) as agent_env: client = agent_env.applied_on_client(client) async with Worker( client, diff --git a/tests/openai_agents/basic/test_tools_workflow.py b/tests/openai_agents/basic/test_tools_workflow.py index 0b28bc787..02ccb6afd 100644 --- a/tests/openai_agents/basic/test_tools_workflow.py +++ b/tests/openai_agents/basic/test_tools_workflow.py @@ -1,4 +1,6 @@ import uuid +import pytest +import os from concurrent.futures import ThreadPoolExecutor from temporalio.client import Client @@ -24,10 +26,13 @@ def tools_test_model(): ) -async def test_execute_workflow(client: Client): +@pytest.mark.parametrize("mock_model", [True, False]) +async def test_execute_workflow(client: Client, mock_model: bool): task_queue_name = str(uuid.uuid4()) + if not mock_model and not os.environ.get("OPENAI_API_KEY"): + pytest.skip(f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set") - async with AgentEnvironment(model=tools_test_model()) as agent_env: + async with AgentEnvironment(model=tools_test_model() if mock_model else None) as agent_env: client = agent_env.applied_on_client(client) async with Worker( client, diff --git a/tests/openai_agents/e2e/test_hello_world_workflow_e2e.py b/tests/openai_agents/e2e/test_hello_world_workflow_e2e.py deleted file mode 100644 index 9aa16f5df..000000000 --- a/tests/openai_agents/e2e/test_hello_world_workflow_e2e.py +++ /dev/null @@ -1,26 +0,0 @@ -import uuid -from concurrent.futures import ThreadPoolExecutor - -from temporalio.client import Client -from temporalio.worker import Worker - -from openai_agents.basic.workflows.hello_world_workflow import HelloWorldAgent - - -async def test_execute_workflow(client: Client): - task_queue_name = str(uuid.uuid4()) - - async with Worker( - client, - task_queue=task_queue_name, - workflows=[HelloWorldAgent], - activity_executor=ThreadPoolExecutor(5), - ): - result = await client.execute_workflow( - HelloWorldAgent.run, - "Write a recursive haiku about recursive haikus.", - id=str(uuid.uuid4()), - task_queue=task_queue_name, - ) - assert isinstance(result, str) - assert len(result) > 0 From a53aba56aaeeaa88909ad4dfcb00afab0bf94f80 Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Thu, 6 Nov 2025 12:38:22 -0500 Subject: [PATCH 24/26] fix a test --- tests/openai_agents/basic/test_hello_world_workflow.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/openai_agents/basic/test_hello_world_workflow.py b/tests/openai_agents/basic/test_hello_world_workflow.py index 238a61799..61d87e018 100644 --- a/tests/openai_agents/basic/test_hello_world_workflow.py +++ b/tests/openai_agents/basic/test_hello_world_workflow.py @@ -40,4 +40,9 @@ async def test_execute_workflow(client: Client, mock_model: bool): id=str(uuid.uuid4()), task_queue=task_queue_name, ) - assert result == "This is a haiku (not really)" + + if mock_model: + assert result == "This is a haiku (not really)" + else: + assert isinstance(result, str) + assert len(result) > 0 From 5db7719be13aaf33c97ad4848439c5939c603b46 Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Thu, 6 Nov 2025 12:39:34 -0500 Subject: [PATCH 25/26] fmt --- .../basic/test_agent_lifecycle_workflow.py | 9 +++++++-- .../basic/test_dynamic_system_prompt_workflow.py | 16 ++++++++++++---- .../basic/test_hello_world_workflow.py | 8 ++++++-- .../basic/test_lifecycle_workflow.py | 8 ++++++-- .../basic/test_local_image_workflow.py | 16 ++++++++++++---- .../basic/test_non_strict_output_workflow.py | 8 ++++++-- .../basic/test_previous_response_id_workflow.py | 8 ++++++-- .../basic/test_remote_image_workflow.py | 16 ++++++++++++---- tests/openai_agents/basic/test_tools_workflow.py | 8 ++++++-- 9 files changed, 73 insertions(+), 24 deletions(-) diff --git a/tests/openai_agents/basic/test_agent_lifecycle_workflow.py b/tests/openai_agents/basic/test_agent_lifecycle_workflow.py index 04ec089f8..c6d392501 100644 --- a/tests/openai_agents/basic/test_agent_lifecycle_workflow.py +++ b/tests/openai_agents/basic/test_agent_lifecycle_workflow.py @@ -21,13 +21,18 @@ def agent_lifecycle_test_model(): [ResponseBuilders.output_message('{"number": 10}')] ) + @pytest.mark.parametrize("mock_model", [True, False]) async def test_execute_workflow(client: Client, mock_model: bool): task_queue_name = str(uuid.uuid4()) if not mock_model and not os.environ.get("OPENAI_API_KEY"): - pytest.skip(f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set") + pytest.skip( + f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set" + ) - async with AgentEnvironment(model=agent_lifecycle_test_model() if mock_model else None) as agent_env: + async with AgentEnvironment( + model=agent_lifecycle_test_model() if mock_model else None + ) as agent_env: client = agent_env.applied_on_client(client) async with Worker( client, diff --git a/tests/openai_agents/basic/test_dynamic_system_prompt_workflow.py b/tests/openai_agents/basic/test_dynamic_system_prompt_workflow.py index 0af541496..d5c52478c 100644 --- a/tests/openai_agents/basic/test_dynamic_system_prompt_workflow.py +++ b/tests/openai_agents/basic/test_dynamic_system_prompt_workflow.py @@ -30,9 +30,13 @@ def dynamic_system_prompt_test_model(): async def test_execute_workflow_with_random_style(client: Client, mock_model: bool): task_queue_name = str(uuid.uuid4()) if not mock_model and not os.environ.get("OPENAI_API_KEY"): - pytest.skip(f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set") + pytest.skip( + f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set" + ) - async with AgentEnvironment(model=dynamic_system_prompt_test_model() if mock_model else None) as agent_env: + async with AgentEnvironment( + model=dynamic_system_prompt_test_model() if mock_model else None + ) as agent_env: client = agent_env.applied_on_client(client) async with Worker( client, @@ -57,9 +61,13 @@ async def test_execute_workflow_with_random_style(client: Client, mock_model: bo async def test_execute_workflow_with_specific_style(client: Client, mock_model: bool): task_queue_name = str(uuid.uuid4()) if not mock_model and not os.environ.get("OPENAI_API_KEY"): - pytest.skip(f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set") + pytest.skip( + f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set" + ) - async with AgentEnvironment(model=dynamic_system_prompt_test_model() if mock_model else None) as agent_env: + async with AgentEnvironment( + model=dynamic_system_prompt_test_model() if mock_model else None + ) as agent_env: client = agent_env.applied_on_client(client) async with Worker( client, diff --git a/tests/openai_agents/basic/test_hello_world_workflow.py b/tests/openai_agents/basic/test_hello_world_workflow.py index 61d87e018..c104c2336 100644 --- a/tests/openai_agents/basic/test_hello_world_workflow.py +++ b/tests/openai_agents/basic/test_hello_world_workflow.py @@ -24,9 +24,13 @@ def hello_world_test_model(): async def test_execute_workflow(client: Client, mock_model: bool): task_queue_name = str(uuid.uuid4()) if not mock_model and not os.environ.get("OPENAI_API_KEY"): - pytest.skip(f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set") + pytest.skip( + f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set" + ) - async with AgentEnvironment(model=hello_world_test_model() if mock_model else None) as agent_env: + async with AgentEnvironment( + model=hello_world_test_model() if mock_model else None + ) as agent_env: client = agent_env.applied_on_client(client) async with Worker( client, diff --git a/tests/openai_agents/basic/test_lifecycle_workflow.py b/tests/openai_agents/basic/test_lifecycle_workflow.py index a4f3a4ea0..0fcb38fe3 100644 --- a/tests/openai_agents/basic/test_lifecycle_workflow.py +++ b/tests/openai_agents/basic/test_lifecycle_workflow.py @@ -24,9 +24,13 @@ def lifecycle_test_model(): async def test_execute_workflow(client: Client, mock_model: bool): task_queue_name = str(uuid.uuid4()) if not mock_model and not os.environ.get("OPENAI_API_KEY"): - pytest.skip(f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set") + pytest.skip( + f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set" + ) - async with AgentEnvironment(model=lifecycle_test_model() if mock_model else None) as agent_env: + async with AgentEnvironment( + model=lifecycle_test_model() if mock_model else None + ) as agent_env: client = agent_env.applied_on_client(client) async with Worker( client, diff --git a/tests/openai_agents/basic/test_local_image_workflow.py b/tests/openai_agents/basic/test_local_image_workflow.py index 8d525b0eb..37b2fda75 100644 --- a/tests/openai_agents/basic/test_local_image_workflow.py +++ b/tests/openai_agents/basic/test_local_image_workflow.py @@ -25,9 +25,13 @@ def local_image_test_model(): async def test_execute_workflow_default_question(client: Client, mock_model: bool): task_queue_name = str(uuid.uuid4()) if not mock_model and not os.environ.get("OPENAI_API_KEY"): - pytest.skip(f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set") + pytest.skip( + f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set" + ) - async with AgentEnvironment(model=local_image_test_model() if mock_model else None) as agent_env: + async with AgentEnvironment( + model=local_image_test_model() if mock_model else None + ) as agent_env: client = agent_env.applied_on_client(client) async with Worker( client, @@ -52,9 +56,13 @@ async def test_execute_workflow_default_question(client: Client, mock_model: boo async def test_execute_workflow_custom_question(client: Client, mock_model: bool): task_queue_name = str(uuid.uuid4()) if not mock_model and not os.environ.get("OPENAI_API_KEY"): - pytest.skip(f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set") + pytest.skip( + f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set" + ) - async with AgentEnvironment(model=local_image_test_model() if mock_model else None) as agent_env: + async with AgentEnvironment( + model=local_image_test_model() if mock_model else None + ) as agent_env: client = agent_env.applied_on_client(client) async with Worker( client, diff --git a/tests/openai_agents/basic/test_non_strict_output_workflow.py b/tests/openai_agents/basic/test_non_strict_output_workflow.py index ab9a3b45e..03b172cfa 100644 --- a/tests/openai_agents/basic/test_non_strict_output_workflow.py +++ b/tests/openai_agents/basic/test_non_strict_output_workflow.py @@ -32,9 +32,13 @@ def non_strict_output_test_model(): async def test_execute_workflow(client: Client, mock_model: bool): task_queue_name = str(uuid.uuid4()) if not mock_model and not os.environ.get("OPENAI_API_KEY"): - pytest.skip(f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set") + pytest.skip( + f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set" + ) - async with AgentEnvironment(model=non_strict_output_test_model() if mock_model else None) as agent_env: + async with AgentEnvironment( + model=non_strict_output_test_model() if mock_model else None + ) as agent_env: client = agent_env.applied_on_client(client) async with Worker( client, diff --git a/tests/openai_agents/basic/test_previous_response_id_workflow.py b/tests/openai_agents/basic/test_previous_response_id_workflow.py index dacf5e3b6..e13fece48 100644 --- a/tests/openai_agents/basic/test_previous_response_id_workflow.py +++ b/tests/openai_agents/basic/test_previous_response_id_workflow.py @@ -31,9 +31,13 @@ def previous_response_id_test_model(): async def test_execute_workflow(client: Client, mock_model: bool): task_queue_name = str(uuid.uuid4()) if not mock_model and not os.environ.get("OPENAI_API_KEY"): - pytest.skip(f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set") + pytest.skip( + f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set" + ) - async with AgentEnvironment(model=previous_response_id_test_model() if mock_model else None) as agent_env: + async with AgentEnvironment( + model=previous_response_id_test_model() if mock_model else None + ) as agent_env: client = agent_env.applied_on_client(client) async with Worker( client, diff --git a/tests/openai_agents/basic/test_remote_image_workflow.py b/tests/openai_agents/basic/test_remote_image_workflow.py index dad7ec516..4fa21bcd1 100644 --- a/tests/openai_agents/basic/test_remote_image_workflow.py +++ b/tests/openai_agents/basic/test_remote_image_workflow.py @@ -28,9 +28,13 @@ def remote_image_test_model(): async def test_execute_workflow_default_question(client: Client, mock_model: bool): task_queue_name = str(uuid.uuid4()) if not mock_model and not os.environ.get("OPENAI_API_KEY"): - pytest.skip(f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set") + pytest.skip( + f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set" + ) - async with AgentEnvironment(model=remote_image_test_model() if mock_model else None) as agent_env: + async with AgentEnvironment( + model=remote_image_test_model() if mock_model else None + ) as agent_env: client = agent_env.applied_on_client(client) async with Worker( client, @@ -56,9 +60,13 @@ async def test_execute_workflow_default_question(client: Client, mock_model: boo async def test_execute_workflow_custom_question(client: Client, mock_model: bool): task_queue_name = str(uuid.uuid4()) if not mock_model and not os.environ.get("OPENAI_API_KEY"): - pytest.skip(f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set") + pytest.skip( + f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set" + ) - async with AgentEnvironment(model=remote_image_test_model() if mock_model else None) as agent_env: + async with AgentEnvironment( + model=remote_image_test_model() if mock_model else None + ) as agent_env: client = agent_env.applied_on_client(client) async with Worker( client, diff --git a/tests/openai_agents/basic/test_tools_workflow.py b/tests/openai_agents/basic/test_tools_workflow.py index 02ccb6afd..855e65ece 100644 --- a/tests/openai_agents/basic/test_tools_workflow.py +++ b/tests/openai_agents/basic/test_tools_workflow.py @@ -30,9 +30,13 @@ def tools_test_model(): async def test_execute_workflow(client: Client, mock_model: bool): task_queue_name = str(uuid.uuid4()) if not mock_model and not os.environ.get("OPENAI_API_KEY"): - pytest.skip(f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set") + pytest.skip( + f"Skipping test (mock_model={mock_model}), because OPENAI_API_KEY is not set" + ) - async with AgentEnvironment(model=tools_test_model() if mock_model else None) as agent_env: + async with AgentEnvironment( + model=tools_test_model() if mock_model else None + ) as agent_env: client = agent_env.applied_on_client(client) async with Worker( client, From d34f9617f6dc9ed92bf163bf1013abb93a79b81a Mon Sep 17 00:00:00 2001 From: Donald Pinckney Date: Thu, 6 Nov 2025 12:40:40 -0500 Subject: [PATCH 26/26] fmt --- tests/openai_agents/basic/test_agent_lifecycle_workflow.py | 4 ++-- .../basic/test_dynamic_system_prompt_workflow.py | 4 ++-- tests/openai_agents/basic/test_hello_world_workflow.py | 4 ++-- tests/openai_agents/basic/test_lifecycle_workflow.py | 4 ++-- tests/openai_agents/basic/test_local_image_workflow.py | 4 ++-- tests/openai_agents/basic/test_non_strict_output_workflow.py | 4 ++-- .../openai_agents/basic/test_previous_response_id_workflow.py | 4 ++-- tests/openai_agents/basic/test_remote_image_workflow.py | 4 ++-- tests/openai_agents/basic/test_tools_workflow.py | 4 ++-- 9 files changed, 18 insertions(+), 18 deletions(-) diff --git a/tests/openai_agents/basic/test_agent_lifecycle_workflow.py b/tests/openai_agents/basic/test_agent_lifecycle_workflow.py index c6d392501..c8f2cca36 100644 --- a/tests/openai_agents/basic/test_agent_lifecycle_workflow.py +++ b/tests/openai_agents/basic/test_agent_lifecycle_workflow.py @@ -1,8 +1,8 @@ -import uuid -import pytest import os +import uuid from concurrent.futures import ThreadPoolExecutor +import pytest from temporalio.client import Client from temporalio.contrib.openai_agents.testing import ( AgentEnvironment, diff --git a/tests/openai_agents/basic/test_dynamic_system_prompt_workflow.py b/tests/openai_agents/basic/test_dynamic_system_prompt_workflow.py index d5c52478c..2fd155a25 100644 --- a/tests/openai_agents/basic/test_dynamic_system_prompt_workflow.py +++ b/tests/openai_agents/basic/test_dynamic_system_prompt_workflow.py @@ -1,8 +1,8 @@ -import uuid -import pytest import os +import uuid from concurrent.futures import ThreadPoolExecutor +import pytest from temporalio.client import Client from temporalio.contrib.openai_agents.testing import ( AgentEnvironment, diff --git a/tests/openai_agents/basic/test_hello_world_workflow.py b/tests/openai_agents/basic/test_hello_world_workflow.py index c104c2336..d461acc2f 100644 --- a/tests/openai_agents/basic/test_hello_world_workflow.py +++ b/tests/openai_agents/basic/test_hello_world_workflow.py @@ -1,8 +1,8 @@ -import uuid -import pytest import os +import uuid from concurrent.futures import ThreadPoolExecutor +import pytest from temporalio.client import Client from temporalio.contrib.openai_agents.testing import ( AgentEnvironment, diff --git a/tests/openai_agents/basic/test_lifecycle_workflow.py b/tests/openai_agents/basic/test_lifecycle_workflow.py index 0fcb38fe3..be38db196 100644 --- a/tests/openai_agents/basic/test_lifecycle_workflow.py +++ b/tests/openai_agents/basic/test_lifecycle_workflow.py @@ -1,8 +1,8 @@ -import uuid -import pytest import os +import uuid from concurrent.futures import ThreadPoolExecutor +import pytest from temporalio.client import Client from temporalio.contrib.openai_agents.testing import ( AgentEnvironment, diff --git a/tests/openai_agents/basic/test_local_image_workflow.py b/tests/openai_agents/basic/test_local_image_workflow.py index 37b2fda75..b303de8b1 100644 --- a/tests/openai_agents/basic/test_local_image_workflow.py +++ b/tests/openai_agents/basic/test_local_image_workflow.py @@ -1,8 +1,8 @@ -import uuid -import pytest import os +import uuid from concurrent.futures import ThreadPoolExecutor +import pytest from temporalio.client import Client from temporalio.contrib.openai_agents.testing import ( AgentEnvironment, diff --git a/tests/openai_agents/basic/test_non_strict_output_workflow.py b/tests/openai_agents/basic/test_non_strict_output_workflow.py index 03b172cfa..779f8b845 100644 --- a/tests/openai_agents/basic/test_non_strict_output_workflow.py +++ b/tests/openai_agents/basic/test_non_strict_output_workflow.py @@ -1,8 +1,8 @@ -import uuid -import pytest import os +import uuid from concurrent.futures import ThreadPoolExecutor +import pytest from temporalio.client import Client from temporalio.contrib.openai_agents.testing import ( AgentEnvironment, diff --git a/tests/openai_agents/basic/test_previous_response_id_workflow.py b/tests/openai_agents/basic/test_previous_response_id_workflow.py index e13fece48..e3dea5608 100644 --- a/tests/openai_agents/basic/test_previous_response_id_workflow.py +++ b/tests/openai_agents/basic/test_previous_response_id_workflow.py @@ -1,8 +1,8 @@ -import uuid -import pytest import os +import uuid from concurrent.futures import ThreadPoolExecutor +import pytest from temporalio.client import Client from temporalio.contrib.openai_agents.testing import ( AgentEnvironment, diff --git a/tests/openai_agents/basic/test_remote_image_workflow.py b/tests/openai_agents/basic/test_remote_image_workflow.py index 4fa21bcd1..2bf611d7a 100644 --- a/tests/openai_agents/basic/test_remote_image_workflow.py +++ b/tests/openai_agents/basic/test_remote_image_workflow.py @@ -1,8 +1,8 @@ -import uuid -import pytest import os +import uuid from concurrent.futures import ThreadPoolExecutor +import pytest from temporalio.client import Client from temporalio.contrib.openai_agents.testing import ( AgentEnvironment, diff --git a/tests/openai_agents/basic/test_tools_workflow.py b/tests/openai_agents/basic/test_tools_workflow.py index 855e65ece..d0b5b5297 100644 --- a/tests/openai_agents/basic/test_tools_workflow.py +++ b/tests/openai_agents/basic/test_tools_workflow.py @@ -1,8 +1,8 @@ -import uuid -import pytest import os +import uuid from concurrent.futures import ThreadPoolExecutor +import pytest from temporalio.client import Client from temporalio.contrib.openai_agents.testing import ( AgentEnvironment,