Testing Lambda durable functions
AWS provides dedicated testing SDKs for durable functions that let you run and inspect executions both locally and in the cloud. Install the testing SDK for your language:
The testing SDK provides two testing modes: local testing for fast unit tests, and cloud testing for integration tests against deployed functions.
Local testing
Local testing runs your durable functions in your development environment without requiring deployed resources. The test runner runs your function code directly and captures all operations for inspection.
Use local testing for unit tests, test-driven development, and CI/CD pipelines. Tests run locally without network latency or additional costs.
Example test:
The test runner captures execution state including the final result, individual step results, wait operations, callbacks, and any errors. You can inspect operations by name or iterate through all operations to verify execution behavior.
Execution stores
The testing SDK uses execution stores to persist test execution data. By default, tests use an in-memory store that's fast and requires no cleanup. For debugging or analyzing execution history, you can use a filesystem store that saves executions as JSON files.
In-memory store (default):
The in-memory store keeps execution data in memory during test runs. Data is lost when tests complete, making it ideal for standard unit tests and CI/CD pipelines where you don't need to inspect executions after tests finish.
Filesystem store:
The filesystem store persists execution data to disk as JSON files. Each execution is saved in a separate file, making it easy to inspect execution history after tests complete. Use the filesystem store when debugging complex test failures or analyzing execution patterns over time.
Configure the store using environment variables:
# Use filesystem store export AWS_DEX_STORE_TYPE=filesystem export AWS_DEX_STORE_PATH=./test-executions # Run tests pytest tests/
Execution files are stored with sanitized names and contain the complete execution state including operations, checkpoints, and results. The filesystem store automatically creates the storage directory if it doesn't exist.
Cloud testing
Cloud testing invokes deployed durable functions in AWS and retrieves their execution history using the Lambda API. Use cloud testing to verify behavior in production-like environments with real AWS services and configurations.
Cloud testing requires a deployed function and AWS credentials with permissions to invoke functions and read execution history:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "lambda:InvokeFunction", "lambda:GetDurableExecution", "lambda:GetDurableExecutionHistory" ], "Resource": "arn:aws:lambda:region:account-id:function:function-name" } ] }
Example cloud test:
Cloud tests invoke the actual deployed function and retrieve execution history from AWS. This lets you verify integration with other AWS services, validate performance characteristics, and test with production-like data and configurations.
What to test
Test durable functions by verifying execution outcomes, operation behavior, and error handling. Focus on business logic correctness rather than implementation details.
Verify execution results: Check that functions return the expected values for given inputs. Test both successful executions and error cases to ensure functions handle invalid input appropriately.
Inspect operation execution: Verify that steps, waits, and callbacks execute as expected. Check step results to ensure intermediate operations produce correct values. Validate that wait operations are configured with appropriate timeouts and that callbacks are created with correct settings.
Test error handling: Verify functions fail correctly with descriptive error messages when given invalid input. Test retry behavior by simulating transient failures and confirming operations retry appropriately. Check that permanent failures don't trigger unnecessary retries.
Validate workflows: For multi-step workflows, verify operations execute in the correct order. Test conditional branching to ensure different execution paths work correctly. Validate parallel operations execute concurrently and produce expected results.
The SDK documentation repositories contain extensive examples of testing patterns including multi-step workflows, error scenarios, timeout handling, and polling patterns.
Testing strategy
Use local testing for unit tests during development and in CI/CD pipelines. Local tests run fast, don't require AWS credentials, and provide immediate feedback on code changes. Write local tests to verify business logic, error handling, and operation behavior.
Use cloud testing for integration tests before deploying to production. Cloud tests verify behavior with real AWS services and configurations, validate performance characteristics, and test end-to-end workflows. Run cloud tests in staging environments to catch integration issues before they reach production.
Mock external dependencies in local tests to isolate function logic and keep tests fast. Use cloud tests to verify actual integration with external services like databases, APIs, and other AWS services.
Write focused tests that verify one specific behavior. Use descriptive test names that explain what's being tested. Group related tests together and use test fixtures for common setup code. Keep tests simple and avoid complex test logic that's hard to understand.
Debugging failures
When tests fail, inspect the execution result to understand what went wrong. Check the execution status to see if the function succeeded, failed, or timed out. Read error messages to understand the failure cause.
Inspect individual operation results to find where behavior diverged from expectations. Check step results to see what values were produced. Verify operation ordering to confirm operations executed in the expected sequence. Count operations to ensure the right number of steps, waits, and callbacks were created.
Common issues include non-deterministic code that produces different results on replay, shared state through global variables that breaks during replay, and missing operations due to conditional logic errors. Use standard debuggers and logging to step through function code and track execution flow.
For cloud tests, inspect execution history in CloudWatch Logs to see detailed operation logs. Use tracing to track execution flow across services and identify bottlenecks.