

# 测试 Lambda 持久性函数
<a name="durable-testing"></a>

AWS 为持久性函数提供专门的测试 SDK，使您能够在本地和云端运行和检查执行情况。安装适用于您的语言的测试 SDK：

------
#### [ TypeScript ]

```
npm install --save-dev @aws/aws-durable-execution-sdk-js-testing
```

有关完整的 API 文档和示例，请参阅 GitHub 上的 [TypeScript 测试 SDK](https://github.com/aws/aws-durable-execution-sdk-js/tree/development/packages/aws-durable-execution-sdk-js-testing)。

------
#### [ Python ]

```
pip install aws-durable-execution-sdk-python-testing
```

有关完整的 API 文档和示例，请参阅 GitHub 上的 [Python 测试 SDK](https://github.com/aws/aws-durable-execution-sdk-python-testing)。

------

测试 SDK 提供两种测试模式：一种是用于快速单元测试的本地测试模式，另一种是用于针对已部署函数进行集成测试的云测试模式。

## 本地测试
<a name="durable-local-testing"></a>

本地测试可在您的开发环境中运行您的持久性函数，无需使用已部署的资源。测试运行器会直接运行您的函数代码，并记录所有操作以便进行检查。

将本地测试用于单元测试、测试驱动型开发和 CI/CD 管道。测试在本地运行，没有网络延迟，不会产生额外费用。

**示例测试：**

------
#### [ TypeScript ]

```
import { withDurableExecution } from '@aws/aws-durable-execution-sdk-js';
import { DurableFunctionTestRunner } from '@aws/aws-durable-execution-sdk-js-testing';

const handler = withDurableExecution(async (event, context) => {
  const result = await context.step('calculate', async () => {
    return event.a + event.b;
  });
  return result;
});

test('addition works correctly', async () => {
  const runner = new DurableFunctionTestRunner({ handler });
  const result = await runner.run({ a: 5, b: 3 });
  
  expect(result.status).toBe('SUCCEEDED');
  expect(result.result).toBe(8);
  
  const step = result.getStep('calculate');
  expect(step.result).toBe(8);
});
```

------
#### [ Python ]

```
from aws_durable_execution_sdk_python import durable_execution, DurableContext
from aws_durable_execution_sdk_python_testing import DurableFunctionTestRunner
from aws_durable_execution_sdk_python.execution import InvocationStatus

@durable_execution
def handler(event: dict, context: DurableContext) -> int:
    result = context.step(lambda _: event["a"] + event["b"], name="calculate")
    return result

def test_addition():
    runner = DurableFunctionTestRunner(handler=handler)
    with runner:
        result = runner.run(input={"a": 5, "b": 3}, timeout=10)
    
    assert result.status is InvocationStatus.SUCCEEDED
    assert result.result == 8
    
    step = result.get_step("calculate")
    assert step.result == 8
```

------

测试运行器会捕获执行状态，包括最终结果、各个步骤的结果、等待操作、回调以及任何错误信息。您可以按名称来检查操作，也可以遍历所有操作以验证执行行为。

### 执行存储
<a name="durable-execution-stores"></a>

测试 SDK 使用执行存储来保存测试执行数据。默认情况下，测试使用快速且无需清理操作的内存存储。为了调试或分析执行历史记录，您可以使用将执行保存为 JSON 文件的文件系统存储。

**内存存储（默认）：**

内存存储在测试运行期间将执行数据保存在内存中。测试完成后数据就会丢失，因此它非常适合用于标准单元测试以及 CI/CD 管道，在这些流程中，您无需在测试结束后检查执行结果。

**文件系统存储：**

文件系统存储会将执行数据以 JSON 文件的形式保存到磁盘上。每次执行都会被保存在单独的文件中，这样在测试完成后便于查看执行历史记录。在调试复杂的测试失败情况或分析长期的执行模式时，请使用文件系统存储功能。

使用环境变量配置存储：

```
# Use filesystem store
export AWS_DEX_STORE_TYPE=filesystem
export AWS_DEX_STORE_PATH=./test-executions

# Run tests
pytest tests/
```

执行文件以经过清理处理的名称进行存储，并包含完整的执行状态，包括操作、检查点和结果。文件系统存储会自动创建存储目录（如果该目录不存在）。

## 云端测试
<a name="durable-cloud-testing"></a>

云测试会调用 AWS 中的已部署持久性函数，并通过 Lambda API 获取其执行历史记录。利用云测试来在类似生产环境的条件下，通过真实的 AWS 服务和配置来验证其行为。

云测试需要已部署的函数以及具有调用函数和读取执行历史记录权限的 AWS 凭证：

```
{
    "Version": "2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "lambda:InvokeFunction",
                "lambda:GetDurableExecution",
                "lambda:GetDurableExecutionHistory"
            ],
            "Resource": "arn:aws:lambda:region:account-id:function:function-name"
        }
    ]
}
```

**云测试示例：**

------
#### [ TypeScript ]

```
import { DurableFunctionCloudTestRunner } from '@aws/aws-durable-execution-sdk-js-testing';

test('deployed function processes orders', async () => {
  const runner = new DurableFunctionCloudTestRunner({
    functionName: 'order-processor',
    region: 'us-east-1'
  });
  
  const result = await runner.run({ orderId: 'order-123' });
  
  expect(result.status).toBe('SUCCEEDED');
  expect(result.result.status).toBe('completed');
});
```

------
#### [ Python ]

```
from aws_durable_execution_sdk_python_testing import (
    DurableFunctionCloudTestRunner,
    DurableFunctionCloudTestRunnerConfig
)

def test_deployed_function():
    config = DurableFunctionCloudTestRunnerConfig(
        function_name="order-processor",
        region="us-east-1"
    )
    runner = DurableFunctionCloudTestRunner(config=config)
    
    result = runner.run(input={"orderId": "order-123"})
    
    assert result.status is InvocationStatus.SUCCEEDED
    assert result.result["status"] == "completed"
```

------

云测试调用实际部署的函数并从 AWS 中检索执行历史记录。这使您可以验证与其他 AWS 服务的集成，检验性能特征，并使用与生产环境类似的数据和配置进行测试。

## 测试内容
<a name="durable-testing-patterns"></a>

通过验证执行结果、操作行为和错误处理来测试持久性函数。要注重业务逻辑的正确性，而非实施细节。

**验证执行结果：**检查函数是否返回给定输入的预期值。同时测试成功执行和错误情况，以确保函数能够正确处理无效输入。

**检查操作执行情况：**验证步骤、等待和回调是否按预期执行。检查步骤结果，以确保中间操作能得出正确的值。验证等待操作已按照适当的超时设置进行配置，并且回调函数是按照正确的设置创建的。

**测试错误处理：**当输入无效数据时，验证函数会正确地返回描述性的错误信息。通过模拟暂时性故障并确认操作能够正确地进行重试来测试重试行为。检查并确认永久性故障不会引发不必要的重试操作。

**验证工作流程：**对于多步骤工作流程，请确认操作按正确的顺序执行。测试条件分支以确保不同的执行路径能够正确运行。验证并行操作能够同时执行，并产生预期的结果。

SDK 文档存储库中包含大量关于测试模式的示例，包括多步骤工作流程、错误场景、超时处理以及轮询模式等。

## 测试策略
<a name="durable-testing-strategy"></a>

在开发过程以及 CI/CD 管道中，使用本地测试来执行单元测试。本地测试运行速度快，不需要 AWS 凭证，并且能即时反馈代码变更情况。编写本地测试以验证业务逻辑、错误处理以及操作行为。

在部署到生产环境之前，请使用云测试进行集成测试。云测试通过真实的 AWS 服务和配置验证其行为，验证性能特征，并测试端到端的工作流程。在暂存环境中运行云测试，以便在问题影响到生产环境之前就捕获集成问题。

在本地测试中模拟外部依赖项，以隔离函数逻辑并保持测试速度。使用云测试来验证与外部服务（如数据库、API 和其他 AWS 服务）的实际集成。

编写有针对性的测试，以验证单一特定行为。使用描述性的测试名称，以说明正在测试的内容。将相关测试组合在一起，并使用测试夹具来编写通用的设置代码。保持测试简单，避免使用难以理解的复杂测试逻辑。

## 调试失败
<a name="durable-testing-debugging"></a>

当测试失败时，检查执行结果以了解问题出在哪里。查看执行状态，以确定函数是成功、失败还是超时。阅读错误消息以了解失败原因。

检查各项操作结果，以找出行为与预期不符的地方。检查步骤结果，以查看产生了哪些值。验证操作顺序，以确认操作按照预期的顺序进行。对操作进行计数，以确保创建了适当数量的步骤、等待和回调。

常见的问题包括：非确定性代码在重放时会产生不同的结果；通过全局变量实现的共享状态在重放时会失效；以及由于条件逻辑错误而导致的操作缺失。使用标准的调试器和日志记录功能逐行执行函数代码并追踪执行流程。

对于云端测试，可在 CloudWatch Logs 中检查执行历史记录，以查看详细的操作日志。利用跟踪功能来跟踪跨服务的执行流程，并找出瓶颈所在。