

# Lambda の耐久関数のテスト
<a name="durable-testing"></a>

AWS は、ローカルとクラウドの両方で実行を動作させ検査できる耐久関数専用のテスト SDK を提供します。言語用のテスト SDK をインストールします。

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

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

詳細なドキュメントと例については、GitHub の「[TypeScript testing 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
```

詳細なドキュメントと例については、GitHub の「[Python testing SDK](https://github.com/aws/aws-durable-execution-sdk-python-testing)」を参照してください。

------

テスト SDK には、高速ユニットテスト用のローカルテストと、デプロイされた関数に対する統合テスト用のクラウドテストの 2 つのテストモードがあります。

## ローカルテスト
<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 サービスなどの外部サービスとの実際の統合を検証します。

1 つの特定の動作を検証する重点テストを記述します。テスト対象を説明するわかりやすいテスト名を使用します。関連するテストをグループ化し、一般的なセットアップコードに試験装置を使用します。テストはシンプルに保ち、わかりにくい複雑なテストロジックは避けてください。

## デバッグの失敗
<a name="durable-testing-debugging"></a>

テストが失敗したら、実行結果を検査して、何が失敗したかを把握します。実行ステータスをチェックして、関数が成功、失敗、またはタイムアウトしたかどうかを確認します。エラーメッセージを読み、障害の原因を把握します。

個々のオペレーション結果を調べて、動作が予想と異なる場所を見つけます。ステップの結果をチェックして、生成された値を確認します。オペレーションの順序を確認し、オペレーションが予想される順序で実行されていることを確認します。オペレーションをカウントして、適切な数のステップ、待機、コールバックが作成されていることを確認します。

一般的な問題には、リプレイ時に異なる結果を生成する非決定的なコード、リプレイ中に破損するグローバル変数を介した共有状態、条件付きロジックエラーによる操作の欠落などがあります。標準的なデバッガーとログを使用して、関数コードをステップスルーし、実行フローを追跡します。

クラウドテストの場合は、CloudWatch Logs の実行履歴を調べて、詳細なオペレーションログを確認します。トレースを使用して、サービス全体の実行フローを追跡し、ボトルネックを特定します。