The CDK Assertions library lets you test your CloudFormation templates generated by AWS CDK code before deploying them to AWS, catching errors early and saving you from costly mistakes.

Here’s a CDK App that defines a simple S3 bucket:

from aws_cdk import (
    Stack,
    aws_s3 as s3,
    App
)
from constructs import Construct

class MyS3Stack(Stack):
    def __init__(self, scope: Construct, id: str) -> None:
        super().__init__(scope, id)

        s3.Bucket(self, "MyBucket",
            bucket_name="my-unique-test-bucket-12345",
            versioned=True,
            removal_policy=s3.RemovalPolicy.DESTROY # Important for testing!
        )

app = App()
MyS3Stack(app, "MyS3Stack")

Now, let’s write a unit test for this stack using assertions:

from aws_cdk import (
    assertions,
    Stack
)
from my_s3_stack import MyS3Stack # Assuming your stack is in my_s3_stack.py

def test_s3_bucket_creation():
    app = App()
    stack = MyS3Stack(app, "MyTestStack")
    template = assertions.Template.from_stack(stack)

    # Assert that exactly one S3 bucket resource is created
    template.resource_count_is("AWS::S3::Bucket", 1)

    # Assert specific properties of the S3 bucket
    template.has_resource_properties("AWS::S3::Bucket", {
        "BucketName": "my-unique-test-bucket-12345",
        "VersioningConfiguration": {
            "Status": "Enabled"
        }
    })

    # Assert that a specific tag is present (if you had added tags)
    # template.has_resource("AWS::S3::Bucket", {
    #     "Tags": assertions.Match.array_with([
    #         assertions.Match.object_like({"Key": "Environment", "Value": "Test"})
    #     ])
    # })

    # Assert that a specific resource *is not* present
    # template.resource_count_is("AWS::IAM::Role", 0)

This test checks two things:

  1. That the template generated by your CDK code contains exactly one resource of type AWS::S3::Bucket.
  2. That this AWS::S3::Bucket resource has specific properties defined: BucketName and VersioningConfiguration.Status set to "Enabled".

The assertions library works by synthesizing your CDK stack into a CloudFormation template. It then provides methods to inspect this template as a JSON object, allowing you to verify the structure and properties of the AWS resources you intend to create.

The power comes from being able to check virtually any CloudFormation property. You can verify IAM policies, security group rules, Lambda function configurations, API Gateway routes, and much more, all without ever deploying to an AWS account. This drastically reduces the feedback loop for infrastructure changes.

To run this test, you’d typically use a test runner like pytest. Ensure you have aws-cdk-lib and pytest installed. Your test file (e.g., test_my_s3_stack.py) would contain the code above, and you’d run pytest from your terminal in the project’s root directory.

The assertions.Template object is your gateway to understanding the generated CloudFormation. Methods like resource_count_is, has_resource_properties, has_resource, and find_resources allow for granular inspection. assertions.Match provides powerful pattern matching capabilities for more complex assertions, like checking for specific elements within arrays or verifying object structures.

When defining resources in your CDK code, pay attention to properties that are critical for security or functionality. These are prime candidates for assertions. For example, if you’re creating a Lambda function, you’ll want to assert its runtime, handler, memory size, and importantly, its execution role’s permissions. For a VPC, you might assert the number of public/private subnets, NAT gateways, or route table configurations.

A common pattern is to test for the absence of unintended resources or configurations. For instance, ensuring a resource doesn’t have overly permissive access control lists (ACLs) or that sensitive data is encrypted at rest. The resource_count_is method can be used to assert that zero instances of a particular resource type exist, and has_resource_properties can check that certain security-related properties are not set to insecure defaults.

The real magic happens when you start combining these assertions. You can verify that a specific IAM policy document is attached to a Lambda function’s role, or that an S3 bucket’s public access block is configured correctly. This allows you to build a robust safety net around your infrastructure code, ensuring that what you intend to deploy is actually what gets synthesized into CloudFormation.

The next step after mastering basic assertions is to explore assertions.Match for more sophisticated validation.

Want structured learning?

Take the full Cdk course →