
Temporal Python Testing
Install this when you run Temporal Python workflows and need integration tests that mock activities instead of calling real APIs or databases.
Overview
temporal-python-testing is an agent skill for the Ship phase that teaches how to integration-test Temporal Python workflows with mocked activities instead of live external services.
Install
npx skills add https://github.com/wshobson/agents --skill temporal-python-testingWhat is this skill?
- Activity mocking strategy so workflow orchestration is tested without real external services
- Basic mock pattern: unittest.mock.Mock registered on the Temporal Worker activities list
- pytest.mark.asyncio tests inside WorkflowEnvironment with execute_workflow assertions
- Covers error injection and complex scenarios beyond the basic mock call (per skill scope)
- Verifies activity invocation with mock assert_called after the workflow completes
- Documents a basic mock pattern using WorkflowEnvironment, Worker, and unittest.mock.Mock for activities
- Explicit activity mocking strategy: test orchestration without real external services
- Scope includes error injection and complex scenarios beyond the basic mock example
Adoption & trust: 7.1k installs on skills.sh; 36.5k GitHub stars; 2/3 security scanners passed (skills.sh audits).
What problem does it solve?
You cannot safely or quickly verify Temporal workflow orchestration when every test hits real databases, APIs, or long-running activities.
Who is it for?
Solo builders maintaining Temporal Python workers who want integration coverage of workflow graphs without standing up external systems in every test run.
Skip if: Teams not using Temporal.io in Python, or anyone who only needs black-box E2E tests against a live Temporal cluster and real integrations with no mocking layer.
When should I use this skill?
When writing or extending Temporal Python workflow tests that should mock external activities, inject errors, or cover complex orchestration without live dependencies.
What do I get? / Deliverables
You get pytest-ready WorkflowEnvironment tests that register mock activities on the Worker, run workflows end-to-end in-process, and assert both outputs and activity calls—so you can extend the same pattern for error inj
- pytest modules that run workflows via WorkflowEnvironment with mock activities on the Worker
- Assertions on workflow results and mock activity call behavior
- Extensible templates for error-injection and multi-activity scenarios
Recommended Skills
Journey fit
Workflow integration testing with mocks is a Ship-phase quality gate before you rely on orchestration in staging or production. The skill is entirely about test harnesses, mocked activities, and pytest + WorkflowEnvironment patterns—not workflow authoring or deploy.
How it compares
Use for in-process Temporal workflow tests with mocked activities—not as a substitute for Temporal server ops skills or generic pytest tutorials without WorkflowEnvironment.
Common Questions / FAQ
Who is temporal-python-testing for?
It is for developers shipping Temporal Python workflows—especially solo builders—who need integration tests focused on orchestration while external activities stay mocked.
When should I use temporal-python-testing?
Use it in the Ship testing subphase when adding or refactoring workflow tests, before merge or release, and whenever you need to simulate activity failures without touching real services.
Is temporal-python-testing safe to install?
Review the Security Audits panel on this Prism page and inspect the skill package in your repo before granting your agent shell or network access; the patterns themselves only describe local pytest and mock-based tests.
SKILL.md
READMESKILL.md - Temporal Python Testing
# Integration Testing with Mocked Activities Comprehensive patterns for testing workflows with mocked external dependencies, error injection, and complex scenarios. ## Activity Mocking Strategy **Purpose**: Test workflow orchestration logic without calling real external services ### Basic Mock Pattern ```python import pytest from temporalio.testing import WorkflowEnvironment from temporalio.worker import Worker from unittest.mock import Mock @pytest.mark.asyncio async def test_workflow_with_mocked_activity(workflow_env): """Mock activity to test workflow logic""" # Create mock activity mock_activity = Mock(return_value="mocked-result") @workflow.defn class WorkflowWithActivity: @workflow.run async def run(self, input: str) -> str: result = await workflow.execute_activity( process_external_data, input, start_to_close_timeout=timedelta(seconds=10), ) return f"processed: {result}" async with Worker( workflow_env.client, task_queue="test", workflows=[WorkflowWithActivity], activities=[mock_activity], # Use mock instead of real activity ): result = await workflow_env.client.execute_workflow( WorkflowWithActivity.run, "test-input", id="wf-mock", task_queue="test", ) assert result == "processed: mocked-result" mock_activity.assert_called_once() ``` ### Dynamic Mock Responses **Scenario-Based Mocking**: ```python @pytest.mark.asyncio async def test_workflow_multiple_mock_scenarios(workflow_env): """Test different workflow paths with dynamic mocks""" # Mock returns different values based on input def dynamic_activity(input: str) -> str: if input == "error-case": raise ApplicationError("Validation failed", non_retryable=True) return f"processed-{input}" @workflow.defn class DynamicWorkflow: @workflow.run async def run(self, input: str) -> str: try: result = await workflow.execute_activity( dynamic_activity, input, start_to_close_timeout=timedelta(seconds=10), ) return f"success: {result}" except ApplicationError as e: return f"error: {e.message}" async with Worker( workflow_env.client, task_queue="test", workflows=[DynamicWorkflow], activities=[dynamic_activity], ): # Test success path result_success = await workflow_env.client.execute_workflow( DynamicWorkflow.run, "valid-input", id="wf-success", task_queue="test", ) assert result_success == "success: processed-valid-input" # Test error path result_error = await workflow_env.client.execute_workflow( DynamicWorkflow.run, "error-case", id="wf-error", task_queue="test", ) assert "Validation failed" in result_error ``` ## Error Injection Patterns ### Testing Transient Failures **Retry Behavior**: ```python @pytest.mark.asyncio async def test_workflow_transient_errors(workflow_env): """Test retry logic with controlled failures""" attempt_count = 0 @activity.defn async def transient_activity() -> str: nonlocal attempt_count attempt_count += 1 if attempt_count < 3: raise Exception(f"Transient error {attempt_count}") return "success-after-retries" @workflow.defn class RetryWorkflow: @workflow.run async def run(self) -> str: return await workflow.execute_activity( transient_activity, start_to_close_timeout=timedelta(seconds=10), retry_policy=RetryPolicy( initial_interva