Testing API Reference¶
Reference for the test runners, the test result, operation accessors, and the enums used across the testing SDKs. For an onboarding walkthrough, start with Authoring.
LocalDurableTestRunner¶
Runs a durable handler in-process against an in-memory checkpoint store. No AWS credentials, no deployment, and no containers are required. Use it for unit tests and CI.
Create a runner¶
Call LocalDurableTestRunner.setupTestEnvironment() in beforeAll and
LocalDurableTestRunner.teardownTestEnvironment() in afterAll.
static setupTestEnvironment(params?: LocalDurableTestRunnerSetupParameters): Promise<void>
static teardownTestEnvironment(): Promise<void>
Constructor parameters:
handlerFunction(required) The handler created withwithDurableExecution.
Use as a context manager. The context manager starts the scheduler thread on entry and stops it on exit.
Parameters:
handler(required) The handler decorated with@durable_execution.poll_interval(optional) Seconds between internal polling cycles. Defaults to1.0.
// Class-based input type
LocalDurableTestRunner.create(Class<I> inputType, BiFunction<I, DurableContext, O> handlerFn)
// TypeToken-based input type (for generic types)
LocalDurableTestRunner.create(TypeToken<I> inputType, BiFunction<I, DurableContext, O> handlerFn)
// With a custom DurableConfig
LocalDurableTestRunner.create(Class<I> inputType, BiFunction<I, DurableContext, O> handlerFn, DurableConfig config)
// From a DurableHandler instance (extracts config automatically)
LocalDurableTestRunner.create(Class<I> inputType, DurableHandler<I, O> handler)
Override config or the output type on an existing runner:
LocalDurableTestRunner<I, O> withDurableConfig(DurableConfig config)
LocalDurableTestRunner<I, O> withOutputType(Class<O> outputType)
LocalDurableTestRunner<I, O> withOutputType(TypeToken<O> outputType)
Parameters:
inputType(required) The input type class orTypeToken.handlerFn(required) ABiFunction<I, DurableContext, O>implementing the handler logic.config(optional) ADurableConfig. The runner overrides theDurableExecutionClientwith its in-memory implementation but preserves all other settings such as customSerDes.handler(optional) ADurableHandlerinstance. The runner extracts its configuration automatically.
Run the handler¶
run() drives the full replay loop until the execution completes or fails.
Parameters:
params(optional) AnInvokeRequestobject.payload(optional) The input payload to pass to the handler.
Returns: Promise<TestResult>
run(
input: str | None = None,
timeout: int = 900,
function_name: str = "test-function",
execution_name: str = "execution-name",
account_id: str = "123456789012",
) -> DurableFunctionTestResult
Parameters:
input(optional) JSON-encoded input string. Defaults toNone.timeout(optional) Maximum seconds to wait for completion. Defaults to900.function_name(optional) Function name used internally. Defaults to"test-function".execution_name(optional) Execution name used internally. Defaults to"execution-name".account_id(optional) Account ID used internally. Defaults to"123456789012".
Returns: DurableFunctionTestResult
Raises: TimeoutError if the execution does not complete within timeout.
Run asynchronously¶
Not applicable. run() already drives the full replay loop.
# Start execution without waiting for completion
run_async(
input: str | None = None,
timeout: int = 900,
function_name: str = "test-function",
execution_name: str = "execution-name",
account_id: str = "123456789012",
) -> str # returns execution_arn
# Wait for a running execution to complete
wait_for_result(execution_arn: str, timeout: int = 60) -> DurableFunctionTestResult
Not applicable on the local runner. run() runs a single invocation,
runUntilComplete() drives the full loop. The cloud runner exposes startAsync(), see
CloudDurableTestRunner.
Inspect operations¶
getOperation(name: string, index?: number): DurableOperation
getOperationByIndex(index: number): DurableOperation
getOperationByNameAndIndex(name: string, index: number): DurableOperation
getOperationById(id: string): DurableOperation
Parameters:
name(required) The operation name.index(optional) Zero-based index when multiple operations share the same name. Defaults to0.id(required) The unique operation ID.
Returns: DurableOperation
Not available on the runner. Inspect operations through the result:
result.get_step(name), result.get_wait(name), result.get_callback(name),
result.get_context(name), result.get_invoke(name),
result.get_operation_by_name(name), and result.get_all_operations(). See
TestResult.
Drive callbacks¶
Callback interaction is on the DurableOperation object. Get a handle with
getOperation() and then call waitForData() and sendCallback*() on it. See
Drive a callback from an operation.
# Wait for a callback to become available and return its ID
wait_for_callback(execution_arn: str, name: str | None = None, timeout: int = 60) -> str
# Send a successful callback result
send_callback_success(callback_id: str, result: bytes | None = None) -> None
# Send a callback failure
send_callback_failure(callback_id: str, error: ErrorObject | None = None) -> None
# Send a callback heartbeat
send_callback_heartbeat(callback_id: str) -> None
// Get the callback ID for a named callback operation
String getCallbackId(String operationName)
// Complete a callback with a success result
void completeCallback(String callbackId, String result)
// Fail a callback
void failCallback(String callbackId, ErrorObject error)
// Time out a callback
void timeoutCallback(String callbackId)
Drive chained invokes¶
Not applicable. Register a mock handler for the invoked function and let the test drive the real handler path. See Register mock handlers for invoke.
Not applicable.
// Complete a chained invoke with a success result
void completeChainedInvoke(String name, String result)
// Fail a chained invoke
void failChainedInvoke(String name, ErrorObject error)
// Time out a chained invoke
void timeoutChainedInvoke(String name)
// Stop a chained invoke
void stopChainedInvoke(String name, ErrorObject error)
Register mock handlers for invoke¶
// Register a durable function for context.invoke() calls
registerDurableFunction(functionName: string, handler: DurableLambdaHandler): this
// Register a standard Lambda function for context.invoke() calls
registerFunction(functionName: string, handler: Handler): this
Both methods return the runner for chaining.
Not applicable.
Not applicable.
Simulate failures¶
Control time¶
Pass { skipTime: true } to setupTestEnvironment(). Both context.wait() delays and
step retry delays complete in zero wall-clock time.
Set the DURABLE_EXECUTION_TIME_SCALE environment variable to a float that multiplies
context.wait() durations. Step retry delays use the configured
next_attempt_delay_seconds at real wall-clock time and the scale does not apply to
them.
See Authoring: Skip time in tests for an overview.
Reset between runs¶
Reference types¶
LocalDurableTestRunnerSetupParameters¶
Fields:
skipTime(optional) Install fake timers so retry delays and waits complete instantly. Defaults tofalse.checkpointDelay(optional) Simulated delay in milliseconds on checkpoint API calls. Useful for surfacing race conditions.
Not applicable. Configure with the DURABLE_EXECUTION_TIME_SCALE environment variable
and the poll_interval constructor argument.
Not applicable. Configure with withDurableConfig, withOutputType, and
advanceTime() on the runner instance.
TestResult¶
The object returned by run(). Exposes the execution status, the final result, any
error, and the full operation history.
Status¶
Returns: ExecutionStatus (SUCCEEDED, FAILED, PENDING, or undefined).
Type: InvocationStatus (SUCCEEDED, FAILED, PENDING, TIMED_OUT, STOPPED).
Result¶
Returns: The deserialized execution output, or undefined if not available.
Throws: The execution error if the execution failed.
Error¶
Operations¶
Parameters:
params(optional) Filter byOperationStatus.
Returns: Array of DurableOperation.
result.operations # list[Operation], top-level only
result.get_all_operations() # list[Operation], including nested
# Typed lookup by name
result.get_step(name: str) -> StepOperation
result.get_wait(name: str) -> WaitOperation
result.get_context(name: str) -> ContextOperation
result.get_callback(name: str) -> CallbackOperation
result.get_invoke(name: str) -> InvokeOperation
result.get_execution(name: str) -> ExecutionOperation
result.get_operation_by_name(name: str) -> Operation
Raises: DurableFunctionsTestError if the operation is not found.
History events¶
Invocations¶
Pretty-print¶
Reference types¶
TestResultError¶
Uses ErrorObject from the main SDK:
Operation¶
Represents a single entry in the operation history. Each type of operation exposes its own details block (step, wait, callback, chained invoke, context, execution) on top of a shared set of accessors.
Common accessors¶
getName(): string | undefined
getType(): OperationType | undefined
getSubType(): OperationSubType | undefined
getStatus(): OperationStatus | undefined
getStartTimestamp(): Date | undefined
getEndTimestamp(): Date | undefined
getId(): string | undefined
getParentId(): string | undefined
getOperationData(): Operation | undefined
getEvents(): Event[] | undefined
getChildOperations(): DurableOperation[] | undefined
isWaitForCallback(): boolean
isCallback(): boolean
Every operation type inherits these fields from the base Operation dataclass:
Step details¶
Wait details¶
Callback details¶
Chained invoke details¶
Context details¶
ctx.result: OperationPayload | None
ctx.error: ErrorObject | None
ctx.child_operations: list[Operation]
# Typed lookup among the context's children
ctx.get_step(name) -> StepOperation
ctx.get_wait(name) -> WaitOperation
ctx.get_context(name) -> ContextOperation
ctx.get_callback(name) -> CallbackOperation
ctx.get_invoke(name) -> InvokeOperation
Execution details¶
Drive a callback from an operation¶
waitForData(status?: WaitingOperationStatus): Promise<DurableOperation>
sendCallbackSuccess(result?: string): Promise<SendDurableExecutionCallbackSuccessResponse>
sendCallbackFailure(error?: ErrorObject): Promise<SendDurableExecutionCallbackFailureResponse>
sendCallbackHeartbeat(): Promise<SendDurableExecutionCallbackHeartbeatResponse>
Driven from the runner. See LocalDurableTestRunner: Drive callbacks.
Driven from the runner. See LocalDurableTestRunner: Drive callbacks.
Enums¶
Execution status¶
The terminal status of a durable execution.
ExecutionStatus from @aws-sdk/client-lambda:
| Value | Meaning |
|---|---|
SUCCEEDED |
Execution completed successfully |
FAILED |
Execution failed |
PENDING |
Execution is waiting (callback, invoke, etc.) |
TIMED_OUT |
Execution exceeded its timeout |
STOPPED |
Execution was stopped |
InvocationStatus from aws_durable_execution_sdk_python.execution:
| Value | Meaning |
|---|---|
SUCCEEDED |
Execution completed successfully |
FAILED |
Execution failed |
PENDING |
Execution is waiting |
TIMED_OUT |
Execution exceeded its timeout |
STOPPED |
Execution was stopped |
ExecutionStatus from software.amazon.lambda.durable.model:
| Value | Meaning |
|---|---|
SUCCEEDED |
Execution completed successfully |
FAILED |
Execution failed |
PENDING |
Execution is waiting |
Operation status¶
The status of an individual operation.
OperationStatus from @aws-sdk/client-lambda:
| Value | Meaning |
|---|---|
STARTED |
Operation is running |
SUCCEEDED |
Operation completed successfully |
FAILED |
Operation failed |
PENDING |
Operation is queued |
CANCELLED |
Operation was cancelled |
TIMED_OUT |
Operation exceeded its timeout |
STOPPED |
Operation was stopped |
OperationStatus from aws_durable_execution_sdk_python.lambda_service. Same values as
TypeScript.
OperationStatus from software.amazon.awssdk.services.lambda.model. Same values as
TypeScript.
Operation type¶
OperationType from @aws-sdk/client-lambda:
| Value | Meaning |
|---|---|
STEP |
A step operation |
WAIT |
A wait operation |
CALLBACK |
A callback operation |
CHAINED_INVOKE |
An invoke operation |
CONTEXT |
A child context |
EXECUTION |
The root execution operation |
OperationType from aws_durable_execution_sdk_python.lambda_service. Same values as
TypeScript.
OperationType from software.amazon.awssdk.services.lambda.model. Same values as
TypeScript.
Waiting operation status¶
WaitingOperationStatus from @aws/durable-execution-sdk-js-testing:
| Value | Meaning |
|---|---|
STARTED |
Fires when the operation starts |
SUBMITTED |
For callbacks: fires when the submitter function completes. For other operations: same as COMPLETED |
COMPLETED |
Fires when the operation reaches a terminal status |
Not applicable. Use runner.wait_for_callback() to wait for a callback to become
available.
Not applicable. Use runner.getCallbackId() after run() returns PENDING.
CloudDurableTestRunner¶
Invokes a deployed Lambda function, polls for completion, and retrieves the full
operation history for assertions. Use it to validate deployment, IAM permissions, and
real service integrations. Both runners share the same TestResult and Operation
types, so tests written against the local runner run unchanged against the cloud runner.
Create a runner¶
new CloudDurableTestRunner({
functionName: string,
client?: LambdaClient,
config?: CloudDurableTestRunnerConfig,
})
Parameters:
functionName(required) The function name or ARN. A qualifier is required for durable functions.client(optional) A configuredLambdaClient. Defaults tonew LambdaClient().config(optional) ACloudDurableTestRunnerConfigobject.
DurableFunctionCloudTestRunner(
function_name: str,
region: str = "us-west-2",
lambda_endpoint: str | None = None,
poll_interval: float = 1.0,
)
Parameters:
function_name(required) The function name or ARN.region(optional) AWS region. Defaults to"us-west-2".lambda_endpoint(optional) Custom Lambda endpoint URL. Defaults toNone.poll_interval(optional) Seconds between status polls. Defaults to1.0.
// Class-based types
CloudDurableTestRunner.create(String functionArn, Class<I> inputType, Class<O> outputType)
// TypeToken-based types
CloudDurableTestRunner.create(String functionArn, TypeToken<I> inputType, TypeToken<O> outputType)
// With custom LambdaClient
CloudDurableTestRunner.create(String functionArn, Class<I> inputType, Class<O> outputType, LambdaClient lambdaClient)
Override settings on an existing runner:
CloudDurableTestRunner<I, O> withLambdaClient(LambdaClient lambdaClient)
CloudDurableTestRunner<I, O> withPollInterval(Duration interval)
CloudDurableTestRunner<I, O> withTimeout(Duration timeout)
CloudDurableTestRunner<I, O> withInvocationType(InvocationType type)
CloudDurableTestRunner<I, O> withSerDes(SerDes serDes)
Parameters:
functionArn(required) The function ARN. A qualifier is required for durable functions.inputType(required) The input type class orTypeToken.outputType(required) The output type class orTypeToken.lambdaClient(optional) A configuredLambdaClient. Defaults to a client usingDefaultCredentialsProvider.
Run the handler¶
Parameters:
params(optional) AnInvokeRequestobject.payload(optional) The input payload.
Returns: Promise<TestResult>
Parameters:
input(optional) JSON-encoded input string.timeout(optional) Maximum seconds to wait. Defaults to60.
Returns: DurableFunctionTestResult
Raises: TimeoutError if the execution does not complete within timeout.
Run asynchronously¶
Not applicable. run() already drives the full replay loop.
Inspect operations¶
Inspect operations through the test result. See TestResult.
Drive callbacks¶
Callback interaction is on the DurableOperation object. See
Drive a callback from an operation.
Drive callbacks through the AsyncExecution<O> returned by startAsync(). Use
getCallbackId(), completeCallback(), failCallback(), and heartbeatCallback() on
the async handle.
Configure polling and timeouts¶
Pass config: { pollInterval, invocationType } to the constructor. See
CloudDurableTestRunnerConfig.
Pass poll_interval to the constructor. Pass timeout to run() or run_async() to
set the maximum wait.
Use withPollInterval(Duration), withTimeout(Duration), and
withInvocationType(InvocationType) on the runner.
Reset between runs¶
Reference types¶
CloudDurableTestRunnerConfig¶
Fields:
pollInterval(optional) Milliseconds between history polls. Defaults to1000.invocationType(optional) Lambda invocation type. Defaults toInvocationType.RequestResponse.
Not a separate config object. Pass poll_interval directly to the constructor.
Not a separate config object. Use the with* builder methods on the runner.
See also¶
- Authoring Set up the local runner and write your first test.
- Assertions Inspect steps, waits, and callbacks after a test run.
- Workflow patterns Complete tests for common workflow shapes.
- Cloud Runner Run tests against a deployed Lambda function.
- Runner How the replay loop and checkpointing work.