

Ini adalah Panduan Pengembang AWS CDK v2. CDK v1 yang lebih lama memasuki pemeliharaan pada 1 Juni 2022 dan mengakhiri dukungan pada 1 Juni 2023.

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

# Uji AWS aplikasi CDK
<a name="testing"></a>

Dengan AWS CDK, infrastruktur Anda dapat diuji seperti kode lain yang Anda tulis. Anda dapat menguji di cloud dan secara lokal. Topik ini membahas cara menguji di cloud. Untuk panduan tentang pengujian lokal, lihat [Uji lokal dan buat aplikasi AWS CDK dengan SAM AWS CLI](testing-locally.md). [Pendekatan standar untuk menguji aplikasi AWS CDK menggunakan modul [pernyataan AWS CDK dan kerangka kerja pengujian](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.assertions-readme.html) populer seperti [Jest](https://jestjs.io/) untuk dan atau Pytest untuk Python. TypeScript JavaScript ](https://docs.pytest.org/en/6.2.x/)

Ada dua kategori tes yang dapat Anda tulis untuk aplikasi AWS CDK.
+  **Pernyataan berbutir halus** menguji aspek spesifik dari AWS CloudFormation templat yang dihasilkan, seperti “sumber daya ini memiliki properti ini dengan nilai ini.” Tes ini dapat mendeteksi regresi. Mereka juga berguna saat Anda mengembangkan fitur baru menggunakan pengembangan berbasis tes. (Anda dapat menulis tes terlebih dahulu, kemudian membuatnya lulus dengan menulis implementasi yang benar.) Pernyataan berbutir halus adalah tes yang paling sering digunakan.
+  **Tes snapshot** menguji template yang disintesis terhadap AWS CloudFormation template dasar yang disimpan sebelumnya. Tes snapshot memungkinkan Anda melakukan refactor secara bebas, karena Anda dapat yakin bahwa kode refactored bekerja persis dengan cara yang sama seperti aslinya. Jika perubahan itu disengaja, Anda dapat menerima baseline baru untuk pengujian masa depan. Namun, peningkatan CDK juga dapat menyebabkan templat yang disintesis berubah, jadi Anda tidak dapat hanya mengandalkan snapshot untuk memastikan implementasi Anda benar.

**catatan**  
Versi lengkap aplikasi TypeScript, Python, dan Java yang digunakan sebagai contoh dalam topik ini [tersedia](https://github.com/cdklabs/aws-cdk-testing-examples/) di. GitHub

## Mulai menggunakan
<a name="testing-getting-started"></a>

Untuk mengilustrasikan cara menulis tes ini, kita akan membuat tumpukan yang berisi mesin status AWS Step Functions dan fungsi AWS Lambda. Fungsi Lambda berlangganan topik Amazon SNS dan hanya meneruskan pesan ke mesin status.

Pertama, buat proyek aplikasi CDK kosong menggunakan CDK Toolkit dan instal pustaka yang kita perlukan. Konstruksi yang akan kita gunakan semuanya ada dalam paket CDK utama, yang merupakan ketergantungan default dalam proyek yang dibuat dengan CDK Toolkit. Namun, Anda harus menginstal kerangka pengujian Anda.

**Example**  

```
$ mkdir state-machine && cd state-machine
cdk init --language=typescript
npm install --save-dev jest @types/jest
```
Buat direktori untuk pengujian Anda.  

```
$ mkdir test
```
Edit proyek `package.json` untuk memberi tahu NPM cara menjalankan Jest, dan untuk memberi tahu Jest jenis file apa yang harus dikumpulkan. Perubahan yang diperlukan adalah sebagai berikut.  
+ Tambahkan `test` kunci baru ke `scripts` bagian
+ Tambahkan Jest dan jenisnya ke bagian `devDependencies`
+ Tambahkan kunci `jest` tingkat atas baru dengan deklarasi `moduleFileExtensions`
Perubahan ini ditunjukkan pada garis besar berikut. Tempatkan teks baru di tempat yang ditunjukkan`package.json`. Placeholder “...” menunjukkan bagian file yang ada yang tidak boleh diubah.  

```
{
  ...
  "scripts": {
    ...
    "test": "jest"
  },
  "devDependencies": {
    ...
    "@types/jest": "^24.0.18",
    "jest": "^24.9.0"
  },
  "jest": {
    "moduleFileExtensions": ["js"]
  }
}
```

```
$ mkdir state-machine && cd state-machine
$ cdk init --language=javascript
$ npm install --save-dev jest
```
Buat direktori untuk pengujian Anda.  

```
$ mkdir test
```
Edit proyek `package.json` untuk memberi tahu NPM cara menjalankan Jest, dan untuk memberi tahu Jest jenis file apa yang harus dikumpulkan. Perubahan yang diperlukan adalah sebagai berikut.  
+ Tambahkan `test` kunci baru ke `scripts` bagian
+ Tambahkan Jest ke bagian `devDependencies`
+ Tambahkan kunci `jest` tingkat atas baru dengan deklarasi `moduleFileExtensions`
Perubahan ini ditunjukkan pada garis besar berikut. Tempatkan teks baru di tempat yang ditunjukkan`package.json`. Placeholder “...” menunjukkan bagian file yang ada yang tidak boleh diubah.  

```
{
  ...
  "scripts": {
    ...
    "test": "jest"
  },
  "devDependencies": {
    ...
    "jest": "^24.9.0"
  },
  "jest": {
    "moduleFileExtensions": ["js"]
  }
}
```

```
$ mkdir state-machine && cd state-machine
$ cdk init --language=python
$ source .venv/bin/activate # On Windows, run '.\venv\Scripts\activate' instead
$ python -m pip install -r requirements.txt
$ python -m pip install -r requirements-dev.txt
```

```
$ mkdir state-machine && cd-state-machine
$ cdk init --language=java
```
Buka proyek di IDE Java pilihan Anda. (Di Eclipse, gunakan **File> **Import** > Existing** Maven Projects.)

```
$ mkdir state-machine && cd-state-machine
$ cdk init --language=csharp
```
Buka `src\StateMachine.sln` di Visual Studio.  
Klik kanan solusi di Solution Explorer dan pilih **Add** > **New Project**. Cari MSTest C \$1 dan tambahkan **Proyek MSTest Uji** untuk C \$1. (Nama default `TestProject1`baik-baik saja.)  
Klik kanan `TestProject1` dan pilih **Add** > **Project Reference**, dan tambahkan `StateMachine` proyek sebagai referensi.

## Contoh tumpukan
<a name="testing-app"></a>

Inilah tumpukan yang akan diuji dalam topik ini. Seperti yang telah kami jelaskan sebelumnya, ini berisi fungsi Lambda dan mesin status Step Functions, dan menerima satu atau beberapa topik Amazon SNS. Fungsi Lambda berlangganan topik Amazon SNS dan meneruskannya ke mesin status.

Anda tidak perlu melakukan sesuatu yang istimewa untuk membuat aplikasi dapat diuji. Faktanya, tumpukan CDK ini tidak berbeda dengan cara yang penting dari tumpukan contoh lainnya dalam Panduan ini.

**Example**  
Tempatkan kode berikut di`lib/state-machine-stack.ts`:  

```
import * as cdk from "aws-cdk-lib";
import * as sns from "aws-cdk-lib/aws-sns";
import * as sns_subscriptions from "aws-cdk-lib/aws-sns-subscriptions";
import * as lambda from "aws-cdk-lib/aws-lambda";
import * as sfn from "aws-cdk-lib/aws-stepfunctions";
import { Construct } from "constructs";

export interface StateMachineStackProps extends cdk.StackProps {
  readonly topics: sns.Topic[];
}

export class StateMachineStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props: StateMachineStackProps) {
    super(scope, id, props);

    // In the future this state machine will do some work...
    const stateMachine = new sfn.StateMachine(this, "StateMachine", {
      definition: new sfn.Pass(this, "StartState"),
    });

    // This Lambda function starts the state machine.
    const func = new lambda.Function(this, "LambdaFunction", {
      runtime: lambda.Runtime.NODEJS_18_X,
      handler: "handler",
      code: lambda.Code.fromAsset("./start-state-machine"),
      environment: {
        STATE_MACHINE_ARN: stateMachine.stateMachineArn,
      },
    });
    stateMachine.grants.startExecution(func);

    const subscription = new sns_subscriptions.LambdaSubscription(func);
    for (const topic of props.topics) {
      topic.addSubscription(subscription);
    }
  }
}
```
Tempatkan kode berikut di`lib/state-machine-stack.js`:  

```
const cdk = require("aws-cdk-lib");
const sns = require("aws-cdk-lib/aws-sns");
const sns_subscriptions = require("aws-cdk-lib/aws-sns-subscriptions");
const lambda = require("aws-cdk-lib/aws-lambda");
const sfn = require("aws-cdk-lib/aws-stepfunctions");

class StateMachineStack extends cdk.Stack {
  constructor(scope, id, props) {
    super(scope, id, props);

    // In the future this state machine will do some work...
    const stateMachine = new sfn.StateMachine(this, "StateMachine", {
      definition: new sfn.Pass(this, "StartState"),
    });

    // This Lambda function starts the state machine.
    const func = new lambda.Function(this, "LambdaFunction", {
      runtime: lambda.Runtime.NODEJS_18_X,
      handler: "handler",
      code: lambda.Code.fromAsset("./start-state-machine"),
      environment: {
        STATE_MACHINE_ARN: stateMachine.stateMachineArn,
      },
    });
    stateMachine.grants.startExecution(func);

    const subscription = new sns_subscriptions.LambdaSubscription(func);
    for (const topic of props.topics) {
      topic.addSubscription(subscription);
    }
  }
}

module.exports = { StateMachineStack }
```
Tempatkan kode berikut di`state_machine/state_machine_stack.py`:  

```
from typing import List

import aws_cdk.aws_lambda as lambda_
import aws_cdk.aws_sns as sns
import aws_cdk.aws_sns_subscriptions as sns_subscriptions
import aws_cdk.aws_stepfunctions as sfn
import aws_cdk as cdk

class StateMachineStack(cdk.Stack):
    def __init__(
        self,
        scope: cdk.Construct,
        construct_id: str,
        *,
        topics: List[sns.Topic],
        **kwargs
    ) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # In the future this state machine will do some work...
        state_machine = sfn.StateMachine(
            self, "StateMachine", definition=sfn.Pass(self, "StartState")
        )

        # This Lambda function starts the state machine.
        func = lambda_.Function(
            self,
            "LambdaFunction",
            runtime=lambda_.Runtime.NODEJS_18_X,
            handler="handler",
            code=lambda_.Code.from_asset("./start-state-machine"),
            environment={
                "STATE_MACHINE_ARN": state_machine.state_machine_arn,
            },
        )
        state_machine.grants.start_execution(func)

        subscription = sns_subscriptions.LambdaSubscription(func)
        for topic in topics:
            topic.add_subscription(subscription)
```

```
package software.amazon.samples.awscdkassertionssamples;

import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.amazon.awscdk.services.lambda.Code;
import software.amazon.awscdk.services.lambda.Function;
import software.amazon.awscdk.services.lambda.Runtime;
import software.amazon.awscdk.services.sns.ITopicSubscription;
import software.amazon.awscdk.services.sns.Topic;
import software.amazon.awscdk.services.sns.subscriptions.LambdaSubscription;
import software.amazon.awscdk.services.stepfunctions.Pass;
import software.amazon.awscdk.services.stepfunctions.StateMachine;

import java.util.Collections;
import java.util.List;

public class StateMachineStack extends Stack {
    public StateMachineStack(final Construct scope, final String id, final List<Topic> topics) {
        this(scope, id, null, topics);
    }

    public StateMachineStack(final Construct scope, final String id, final StackProps props, final List<Topic> topics) {
        super(scope, id, props);

        // In the future this state machine will do some work...
        final StateMachine stateMachine = StateMachine.Builder.create(this, "StateMachine")
                .definition(new Pass(this, "StartState"))
                .build();

        // This Lambda function starts the state machine.
        final Function func = Function.Builder.create(this, "LambdaFunction")
                .runtime(Runtime.NODEJS_18_X)
                .handler("handler")
                .code(Code.fromAsset("./start-state-machine"))
                .environment(Collections.singletonMap("STATE_MACHINE_ARN", stateMachine.getStateMachineArn()))
                .build();
        stateMachine.getGrants().startExecution(func);

        final ITopicSubscription subscription = new LambdaSubscription(func);
        for (final Topic topic : topics) {
            topic.addSubscription(subscription);
        }
    }
}
```

```
using Amazon.CDK;
using Amazon.CDK.AWS.Lambda;
using Amazon.CDK.AWS.StepFunctions;
using Amazon.CDK.AWS.SNS;
using Amazon.CDK.AWS.SNS.Subscriptions;
using Constructs;

using System.Collections.Generic;

namespace AwsCdkAssertionSamples
{
    public class StateMachineStackProps : StackProps
    {
        public Topic[] Topics;
    }

    public class StateMachineStack : Stack
    {

        internal StateMachineStack(Construct scope, string id, StateMachineStackProps props = null) : base(scope, id, props)
        {
            // In the future this state machine will do some work...
            var stateMachine = new StateMachine(this, "StateMachine", new StateMachineProps
            {
                Definition = new Pass(this, "StartState")
            });

            // This Lambda function starts the state machine.
            var func = new Function(this, "LambdaFunction", new FunctionProps
            {
                Runtime = Runtime.NODEJS_18_X,
                Handler = "handler",
                Code = Code.FromAsset("./start-state-machine"),
                Environment = new Dictionary<string, string>
                {
                    { "STATE_MACHINE_ARN", stateMachine.StateMachineArn }
                }
            });
            stateMachine.Grants.StartExecution(func);

            foreach (Topic topic in props?.Topics ?? new Topic[0])
            {
                var subscription = new LambdaSubscription(func);
            }

        }
    }
}
```

Kita akan memodifikasi titik masuk utama aplikasi sehingga kita tidak benar-benar membuat instance stack kita. Kami tidak ingin menyebarkannya secara tidak sengaja. Pengujian kami akan membuat aplikasi dan instance tumpukan untuk pengujian. Ini adalah taktik yang berguna bila dikombinasikan dengan pengembangan berbasis tes: pastikan tumpukan melewati semua pengujian sebelum Anda mengaktifkan penerapan.

**Example**  
Dalam `bin/state-machine.ts`:  

```
#!/usr/bin/env node
import * as cdk from "aws-cdk-lib";

const app = new cdk.App();

// Stacks are intentionally not created here -- this application isn't meant to
// be deployed.
```
Dalam `bin/state-machine.js`:  

```
#!/usr/bin/env node
const cdk = require("aws-cdk-lib");

const app = new cdk.App();

// Stacks are intentionally not created here -- this application isn't meant to
// be deployed.
```
Dalam `app.py`:  

```
#!/usr/bin/env python3
import os

import aws_cdk  as cdk

app = cdk.App()

# Stacks are intentionally not created here -- this application isn't meant to
# be deployed.

app.synth()
```

```
package software.amazon.samples.awscdkassertionssamples;

import software.amazon.awscdk.App;

public class SampleApp {
    public static void main(final String[] args) {
        App app = new App();

        // Stacks are intentionally not created here -- this application isn't meant to be deployed.

        app.synth();
    }
}
```

```
using Amazon.CDK;

namespace AwsCdkAssertionSamples
{
    sealed class Program
    {
        public static void Main(string[] args)
        {
            var app = new App();

            // Stacks are intentionally not created here -- this application isn't meant to be deployed.

            app.Synth();
        }
    }
}
```

## Fungsi Lambda
<a name="testing-lambda"></a>

Contoh tumpukan kami mencakup fungsi Lambda yang memulai mesin status kami. Kita harus menyediakan kode sumber untuk fungsi ini sehingga CDK dapat menggabungkan dan menyebarkannya sebagai bagian dari pembuatan sumber daya fungsi Lambda.
+ Buat folder `start-state-machine` di direktori utama aplikasi.
+ Di folder ini, buat setidaknya satu file. Misalnya, Anda dapat menyimpan kode berikut di`start-state-machines/index.js`.

  ```
  exports.handler = async function (event, context) {
  	return 'hello world';
  };
  ```

  Namun, file apa pun akan berfungsi, karena kami tidak akan benar-benar menyebarkan tumpukan.

## Menjalankan tes
<a name="testing-running-tests"></a>

Sebagai referensi, berikut adalah perintah yang Anda gunakan untuk menjalankan pengujian di aplikasi AWS CDK Anda. Ini adalah perintah yang sama yang akan Anda gunakan untuk menjalankan pengujian dalam proyek apa pun menggunakan kerangka pengujian yang sama. Untuk bahasa yang memerlukan langkah build, sertakan itu untuk memastikan pengujian Anda telah dikompilasi.

**Example**  

```
$ tsc && npm test
```

```
$ npm test
```

```
$ python -m pytest
```

```
$ mvn compile && mvn test
```
Bangun solusi Anda (F6) untuk menemukan pengujian, lalu jalankan pengujian (**Test** > **Run All Tests**). Untuk memilih tes mana yang akan dijalankan, buka Test Explorer (**Test** > **Test Explorer**).  
Atau:  

```
$ dotnet test src
```

## Pernyataan berbutir halus
<a name="testing-fine-grained"></a>

Langkah pertama untuk menguji tumpukan dengan pernyataan berbutir halus adalah mensintesis tumpukan, karena kami menulis pernyataan terhadap template yang dihasilkan. AWS CloudFormation 

Kami `StateMachineStackStack` mengharuskan kami meneruskan topik Amazon SNS untuk diteruskan ke mesin negara. Jadi dalam pengujian kami, kami akan membuat tumpukan terpisah untuk memuat topik.

Biasanya, saat menulis aplikasi CDK, Anda dapat mensubkelas `Stack` dan membuat instance topik Amazon SNS di konstruktor tumpukan. Dalam pengujian kami, kami membuat instance `Stack` secara langsung, lalu meneruskan tumpukan ini sebagai ruang lingkup, melampirkannya ke tumpukan. `Topic` Ini setara secara fungsional dan kurang bertele-tele. Ini juga membantu membuat tumpukan yang hanya digunakan dalam pengujian “terlihat berbeda” dari tumpukan yang ingin Anda terapkan.

**Example**  

```
import { Capture, Match, Template } from "aws-cdk-lib/assertions";
import * as cdk from "aws-cdk-lib";
import * as sns from "aws-cdk-lib/aws-sns";
import { StateMachineStack } from "../lib/state-machine-stack";

describe("StateMachineStack", () => {
  test("synthesizes the way we expect", () => {
    const app = new cdk.App();

    // Since the StateMachineStack consumes resources from a separate stack
    // (cross-stack references), we create a stack for our SNS topics to live
    // in here. These topics can then be passed to the StateMachineStack later,
    // creating a cross-stack reference.
    const topicsStack = new cdk.Stack(app, "TopicsStack");

    // Create the topic the stack we're testing will reference.
    const topics = [new sns.Topic(topicsStack, "Topic1", {})];

    // Create the StateMachineStack.
    const stateMachineStack = new StateMachineStack(app, "StateMachineStack", {
      topics: topics, // Cross-stack reference
    });

    // Prepare the stack for assertions.
    const template = Template.fromStack(stateMachineStack);
  })
})
```

```
const { Capture, Match, Template } = require("aws-cdk-lib/assertions");
const cdk = require("aws-cdk-lib");
const sns = require("aws-cdk-lib/aws-sns");
const { StateMachineStack } = require("../lib/state-machine-stack");

describe("StateMachineStack", () => {
  test("synthesizes the way we expect", () => {
    const app = new cdk.App();

    // Since the StateMachineStack consumes resources from a separate stack
    // (cross-stack references), we create a stack for our SNS topics to live
    // in here. These topics can then be passed to the StateMachineStack later,
    // creating a cross-stack reference.
    const topicsStack = new cdk.Stack(app, "TopicsStack");

    // Create the topic the stack we're testing will reference.
    const topics = [new sns.Topic(topicsStack, "Topic1", {})];

    // Create the StateMachineStack.
    const StateMachineStack = new StateMachineStack(app, "StateMachineStack", {
      topics: topics, // Cross-stack reference
    });

    // Prepare the stack for assertions.
    const template = Template.fromStack(stateMachineStack);
  })
})
```

```
from aws_cdk import aws_sns as sns
import aws_cdk as cdk
from aws_cdk.assertions import Template

from app.state_machine_stack import StateMachineStack

def test_synthesizes_properly():
    app = cdk.App()

    # Since the StateMachineStack consumes resources from a separate stack
    # (cross-stack references), we create a stack for our SNS topics to live
    # in here. These topics can then be passed to the StateMachineStack later,
    # creating a cross-stack reference.
    topics_stack = cdk.Stack(app, "TopicsStack")

    # Create the topic the stack we're testing will reference.
    topics = [sns.Topic(topics_stack, "Topic1")]

    # Create the StateMachineStack.
    state_machine_stack = StateMachineStack(
        app, "StateMachineStack", topics=topics  # Cross-stack reference
    )

    # Prepare the stack for assertions.
    template = Template.from_stack(state_machine_stack)
```

```
package software.amazon.samples.awscdkassertionssamples;

import org.junit.jupiter.api.Test;
import software.amazon.awscdk.assertions.Capture;
import software.amazon.awscdk.assertions.Match;
import software.amazon.awscdk.assertions.Template;
import software.amazon.awscdk.App;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.services.sns.Topic;

import java.util.*;

import static org.assertj.core.api.Assertions.assertThat;

public class StateMachineStackTest {
    @Test
    public void testSynthesizesProperly() {
        final App app = new App();

        // Since the StateMachineStack consumes resources from a separate stack (cross-stack references), we create a stack
        // for our SNS topics to live in here. These topics can then be passed to the StateMachineStack later, creating a
        // cross-stack reference.
        final Stack topicsStack = new Stack(app, "TopicsStack");

        // Create the topic the stack we're testing will reference.
        final List<Topic> topics = Collections.singletonList(Topic.Builder.create(topicsStack, "Topic1").build());

        // Create the StateMachineStack.
        final StateMachineStack stateMachineStack = new StateMachineStack(
                app,
                "StateMachineStack",
                topics // Cross-stack reference
        );

        // Prepare the stack for assertions.
        final Template template = Template.fromStack(stateMachineStack)
    }
}
```

```
using Microsoft.VisualStudio.TestTools.UnitTesting;

using Amazon.CDK;
using Amazon.CDK.AWS.SNS;
using Amazon.CDK.Assertions;
using AwsCdkAssertionSamples;

using ObjectDict = System.Collections.Generic.Dictionary<string, object>;
using StringDict = System.Collections.Generic.Dictionary<string, string>;

namespace TestProject1
{
    [TestClass]
    public class StateMachineStackTest
    {
        [TestMethod]
        public void TestMethod1()
        {
            var app = new App();

            // Since the StateMachineStack consumes resources from a separate stack (cross-stack references), we create a stack
            // for our SNS topics to live in here. These topics can then be passed to the StateMachineStack later, creating a
            // cross-stack reference.
            var topicsStack = new Stack(app, "TopicsStack");

            // Create the topic the stack we're testing will reference.
            var topics = new Topic[] { new Topic(topicsStack, "Topic1") };

            // Create the StateMachineStack.
            var StateMachineStack = new StateMachineStack(app, "StateMachineStack", new StateMachineStackProps
            {
                Topics = topics
            });

            // Prepare the stack for assertions.
            var template = Template.FromStack(stateMachineStack);

            // test will go here
        }
    }
}
```

Sekarang kita dapat menegaskan bahwa fungsi Lambda dan langganan Amazon SNS telah dibuat.

**Example**  

```
    // Assert it creates the function with the correct properties...
    template.hasResourceProperties("AWS::Lambda::Function", {
      Handler: "handler",
      Runtime: "nodejs14.x",
    });

    // Creates the subscription...
    template.resourceCountIs("AWS::SNS::Subscription", 1);
```

```
    // Assert it creates the function with the correct properties...
    template.hasResourceProperties("AWS::Lambda::Function", {
      Handler: "handler",
      Runtime: "nodejs14.x",
    });

    // Creates the subscription...
    template.resourceCountIs("AWS::SNS::Subscription", 1);
```

```
# Assert that we have created the function with the correct properties
    template.has_resource_properties(
        "AWS::Lambda::Function",
        {
            "Handler": "handler",
            "Runtime": "nodejs14.x",
        },
    )

    # Assert that we have created a subscription
    template.resource_count_is("AWS::SNS::Subscription", 1)
```

```
        // Assert it creates the function with the correct properties...
        template.hasResourceProperties("AWS::Lambda::Function", Map.of(
                "Handler", "handler",
                "Runtime", "nodejs14.x"
        ));

         // Creates the subscription...
        template.resourceCountIs("AWS::SNS::Subscription", 1);
```

```
            // Prepare the stack for assertions.
            var template = Template.FromStack(stateMachineStack);

            // Assert it creates the function with the correct properties...
            template.HasResourceProperties("AWS::Lambda::Function", new StringDict {
                { "Handler", "handler"},
                { "Runtime", "nodejs14x" }
            });

            // Creates the subscription...
            template.ResourceCountIs("AWS::SNS::Subscription", 1);
```

Uji fungsi Lambda kami menegaskan bahwa dua properti tertentu dari sumber daya fungsi memiliki nilai tertentu. Secara default, `hasResourceProperties` metode melakukan kecocokan sebagian pada properti sumber daya seperti yang diberikan dalam CloudFormation template yang disintesis. Tes ini mengharuskan properti yang disediakan ada dan memiliki nilai yang ditentukan, tetapi sumber daya juga dapat memiliki properti lain, yang tidak diuji.

Pernyataan Amazon SNS kami menegaskan bahwa template yang disintesis berisi langganan, tetapi tidak ada tentang langganan itu sendiri. Kami menyertakan pernyataan ini terutama untuk menggambarkan bagaimana menegaskan jumlah sumber daya. `Template`Kelas menawarkan metode yang lebih spesifik untuk menulis pernyataan terhadap`Resources`,`Outputs`, dan `Mapping` bagian dari template. CloudFormation <a name="testing-fine-grained-matchers"></a>

 **Matcher**   
Perilaku pencocokan paral default `hasResourceProperties` dapat diubah menggunakan *matcher* dari kelas. ` [Match](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.assertions.Match.html#methods) `  
Matcher berkisar dari lunak () hingga ketat (`Match.anyValue`). `Match.objectEquals` Mereka dapat disarangkan untuk menerapkan metode pencocokan yang berbeda ke berbagai bagian properti sumber daya. Menggunakan `Match.objectEquals` dan `Match.anyValue` bersama-sama, misalnya, kita dapat menguji peran IAM mesin status lebih lengkap, sementara tidak memerlukan nilai spesifik untuk properti yang dapat berubah.  

**Example**  

```
    // Fully assert on the state machine's IAM role with matchers.
    template.hasResourceProperties(
      "AWS::IAM::Role",
      Match.objectEquals({
        AssumeRolePolicyDocument: {
          Version: "2012-10-17",		 	 	 
          Statement: [
            {
              Action: "sts:AssumeRole",
              Effect: "Allow",
              Principal: {
                Service: {
                  "Fn::Join": [
                    "",
                    ["states.", Match.anyValue(), ".amazonaws.com"],
                  ],
                },
              },
            },
          ],
        },
      })
    );
```

```
    // Fully assert on the state machine's IAM role with matchers.
    template.hasResourceProperties(
      "AWS::IAM::Role",
      Match.objectEquals({
        AssumeRolePolicyDocument: {
          Version: "2012-10-17",		 	 	 
          Statement: [
            {
              Action: "sts:AssumeRole",
              Effect: "Allow",
              Principal: {
                Service: {
                  "Fn::Join": [
                    "",
                    ["states.", Match.anyValue(), ".amazonaws.com"],
                  ],
                },
              },
            },
          ],
        },
      })
    );
```

```
from aws_cdk.assertions import Match

    # Fully assert on the state machine's IAM role with matchers.
    template.has_resource_properties(
        "AWS::IAM::Role",
        Match.object_equals(
            {
                "AssumeRolePolicyDocument": {
                    "Version": "2012-10-17",		 	 	 
                    "Statement": [
                        {
                            "Action": "sts:AssumeRole",
                            "Effect": "Allow",
                            "Principal": {
                                "Service": {
                                    "Fn::Join": [
                                        "",
                                        [
                                            "states.",
                                            Match.any_value(),
                                            ".amazonaws.com",
                                        ],
                                    ],
                                },
                            },
                        },
                    ],
                },
            }
        ),
    )
```

```
        // Fully assert on the state machine's IAM role with matchers.
        template.hasResourceProperties("AWS::IAM::Role", Match.objectEquals(
                Collections.singletonMap("AssumeRolePolicyDocument", Map.of(
                        "Version", "2012-10-17",		 	 	 
                        "Statement", Collections.singletonList(Map.of(
                                "Action", "sts:AssumeRole",
                                "Effect", "Allow",
                                "Principal", Collections.singletonMap(
                                        "Service", Collections.singletonMap(
                                                "Fn::Join", Arrays.asList(
                                                        "",
                                                        Arrays.asList("states.", Match.anyValue(), ".amazonaws.com")
                                                )
                                        )
                                )
                        ))
                ))
        ));
```

```
            // Fully assert on the state machine's IAM role with matchers.
            template.HasResource("AWS::IAM::Role", Match.ObjectEquals(new ObjectDict
            {
                { "AssumeRolePolicyDocument", new ObjectDict
                    {
                        { "Version", "2012-10-17"		 	 	  },
                        { "Action", "sts:AssumeRole" },
                        { "Principal", new ObjectDict
                            {
                                { "Version", "2012-10-17"		 	 	  },
                                { "Statement", new object[]
                                    {
                                        new ObjectDict {
                                            { "Action", "sts:AssumeRole" },
                                            { "Effect", "Allow" },
                                            { "Principal", new ObjectDict
                                                {
                                                    { "Service", new ObjectDict
                                                        {
                                                            { "", new object[]
                                                                { "states", Match.AnyValue(), ".amazonaws.com" }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }));
```
Banyak CloudFormation sumber daya termasuk objek JSON serial yang direpresentasikan sebagai string. `Match.serializedJson()`Matcher dapat digunakan untuk mencocokkan properti di dalam JSON ini.  
Misalnya, mesin status Step Functions didefinisikan menggunakan string dalam [Amazon](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-amazon-states-language.html) States Language berbasis JSON. Kita akan gunakan `Match.serializedJson()` untuk memastikan bahwa status awal kita adalah satu-satunya langkah. Sekali lagi, kita akan menggunakan pencocokan bersarang untuk menerapkan berbagai jenis pencocokan ke berbagai bagian objek.  

**Example**  

```
    // Assert on the state machine's definition with the Match.serializedJson()
    // matcher.
    template.hasResourceProperties("AWS::StepFunctions::StateMachine", {
      DefinitionString: Match.serializedJson(
        // Match.objectEquals() is used implicitly, but we use it explicitly
        // here for extra clarity.
        Match.objectEquals({
          StartAt: "StartState",
          States: {
            StartState: {
              Type: "Pass",
              End: true,
              // Make sure this state doesn't provide a next state -- we can't
              // provide both Next and set End to true.
              Next: Match.absent(),
            },
          },
        })
      ),
    });
```

```
    // Assert on the state machine's definition with the Match.serializedJson()
    // matcher.
    template.hasResourceProperties("AWS::StepFunctions::StateMachine", {
      DefinitionString: Match.serializedJson(
        // Match.objectEquals() is used implicitly, but we use it explicitly
        // here for extra clarity.
        Match.objectEquals({
          StartAt: "StartState",
          States: {
            StartState: {
              Type: "Pass",
              End: true,
              // Make sure this state doesn't provide a next state -- we can't
              // provide both Next and set End to true.
              Next: Match.absent(),
            },
          },
        })
      ),
    });
```

```
    # Assert on the state machine's definition with the serialized_json matcher.
    template.has_resource_properties(
        "AWS::StepFunctions::StateMachine",
        {
            "DefinitionString": Match.serialized_json(
                # Match.object_equals() is the default, but specify it here for clarity
                Match.object_equals(
                    {
                        "StartAt": "StartState",
                        "States": {
                            "StartState": {
                                "Type": "Pass",
                                "End": True,
                                # Make sure this state doesn't provide a next state --
                                # we can't provide both Next and set End to true.
                                "Next": Match.absent(),
                            },
                        },
                    }
                )
            ),
        },
    )
```

```
        // Assert on the state machine's definition with the Match.serializedJson() matcher.
        template.hasResourceProperties("AWS::StepFunctions::StateMachine", Collections.singletonMap(
                "DefinitionString", Match.serializedJson(
                        // Match.objectEquals() is used implicitly, but we use it explicitly here for extra clarity.
                        Match.objectEquals(Map.of(
                                "StartAt", "StartState",
                                "States", Collections.singletonMap(
                                        "StartState", Map.of(
                                                "Type", "Pass",
                                                "End", true,
                                                // Make sure this state doesn't provide a next state -- we can't provide
                                                // both Next and set End to true.
                                                "Next", Match.absent()
                                        )
                                )
                        ))
                )
        ));
```

```
            // Assert on the state machine's definition with the Match.serializedJson() matcher
            template.HasResourceProperties("AWS::StepFunctions::StateMachine", new ObjectDict
            {
                { "DefinitionString", Match.SerializedJson(
                    // Match.objectEquals() is used implicitly, but we use it explicitly here for extra clarity.
                    Match.ObjectEquals(new ObjectDict {
                        { "StartAt", "StartState" },
                        { "States", new ObjectDict
                        {
                            { "StartState", new ObjectDict {
                                { "Type", "Pass" },
                                { "End", "True" },
                                // Make sure this state doesn't provide a next state -- we can't provide
                                // both Next and set End to true.
                                { "Next", Match.Absent() }
                            }}
                        }}
                    })
                )}});
```<a name="testing-fine-grained-capture"></a>

 **Menangkap**   
Seringkali berguna untuk menguji properti untuk memastikan mereka mengikuti format tertentu, atau memiliki nilai yang sama dengan properti lain, tanpa perlu mengetahui nilai pastinya sebelumnya. `assertions`Modul ini menyediakan kemampuan ini di ` [Capture](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.assertions.Capture.html) ` kelasnya.  
Dengan menentukan `Capture` instance di tempat nilai di`hasResourceProperties`, nilai itu dipertahankan dalam objek. `Capture` Nilai yang ditangkap sebenarnya dapat diambil menggunakan `as` metode objek, termasuk`asNumber()`,`asString()`, dan`asObject`, dan diuji. Gunakan `Capture` dengan matcher untuk menentukan lokasi yang tepat dari nilai yang akan ditangkap dalam properti sumber daya, termasuk properti JSON serial.  
Contoh berikut menguji untuk memastikan bahwa status awal mesin status kami memiliki nama yang dimulai dengan`Start`. Ini juga menguji bahwa keadaan ini ada dalam daftar negara bagian dalam mesin.  

**Example**  

```
    // Capture some data from the state machine's definition.
    const startAtCapture = new Capture();
    const statesCapture = new Capture();
    template.hasResourceProperties("AWS::StepFunctions::StateMachine", {
      DefinitionString: Match.serializedJson(
        Match.objectLike({
          StartAt: startAtCapture,
          States: statesCapture,
        })
      ),
    });

    // Assert that the start state starts with "Start".
    expect(startAtCapture.asString()).toEqual(expect.stringMatching(/^Start/));

    // Assert that the start state actually exists in the states object of the
    // state machine definition.
    expect(statesCapture.asObject()).toHaveProperty(startAtCapture.asString());
```

```
    // Capture some data from the state machine's definition.
    const startAtCapture = new Capture();
    const statesCapture = new Capture();
    template.hasResourceProperties("AWS::StepFunctions::StateMachine", {
      DefinitionString: Match.serializedJson(
        Match.objectLike({
          StartAt: startAtCapture,
          States: statesCapture,
        })
      ),
    });

    // Assert that the start state starts with "Start".
    expect(startAtCapture.asString()).toEqual(expect.stringMatching(/^Start/));

    // Assert that the start state actually exists in the states object of the
    // state machine definition.
    expect(statesCapture.asObject()).toHaveProperty(startAtCapture.asString());
```

```
import re

    from aws_cdk.assertions import Capture

    # ...

    # Capture some data from the state machine's definition.
    start_at_capture = Capture()
    states_capture = Capture()
    template.has_resource_properties(
        "AWS::StepFunctions::StateMachine",
        {
            "DefinitionString": Match.serialized_json(
                Match.object_like(
                    {
                        "StartAt": start_at_capture,
                        "States": states_capture,
                    }
                )
            ),
        },
    )

    # Assert that the start state starts with "Start".
    assert re.match("^Start", start_at_capture.as_string())

    # Assert that the start state actually exists in the states object of the
    # state machine definition.
    assert start_at_capture.as_string() in states_capture.as_object()
```

```
        // Capture some data from the state machine's definition.
        final Capture startAtCapture = new Capture();
        final Capture statesCapture = new Capture();
        template.hasResourceProperties("AWS::StepFunctions::StateMachine", Collections.singletonMap(
                "DefinitionString", Match.serializedJson(
                        Match.objectLike(Map.of(
                                "StartAt", startAtCapture,
                                "States", statesCapture
                        ))
                )
        ));

        // Assert that the start state starts with "Start".
        assertThat(startAtCapture.asString()).matches("^Start.+");

        // Assert that the start state actually exists in the states object of the state machine definition.
        assertThat(statesCapture.asObject()).containsKey(startAtCapture.asString());
```

```
            // Capture some data from the state machine's definition.
            var startAtCapture = new Capture();
            var statesCapture = new Capture();
            template.HasResourceProperties("AWS::StepFunctions::StateMachine", new ObjectDict
            {
                { "DefinitionString", Match.SerializedJson(
                    new ObjectDict
                    {
                        { "StartAt", startAtCapture },
                        { "States", statesCapture }
                    }
                )}
            });

            Assert.IsTrue(startAtCapture.ToString().StartsWith("Start"));
            Assert.IsTrue(statesCapture.AsObject().ContainsKey(startAtCapture.ToString()));
```

## Tes snapshot
<a name="testing-snapshot"></a>

Dalam *pengujian snapshot*, Anda membandingkan seluruh template yang disintesis dengan CloudFormation template baseline yang disimpan sebelumnya (sering disebut “master”). Tidak seperti pernyataan berbutir halus, pengujian snapshot tidak berguna dalam menangkap regresi. Ini karena pengujian snapshot berlaku untuk seluruh template, dan hal-hal selain perubahan kode dapat menyebabkan perbedaan kecil (atau not-so-small) dalam hasil sintesis. Perubahan ini bahkan mungkin tidak memengaruhi penerapan Anda, tetapi masih akan menyebabkan pengujian snapshot gagal.

Misalnya, Anda dapat memperbarui konstruksi CDK untuk menggabungkan praktik terbaik baru, yang dapat menyebabkan perubahan pada sumber daya yang disintesis atau bagaimana mereka diatur. Atau, Anda dapat memperbarui CDK Toolkit ke versi yang melaporkan metadata tambahan. Perubahan nilai konteks juga dapat mempengaruhi template yang disintesis.

Namun, tes snapshot dapat sangat membantu dalam refactoring, selama Anda mempertahankan semua faktor lain yang dapat memengaruhi templat yang disintesis. Anda akan segera tahu jika perubahan yang Anda buat telah mengubah template secara tidak sengaja. Jika perubahan disengaja, cukup terima template baru sebagai baseline.

Misalnya, jika kita memiliki `DeadLetterQueue` konstruksi ini:

**Example**  

```
export class DeadLetterQueue extends sqs.Queue {
  public readonly messagesInQueueAlarm: cloudwatch.IAlarm;

  constructor(scope: Construct, id: string) {
    super(scope, id);

    // Add the alarm
    this.messagesInQueueAlarm = new cloudwatch.Alarm(this, 'Alarm', {
      alarmDescription: 'There are messages in the Dead Letter Queue',
      evaluationPeriods: 1,
      threshold: 1,
      metric: this.metricApproximateNumberOfMessagesVisible(),
    });
  }
}
```

```
class DeadLetterQueue extends sqs.Queue {

  constructor(scope, id) {
    super(scope, id);

    // Add the alarm
    this.messagesInQueueAlarm = new cloudwatch.Alarm(this, 'Alarm', {
      alarmDescription: 'There are messages in the Dead Letter Queue',
      evaluationPeriods: 1,
      threshold: 1,
      metric: this.metricApproximateNumberOfMessagesVisible(),
    });
  }
}

module.exports = { DeadLetterQueue }
```

```
class DeadLetterQueue(sqs.Queue):
    def __init__(self, scope: Construct, id: str):
        super().__init__(scope, id)

        self.messages_in_queue_alarm = cloudwatch.Alarm(
            self,
            "Alarm",
            alarm_description="There are messages in the Dead Letter Queue.",
            evaluation_periods=1,
            threshold=1,
            metric=self.metric_approximate_number_of_messages_visible(),
        )
```

```
public class DeadLetterQueue extends Queue {
    private final IAlarm messagesInQueueAlarm;

    public DeadLetterQueue(@NotNull Construct scope, @NotNull String id) {
        super(scope, id);

        this.messagesInQueueAlarm = Alarm.Builder.create(this, "Alarm")
                .alarmDescription("There are messages in the Dead Letter Queue.")
                .evaluationPeriods(1)
                .threshold(1)
                .metric(this.metricApproximateNumberOfMessagesVisible())
                .build();
    }

    public IAlarm getMessagesInQueueAlarm() {
        return messagesInQueueAlarm;
    }
}
```

```
namespace AwsCdkAssertionSamples
{
    public class DeadLetterQueue : Queue
    {
        public IAlarm messagesInQueueAlarm;

        public DeadLetterQueue(Construct scope, string id) : base(scope, id)
        {
            messagesInQueueAlarm = new Alarm(this, "Alarm", new AlarmProps
            {
                AlarmDescription = "There are messages in the Dead Letter Queue.",
                EvaluationPeriods = 1,
                Threshold = 1,
                Metric = this.MetricApproximateNumberOfMessagesVisible()
            });
        }
    }
}
```

Kita bisa mengujinya seperti ini:

**Example**  

```
import { Match, Template } from "aws-cdk-lib/assertions";
import * as cdk from "aws-cdk-lib";
import { DeadLetterQueue } from "../lib/dead-letter-queue";

describe("DeadLetterQueue", () => {
  test("matches the snapshot", () => {
    const stack = new cdk.Stack();
    new DeadLetterQueue(stack, "DeadLetterQueue");

    const template = Template.fromStack(stack);
    expect(template.toJSON()).toMatchSnapshot();
  });
});
```

```
const { Match, Template } = require("aws-cdk-lib/assertions");
const cdk = require("aws-cdk-lib");
const { DeadLetterQueue } = require("../lib/dead-letter-queue");

describe("DeadLetterQueue", () => {
  test("matches the snapshot", () => {
    const stack = new cdk.Stack();
    new DeadLetterQueue(stack, "DeadLetterQueue");

    const template = Template.fromStack(stack);
    expect(template.toJSON()).toMatchSnapshot();
  });
});
```

```
import aws_cdk_lib as cdk
from aws_cdk_lib.assertions import Match, Template

from app.dead_letter_queue import DeadLetterQueue

def snapshot_test():
    stack = cdk.Stack()
    DeadLetterQueue(stack, "DeadLetterQueue")

    template = Template.from_stack(stack)
    assert template.to_json() == snapshot
```

```
package software.amazon.samples.awscdkassertionssamples;

import org.junit.jupiter.api.Test;
import au.com.origin.snapshots.Expect;
import software.amazon.awscdk.assertions.Match;
import software.amazon.awscdk.assertions.Template;
import software.amazon.awscdk.Stack;

import java.util.Collections;
import java.util.Map;

public class DeadLetterQueueTest {
    @Test
    public void snapshotTest() {
        final Stack stack = new Stack();
        new DeadLetterQueue(stack, "DeadLetterQueue");

        final Template template = Template.fromStack(stack);
        expect.toMatchSnapshot(template.toJSON());
    }
}
```

```
using Microsoft.VisualStudio.TestTools.UnitTesting;

using Amazon.CDK;
using Amazon.CDK.Assertions;
using AwsCdkAssertionSamples;

using ObjectDict = System.Collections.Generic.Dictionary<string, object>;
using StringDict = System.Collections.Generic.Dictionary<string, string>;

namespace TestProject1
{
    [TestClass]
    public class StateMachineStackTest

    [TestClass]
    public class DeadLetterQueueTest
    {
    [TestMethod]
        public void SnapshotTest()
        {
            var stack = new Stack();
            new DeadLetterQueue(stack, "DeadLetterQueue");

            var template = Template.FromStack(stack);

            return Verifier.Verify(template.ToJSON());
        }
    }
}
```

## Kiat untuk tes
<a name="testing-tips"></a>

Ingat, tes Anda akan hidup selama kode yang mereka uji, dan mereka akan dibaca dan dimodifikasi sesering mungkin. Oleh karena itu, perlu waktu sejenak untuk mempertimbangkan cara terbaik untuk menulisnya.

Jangan salin dan tempel baris pengaturan atau pernyataan umum. Sebaliknya, refaktorkan logika ini menjadi perlengkapan atau fungsi pembantu. Gunakan nama baik yang mencerminkan apa yang sebenarnya diuji oleh setiap tes.

Jangan mencoba melakukan terlalu banyak dalam satu tes. Lebih disukai, tes harus menguji satu dan hanya satu perilaku. Jika Anda secara tidak sengaja merusak perilaku itu, tepat satu tes akan gagal, dan nama tes akan memberi tahu Anda apa yang gagal. Namun, ini lebih ideal untuk diperjuangkan; terkadang Anda pasti akan (atau tidak sengaja) menulis tes yang menguji lebih dari satu perilaku. Tes snapshot, untuk alasan yang telah kami jelaskan, terutama rentan terhadap masalah ini, jadi gunakan dengan hemat.

# Uji dan bangun aplikasi AWS CDK secara lokal dengan SAM CLI AWS
<a name="testing-locally"></a>

Anda dapat menggunakan AWS SAM CLI untuk menguji dan membangun aplikasi tanpa server secara lokal yang ditentukan menggunakan AWS Cloud Development Kit (CDK).AWS Karena AWS SAM CLI bekerja dalam struktur proyek AWS CDK, Anda masih dapat menggunakan [referensi CDK AWS CLI](cli.md) untuk membuat, memodifikasi, dan menyebarkan aplikasi CDK Anda. AWS 

Untuk detail tentang penggunaan AWS SAM, lihat [Memulai AWS SAM](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-getting-started.html) di Panduan *Pengembang Model Aplikasi AWS Tanpa Server*.

**Topics**
+ [Memulai dengan pengujian lokal](testing-locally-getting-started.md)
+ [Aplikasi AWS CDK pengujian lokal dengan AWS SAM](testing-locally-with-sam-cli.md)
+ [Membangun aplikasi AWS CDK dengan AWS SAM](testing-locally-build-with-sam-cli.md)

# Memulai dengan pengujian lokal
<a name="testing-locally-getting-started"></a>

Topik ini menjelaskan apa yang Anda butuhkan untuk menggunakan AWS SAM CLI dengan aplikasi AWS CDK, dan memberikan instruksi untuk membangun dan menguji aplikasi CDK sederhana secara lokal. AWS 

## Prasyarat
<a name="testing-locally-getting-started-prerequisites"></a>

Untuk menguji secara lokal, Anda harus menginstal AWS SAM CLI. lihat [Instal SAM AWS CLI untuk](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/getting_started.html) petunjuk instalasi.

## Membuat dan menguji aplikasi AWS CDK secara lokal
<a name="testing-locally-getting-started-tutorial"></a>

Untuk menguji aplikasi AWS CDK secara lokal menggunakan SAM AWS CLI, Anda harus memiliki aplikasi AWS CDK yang berisi fungsi Lambda. Gunakan langkah-langkah berikut untuk membuat aplikasi AWS CDK dasar dengan fungsi Lambda. Untuk informasi selengkapnya, lihat [Membuat aplikasi tanpa server menggunakan AWS CDK di Panduan Pengembang AWS](https://docs.aws.amazon.com/cdk/latest/guide/serverless_example.html) *Cloud Development Kit (AWS CDK*).<a name="testing-locally-getting-started-tutorial-init"></a>

 **Langkah 1: Buat aplikasi AWS CDK**   
Untuk tutorial ini, inisialisasi aplikasi AWS CDK yang menggunakan. TypeScript  
Perintah untuk menjalankan:  

```
$ mkdir cdk-sam-example
$ cd cdk-sam-example
$ cdk init app --language typescript
```<a name="testing-locally-getting-started-tutorial-lambda"></a>

 **Langkah 2: Tambahkan fungsi Lambda ke aplikasi Anda**   
Ganti kode `lib/cdk-sam-example-stack.ts` dengan yang berikut ini:  

```
import { Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as lambda from 'aws-cdk-lib/aws-lambda';

export class CdkSamExampleStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    new lambda.Function(this, 'MyFunction', {
      runtime: lambda.Runtime.PYTHON_3_12,
      handler: 'app.lambda_handler',
      code: lambda.Code.fromAsset('./my_function'),
    });
  }
}
```<a name="testing-locally-getting-started-tutorial-code"></a>

 **Langkah 3: Tambahkan kode fungsi Lambda Anda**   
Membuat sebuah direktori bernama `my_function`. Di direktori itu, buat file bernama`app.py`.  
Perintah untuk menjalankan:  

**Example**  

```
$ mkdir my_function
$ cd my_function
$ touch app.py
```

```
$ mkdir my_function
$ cd my_function
$ type nul > app.py
```

```
$ mkdir my_function
$ cd my_function
$ New-Item -Path "app.py”
```
Tambahkan kode berikut ke `app.py`:

```
def lambda_handler(event, context):
    return "Hello from SAM and the CDK!"
```<a name="testing-locally-getting-started-tutorial-function"></a>

 **Langkah 4: Uji fungsi Lambda Anda**   
Anda dapat menggunakan AWS SAM CLI untuk memanggil fungsi Lambda secara lokal yang Anda tentukan dalam aplikasi CDK. AWS Untuk melakukan ini, Anda memerlukan pengenal konstruksi fungsi dan jalur ke template yang disintesis AWS CloudFormation .  
Jalankan perintah berikut untuk kembali ke `lib` direktori:  

```
$  cd ..
```
 **Perintah untuk menjalankan:**   

```
$  cdk synth --no-staging
```

```
$  sam local invoke MyFunction --no-event -t ./cdk.out/CdkSamExampleStack.template.json
```
 **Contoh keluaran:**   

```
Invoking app.lambda_handler (python3.9)

START RequestId: 5434c093-7182-4012-9b06-635011cac4f2 Version: $LATEST
"Hello from SAM and the CDK!"
END RequestId: 5434c093-7182-4012-9b06-635011cac4f2
REPORT RequestId: 5434c093-7182-4012-9b06-635011cac4f2	Init Duration: 0.32 ms	Duration: 177.47 ms	Billed Duration: 178 ms	Memory Size: 128 MB	Max Memory Used: 128 MB
```

# Aplikasi AWS CDK pengujian lokal dengan AWS SAM
<a name="testing-locally-with-sam-cli"></a>

Anda dapat menggunakan AWS SAM CLI untuk menguji aplikasi AWS CDK Anda secara lokal dengan menjalankan perintah berikut dari direktori root proyek aplikasi CDK Anda: AWS 
+  ` [sam local invoke](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-local-invoke.html) ` 
+  ` [sam local start-api](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-local-start-api.html) ` 
+  ` [sam local start-lambda](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-local-start-lambda.html) ` 

Sebelum Anda menjalankan salah satu `sam local` perintah dengan aplikasi AWS CDK, Anda harus menjalankannya`cdk synth`.

Saat menjalankan, `sam local invoke` Anda memerlukan pengenal konstruksi fungsi yang ingin Anda panggil, dan jalur ke templat yang disintesis. AWS CloudFormation Jika aplikasi Anda menggunakan tumpukan bersarang, untuk menyelesaikan konflik penamaan, Anda juga memerlukan nama tumpukan tempat fungsi didefinisikan.

 **Penggunaan**   

```
# Invoke the function FUNCTION_IDENTIFIER declared in the stack STACK_NAME
$  sam local invoke <OPTIONS> <STACK_NAME/FUNCTION_IDENTIFIER>

# Start all APIs declared in the AWS CDK application
$  sam local start-api -t <./cdk.out/CdkSamExampleStack.template.json> <OPTIONS>

# Start a local endpoint that emulates AWS Lambda
$  sam local start-lambda -t <./cdk.out/CdkSamExampleStack.template.json> <OPTIONS>
```

## Contoh
<a name="testing-cdk-applications-examples"></a>

Pertimbangkan tumpukan dan fungsi yang dideklarasikan dengan sampel berikut:

```
app = new HelloCdkStack(app, "HelloCdkStack",
   ...
)
class HelloCdkStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    ...
    new lambda.Function(this, 'MyFunction', {
        ...
    });

    new HelloCdkNestedStack(this, 'HelloNestedStack' ,{
        ...
    });
  }
}

class HelloCdkNestedStack extends cdk.NestedStack {
  constructor(scope: Construct, id: string, props?: cdk.NestedStackProps) {
    ...
    new lambda.Function(this, 'MyFunction', {
        ...
    });
    new lambda.Function(this, 'MyNestedFunction', {
        ...
    });
  }
}
```

Perintah berikut secara lokal memanggil fungsi Lambda yang didefinisikan dalam contoh yang disajikan di atas:

```
# Invoke MyFunction from the HelloCdkStack
$ sam local invoke -t <./cdk.out/HelloCdkStack.template.json> <MyFunction>
```

```
# Invoke MyNestedFunction from the HelloCdkNestedStack
$ sam local invoke -t <./cdk.out/HelloCdkStack.template.json> <MyNestedFunction>
```

```
# Invoke MyFunction from the HelloCdkNestedStack
$ sam local invoke -t <./cdk.out/HelloCdkStack.template.json> <HelloNestedStack/MyFunction>
```

# Membangun aplikasi AWS CDK dengan AWS SAM
<a name="testing-locally-build-with-sam-cli"></a>

 AWS SAM CLI menyediakan dukungan untuk membangun fungsi dan lapisan Lambda yang ditentukan dalam aplikasi CDK Anda AWS . ` [sam build](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-build.html) `

Untuk fungsi Lambda yang menggunakan artefak zip, jalankan `cdk synth` sebelum Anda menjalankan perintah. `sam local` `sam build`tidak diperlukan.

Jika aplikasi AWS CDK Anda menggunakan fungsi dengan tipe gambar, jalankan `cdk synth` lalu jalankan `sam build` sebelum Anda menjalankan `sam local` perintah. Saat Anda menjalankan`sam build`, AWS SAM tidak membangun fungsi atau lapisan Lambda yang menggunakan konstruksi khusus runtime, misalnya,. ` [NodejsFunction](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda_nodejs.NodejsFunction.html) ` `sam build`tidak mendukung [aset yang dibundel](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.BundlingOptions.html).

## Contoh
<a name="testing-locally-build-with-sam-cli-examples"></a>

Menjalankan perintah berikut dari direktori root proyek AWS CDK membangun aplikasi.

```
$ sam build -t <./cdk.out/CdkSamExampleStack.template.json>
```