- Overview
- Terminology
- Key features
- Getting started
- Configuration
- Deployment workflow
- Running tests in different modes
- Local vs cloud modes
- Best practices
- Troubleshooting
- See also
The AWS Durable Execution SDK Testing Framework (aws-durable-execution-sdk-python-testing) supports two execution modes: local and cloud. Local mode runs tests in-memory for fast development, while cloud mode runs tests against actual AWS Lambda functions for integration validation.
Local mode uses DurableFunctionTestRunner to execute your function in-memory without AWS deployment. It's fast, requires no credentials, and perfect for development.
Cloud mode uses DurableFunctionCloudTestRunner to invoke deployed Lambda functions and poll for completion. It validates your function's behavior in a real AWS environment, including Lambda runtime behavior, IAM permissions, and service integrations.
Cloud mode - Test execution mode that runs tests against deployed Lambda functions in AWS.
Local mode - Test execution mode that runs tests in-memory without AWS deployment (default).
DurableFunctionCloudTestRunner - Test runner class that executes durable functions against AWS Lambda backend.
Qualified function name - Lambda function identifier including version or alias (e.g., MyFunction:$LATEST).
Polling - The process of repeatedly checking execution status until completion.
- Real AWS environment - Tests run against actual Lambda functions
- End-to-end validation - Verifies deployment, IAM permissions, and service integrations
- Same test interface - Tests work in both local and cloud modes without changes
- Automatic polling - Waits for execution completion automatically
- Execution history - Retrieves full execution history for assertions
Here's a simple example of running tests in cloud mode:
import pytest
from aws_durable_execution_sdk_python.execution import InvocationStatus
from examples.src import hello_world
@pytest.mark.durable_execution(
handler=hello_world.handler,
lambda_function_name="hello world",
)
def test_hello_world(durable_runner):
"""Test hello world in both local and cloud modes."""
with durable_runner:
result = durable_runner.run(input="test", timeout=10)
assert result.status == InvocationStatus.SUCCEEDED
assert result.result == "Hello World!"Run the test in cloud mode:
# Set environment variables
export AWS_REGION=us-west-2
export QUALIFIED_FUNCTION_NAME="HelloWorld:$LATEST"
export LAMBDA_FUNCTION_TEST_NAME="hello world"
# Run test
pytest --runner-mode=cloud -k test_hello_worldCloud mode requires these environment variables:
Required:
-
QUALIFIED_FUNCTION_NAME- The deployed Lambda function ARN or qualified name- Example:
MyFunction:$LATEST - Example:
arn:aws:lambda:us-west-2:123456789012:function:MyFunction:$LATEST
- Example:
-
LAMBDA_FUNCTION_TEST_NAME- The function name to match against test markers- Example:
hello world - Must match the
lambda_function_nameparameter in@pytest.mark.durable_execution
- Example:
Optional:
-
AWS_REGION- AWS region for Lambda invocation (default:us-west-2)- Example:
us-east-1
- Example:
-
LAMBDA_ENDPOINT- Custom Lambda endpoint URL for testing- Example:
https://lambda.us-west-2.amazonaws.com - Useful for testing against local Lambda emulators
- Example:
--runner-mode- Test execution modelocal(default) - Run tests in-memorycloud- Run tests against deployed Lambda functions
Use the @pytest.mark.durable_execution marker to configure tests:
@pytest.mark.durable_execution(
handler=my_function.handler, # Required for local mode
lambda_function_name="my function", # Required for cloud mode
)
def test_my_function(durable_runner):
# Test code here
passParameters:
handler- The durable function handler (required for local mode)lambda_function_name- The function name for cloud mode matching (required for cloud mode)
Follow these steps to deploy and test your durable functions in the cloud:
Deploy your Lambda function to AWS using your preferred deployment tool (SAM, CDK, Terraform, etc.):
# Example using SAM
sam build
sam deploy --stack-name my-durable-functionAfter deployment, get the qualified function name or ARN:
# Get function ARN
aws lambda get-function --function-name MyFunction --query 'Configuration.FunctionArn'Configure the environment for cloud testing:
export AWS_REGION=us-west-2
export QUALIFIED_FUNCTION_NAME="MyFunction:$LATEST"
export LAMBDA_FUNCTION_TEST_NAME="my function"Execute your tests in cloud mode:
pytest --runner-mode=cloud -k test_my_functionpytest examples/test/pytest --runner-mode=cloud examples/test/pytest --runner-mode=cloud -k test_hello_world examples/test/Increase the timeout for long-running functions:
def test_long_running(durable_runner):
with durable_runner:
result = durable_runner.run(input="test", timeout=300) # 5 minutes
assert result.status == InvocationStatus.SUCCEEDEDCheck the runner mode in your tests:
def test_with_mode_check(durable_runner):
with durable_runner:
result = durable_runner.run(input="test", timeout=10)
assert result.status == InvocationStatus.SUCCEEDED
# Cloud-specific validation
if durable_runner.mode == "cloud":
# Additional assertions for cloud environment
pass| Feature | Local Mode | Cloud Mode |
|---|---|---|
| Execution | In-memory | AWS Lambda |
| Speed | Fast (seconds) | Slower (network latency) |
| AWS credentials | Not required | Required |
| Deployment | Not required | Required |
| IAM permissions | Not validated | Validated |
| Service integrations | Mocked | Real |
| Cost | Free | Lambda invocation costs |
| Use case | Development, unit tests | Integration tests, validation |
Use local mode for:
- Development - Fast iteration during development
- Unit tests - Testing function logic without AWS dependencies
- CI/CD - Fast feedback in pull request checks
- Debugging - Easy debugging with local tools
Use cloud mode for:
- Integration testing - Validate real AWS service integrations
- Deployment validation - Verify deployed functions work correctly
- IAM testing - Ensure permissions are configured correctly
- End-to-end testing - Test complete workflows in production-like environment
Write tests that work in both modes:
@pytest.mark.durable_execution(
handler=my_function.handler,
lambda_function_name="my function",
)
def test_my_function(durable_runner):
"""Test works in both local and cloud modes."""
with durable_runner:
result = durable_runner.run(input={"value": 42}, timeout=10)
# These assertions work in both modes
assert result.status == InvocationStatus.SUCCEEDED
assert result.result == "expected output"Run tests locally during development for fast feedback:
# Fast local testing
pytest examples/test/Run cloud tests before merging or deploying:
# Validate deployment
pytest --runner-mode=cloud examples/test/Cloud tests need longer timeouts due to network latency:
# Local mode: short timeout
result = runner.run(input="test", timeout=10)
# Cloud mode: longer timeout
result = runner.run(input="test", timeout=60)Configure different settings for different environments:
# Development
export AWS_REGION=us-west-2
export QUALIFIED_FUNCTION_NAME="MyFunction-Dev:$LATEST"
# Production
export AWS_REGION=us-east-1
export QUALIFIED_FUNCTION_NAME="MyFunction-Prod:$LATEST"When running cloud tests, test one function at a time to avoid confusion:
# Test specific function
export LAMBDA_FUNCTION_TEST_NAME="hello world"
pytest --runner-mode=cloud -k test_hello_worldIntegrate cloud testing into your CI/CD pipeline:
# Example GitHub Actions workflow
- name: Deploy function
run: sam deploy --stack-name test-stack
- name: Run cloud tests
env:
AWS_REGION: us-west-2
QUALIFIED_FUNCTION_NAME: ${{ steps.deploy.outputs.function_arn }}
LAMBDA_FUNCTION_TEST_NAME: "hello world"
run: pytest --runner-mode=cloud -k test_hello_worldProblem: Test times out waiting for execution to complete.
Cause: The function takes longer than the timeout value, or the function is stuck.
Solution: Increase the timeout parameter:
# Increase timeout to 120 seconds
result = runner.run(input="test", timeout=120)Check the Lambda function logs to see if it's actually running:
aws logs tail /aws/lambda/MyFunction --followProblem: Cloud mode requires both QUALIFIED_FUNCTION_NAME and LAMBDA_FUNCTION_TEST_NAME environment variables
Cause: Required environment variables are missing.
Solution: Set both required environment variables:
export QUALIFIED_FUNCTION_NAME="MyFunction:$LATEST"
export LAMBDA_FUNCTION_TEST_NAME="hello world"Problem: Test is skipped with message about function name mismatch.
Cause: The test's lambda_function_name doesn't match LAMBDA_FUNCTION_TEST_NAME.
Solution: Either:
-
Update
LAMBDA_FUNCTION_TEST_NAMEto match the test:export LAMBDA_FUNCTION_TEST_NAME="my function" -
Or run only the matching test:
pytest --runner-mode=cloud -k test_hello_world
Problem: Failed to invoke Lambda function MyFunction: ...
Cause: AWS credentials are invalid, function doesn't exist, or IAM permissions are missing.
Solution:
-
Verify AWS credentials:
aws sts get-caller-identity -
Verify function exists:
aws lambda get-function --function-name MyFunction -
Check IAM permissions - you need
lambda:InvokeFunctionpermission:{ "Effect": "Allow", "Action": "lambda:InvokeFunction", "Resource": "arn:aws:lambda:*:*:function:*" }
Problem: No DurableExecutionArn in response for function MyFunction
Cause: The Lambda function is not a durable function or doesn't have durable execution enabled.
Solution: Ensure your function is decorated with @durable_execution:
from aws_durable_execution_sdk_python import durable_execution, DurableContext
@durable_execution
def handler(event: dict, context: DurableContext):
# Your durable function code
passProblem: Lambda function failed: ...
Cause: The function threw an unhandled exception.
Solution: Check the Lambda function logs:
aws logs tail /aws/lambda/MyFunction --followFix the error in your function code and redeploy.
Problem: Failed to get execution status: ...
Cause: The Lambda service API call failed.
Solution:
- Check AWS service health
- Verify your AWS credentials have the required permissions
- Check if you're using the correct region:
export AWS_REGION=us-west-2
- Getting Started - Set up your development environment
- Testing patterns - Practical pytest examples
- Examples README - More examples and configuration details