pip install aws-durable-execution-sdk-python-testingUse the AWS Durable Execution Testing SDK for Python to test your Python durable functions locally.
The test framework contains a local runner, so you can run and test your durable function locally before you deploy it.
from aws_durable_execution_sdk_python.context import (
DurableContext,
durable_step,
durable_with_child_context,
)
from aws_durable_execution_sdk_python.execution import durable_execution
from aws_durable_execution_sdk_python.config import Duration
@durable_step
def one(a: int, b: int) -> str:
return f"{a} {b}"
@durable_step
def two_1(a: int, b: int) -> str:
return f"{a} {b}"
@durable_step
def two_2(a: int, b: int) -> str:
return f"{b} {a}"
@durable_with_child_context
def two(ctx: DurableContext, a: int, b: int) -> str:
two_1_result: str = ctx.step(two_1(a, b))
two_2_result: str = ctx.step(two_2(a, b))
return f"{two_1_result} {two_2_result}"
@durable_step
def three(a: int, b: int) -> str:
return f"{a} {b}"
@durable_execution
def function_under_test(event: Any, context: DurableContext) -> list[str]:
results: list[str] = []
result_one: str = context.step(one(1, 2))
results.append(result_one)
context.wait(Duration.from_seconds(1))
result_two: str = context.run_in_child_context(two(3, 4))
results.append(result_two)
result_three: str = context.step(three(5, 6))
results.append(result_three)
return resultsfrom aws_durable_execution_sdk_python.execution import InvocationStatus
from aws_durable_execution_sdk_python_testing.runner import (
ContextOperation,
DurableFunctionTestResult,
DurableFunctionTestRunner,
StepOperation,
)
def test_my_durable_functions():
with DurableFunctionTestRunner(handler=function_under_test) as runner:
result: DurableFunctionTestResult = runner.run(input="input str", timeout=10)
assert result.status is InvocationStatus.SUCCEEDED
assert result.result == '["1 2", "3 4 4 3", "5 6"]'
one_result: StepOperation = result.get_step("one")
assert one_result.result == '"1 2"'
two_result: ContextOperation = result.get_context("two")
assert two_result.result == '"3 4 4 3"'
three_result: StepOperation = result.get_step("three")
assert three_result.result == '"5 6"'- DurableTestRunner starts execution via Executor
- Executor creates Execution and schedules initial invocation
- During execution, checkpoints are processed by CheckpointProcessor
- Individual Processors transform operation updates and may trigger events
- ExecutionNotifier broadcasts events to Executor (observer)
- Executor updates Execution state based on events
- Execution completion triggers final event notifications
- DurableTestRunner run() blocks until it receives completion event, and then returns
DurableFunctionTestResult.
- DurableTestRunner - Main entry point that orchestrates test execution
- Executor - Manages execution lifecycle. Mutates Execution.
- Execution - Represents the state and operations of a single durable execution
- InMemoryServiceClient - Replaces AWS Lambda service client for local testing. Injected into SDK via
DurableExecutionInvocationInputWithClient
- CheckpointProcessor - Orchestrates operation transformations and validation
- Individual Validators - Validate operation updates and state transitions
- Individual Processors - Transform operation updates into operations (step, wait, callback, context, execution)
- ExecutionNotifier - Notifies observers of execution events
- ExecutionObserver - Interface for receiving execution lifecycle events
- Executor implements
ExecutionObserverto handle completion events
- DurableTestRunner serves as the main API entry point and sets up all components
- Executor manages the execution lifecycle, handling invocations and state transitions
- Execution maintains the state of operations and completion status
- DurableTestRunner creates InMemoryServiceClient with CheckpointProcessor
- InProcessInvoker injects the service client into SDK via
DurableExecutionInvocationInputWithClient - When durable functions call checkpoint operations, they're intercepted by InMemoryServiceClient
- InMemoryServiceClient delegates to CheckpointProcessor for local processing
- CheckpointProcessor orchestrates the checkpoint processing pipeline
- Individual Validators (CheckpointValidator, TransitionsValidator, and operation-specific validators) ensure operation updates are valid
- Individual Processors (StepProcessor, WaitProcessor, etc.) transform
OperationUpdateintoOperation
The observer pattern enables loose coupling between checkpoint processing and execution management:
- CheckpointProcessor processes operation updates
- Individual Processors detect state changes (completion, failures, timer scheduling)
- ExecutionNotifier broadcasts events to registered observers
- Executor (as ExecutionObserver) receives notifications and updates Execution state
- Execution complete_* methods finalize the execution state
The testing framework implements AWS-compliant error responses that match the exact format expected by boto3 and AWS services. For detailed information about error response formats, exception types, and troubleshooting, see:
Key features:
- AWS-compliant JSON format: Matches boto3 expectations exactly
- Smithy model compliance: Field names follow AWS Smithy definitions
- HTTP status code mapping: Standard AWS service status codes
- Boto3 compatibility: Seamless integration with boto3 error handling
Please see CONTRIBUTING.md. It contains the testing guide, sample commands and instructions for how to contribute to this package.
tldr; use hatch and it will manage virtual envs and dependencies for you, so you don't have to do it manually.
This project is licensed under the Apache-2.0 License.