SaveMyCert
Log in
5 of 5 free questions left today·for unlimited practice
Deployment

Automate Deployment Testing: Test Events, Approved Versions, and IaC

13 min readDVA-C02 · DeploymentUpdated

Automated deployment testing means proving every deployment works by wiring tests into the release process itself: realistic JSON test events fired at your functions, integration environments pinned to approved code versions, and infrastructure defined as code so environments are reproducible. On the DVA-C02 exam this is Domain 3, Task 3.3, and it sits between two neighbors you must not confuse: manual testing during development (Task 3.2) and the CI/CD pipeline services that orchestrate releases (Task 3.4). Here the question is what you test with and where — the shape of a Lambda test event, how an API change reaches a test stage, why an alias or an immutable image tag guarantees you are testing the exact build you approved, and how SAM and CloudFormation templates create those environments safely with change sets and predictable rollback behavior.

What you’ll learn
  • Build realistic JSON test events for Lambda functions invoked by API Gateway, SQS, and S3, and generate them with sam local generate-event
  • Deploy API Gateway resources to dev, test, and prod stages from automation
  • Pin integration-test environments to approved code using Lambda versions and aliases, immutable container image tags, and Amplify branches
  • Compare AWS SAM, CloudFormation, and the CDK, and read template Parameters, Resources, and Outputs at exam depth
  • Use change sets to preview stack updates and predict CloudFormation rollback behavior on failure
  • Choose the right environment boundary per service, from API Gateway stages up to separate AWS accounts

Test events: JSON payloads that stand in for real triggers

AWS Lambda never sees an HTTP request, a queue, or an uploaded file directly. Every invocation delivers a JSON event document, and its shape depends entirely on which service invoked the function. Automated deployment testing therefore starts with a library of realistic event payloads that your automation can fire at freshly deployed code.

Three event shapes dominate the exam:

  • API Gateway proxy events wrap the whole HTTP request into one object: httpMethod, path, headers, queryStringParameters, pathParameters, a requestContext block, and a body that is always a string (base64-encoded when binary, flagged by isBase64Encoded). Your function must return a matching proxy response object with a statusCode and a string body.
  • SQS events deliver a Records array — one entry per message in the batch — each with a messageId, a receiptHandle, and the message body. A test event containing two or three records also exercises your batch-handling logic, which a single-record payload never would.
  • S3 notification events also use a Records array; each record identifies the eventName (for example ObjectCreated:Put) and nests the bucket name and object key under s3. Object keys arrive URL-encoded, a detail that regularly breaks naive handlers and shows up in exam distractors.

Because these documents are just JSON, they belong in version control next to the code they test. A deployment stage can then invoke the function with each stored payload and assert on the response — the same events, every deployment, with no manual clicking in a console.

Generating and sharing test events

Writing event payloads by hand is error prone, so AWS SAM generates them for you. sam local generate-event prints a realistic sample event for dozens of service integrations:

sam local generate-event s3 put --bucket uploads --key report.pdf
sam local generate-event apigateway aws-proxy --method GET --path orders
sam local generate-event sqs receive-message

Redirect the output to files, commit them, and reuse the same payloads in local runs, build-stage test phases, and post-deployment smoke tests. Generating the event is Task 3.3 territory; feeding it to sam local invoke for interactive debugging belongs to the development loop in Task 3.2 — the exam distinguishes between the two.

The Lambda console adds shareable test events. A private test event exists only for the user who created it; marking it shareable stores the payload in the account's Amazon EventBridge schema registry, so every developer and pipeline role with access tests the function with exactly the same document instead of hand-copied variants that drift apart.

Generating tests with Amazon Q Developer

Version 2.1 of the exam guide added Amazon Q Developer as a way to generate automated tests. From your IDE, Q Developer can read a function and propose unit tests — happy paths, edge cases, and mocks for AWS SDK calls — which then run in the same automated stages as any hand-written test. Treat the output as a draft: you are expected to review generated tests for correctness and meaningful assertions before committing them, not to trust them blindly.

Deploying API resources to different environments

Deploying API resources starts from one fact about Amazon API Gateway: editing your API changes nothing for callers. Resources, methods, and integrations you modify live in a working definition; they take effect only when you create a deployment — an immutable snapshot of the API — and attach it to a stage such as dev, test, or prod. Each stage has its own invoke URL and its own stage-level configuration: throttling limits, caching, logging, and stage variables.

That split is what makes automated promotion possible. A pipeline step runs aws apigateway create-deployment --rest-api-id abc123 --stage-name test, the integration suite exercises the test URL, and a later step points the prod stage at the deployment that passed. Forgetting to create a new deployment is the classic reason an API change "does not show up" — an exam favorite.

With AWS SAM, the same flow is declarative: an AWS::Serverless::Api resource with a StageName property, deployed once per environment with different parameter values, or a single template deployed to separate stacks for test and production. Either way the automation, not a human in the console, decides which API snapshot each environment serves — and because every deployment is a snapshot, the API version your tests exercised is exactly the one production will run.

Environments pinned to approved versions

Integration tests only mean something when the environment under test contains exactly the build you approved — not whatever was pushed last. Each service has a pinning mechanism:

  • Lambda versions and aliases. Publishing a version creates an immutable snapshot of code plus configuration; $LATEST is the only mutable target. An alias is a named pointer (test, staging, live) to one version. Point your integration environment at an alias ARN and it always invokes an approved snapshot, even while developers keep changing $LATEST.
  • Container image tags. A mutable tag like latest can be overwritten in Amazon ECR at any time, silently changing what your test environment runs. Use unique version tags (or image digests) and turn on ECR tag immutability so an approved tag can never point at different bytes later.
  • AWS Amplify branches. Amplify treats every connected Git branch as its own environment with its own URL, backend, and environment variables — branch main is production, branch develop is your integration environment.
  • AWS Copilot environments. Copilot models named environments such as test and prod for containerized apps. It was dropped from the in-scope service list in guide v2.1 but survives as an example in this skill, so recognize the term.

A concrete flow: after review, automation publishes Lambda version 7 and moves the staging alias to it. The integration stage fires the stored API Gateway and SQS test events at the staging alias and asserts on the responses. Only when the suite passes does the live alias move to version 7. Nothing ever tested $LATEST, so nothing unapproved could leak into the result.

SAM, CloudFormation, and CDK: choosing the template layer

Environments that are typed in by hand drift; environments created from templates are reproducible, which is why infrastructure as code is the backbone of automated deployment testing. The exam expects you to place three tools relative to each other:

ToolYou writeHow it deploysBest fit
AWS CloudFormationDeclarative JSON or YAML templatesStacks, via direct updates or change setsAny AWS infrastructure; the engine everything else compiles to
AWS SAMCloudFormation plus the AWS::Serverless-2016-10-31 transformsam buildsam packagesam deployServerless apps: functions, APIs, and tables in a few lines
AWS CDKReal code (TypeScript, Python, Java, and more)cdk synth emits CloudFormation; cdk deploy applies itTeams that want loops, types, and reusable constructs

SAM is a superset: the Transform line tells CloudFormation to expand shorthand resources like AWS::Serverless::Function and AWS::Serverless::Api into full CloudFormation resources at deploy time. sam build resolves dependencies, sam package uploads artifacts to Amazon S3 and rewrites local paths into S3 URIs, and sam deploy creates and executes a change set. The CDK follows the same physics from the other direction — code in, CloudFormation out.

The consequence the exam loves: because all three converge on the CloudFormation engine, they share one deployment model — the same stacks, the same change sets, the same rollback behavior. Choosing SAM or the CDK changes how you author templates, not how updates apply.

Template anatomy at exam depth

You do not need the full template specification, but you must be able to read a template's three working parts:

  • Parameters are inputs supplied at deploy time — instance sizes, stage names, memory settings — with types, defaults, and AllowedValues. Parameters are how one template serves dev, test, and prod without editing: same file, different values per environment.
  • Resources is the only required section. Each resource has a logical ID, a Type, and Properties; templates wire resources together with Ref and Fn::GetAtt, which also lets CloudFormation order creation correctly.
  • Outputs return values after deployment — an API URL, a table name — for humans, scripts, or other stacks to consume.

Outputs become cross-stack when you add an Export name. Another stack in the same account and Region consumes the value with Fn::ImportValue — the standard way a shared network stack hands a VPC ID to an application stack. Two rules ride along: export names must be unique within the account and Region, and CloudFormation refuses to delete or change an exported value while any stack still imports it. That protection is the point for testing: your integration-test stack cannot have its foundations deleted out from under it in the middle of a run, because the dependency is declared where CloudFormation can enforce it.

Change sets and rollback behavior

Change sets answer the question every reviewer asks before an automated update: what exactly will this deployment do? Creating a change set compares your new template and parameters against the running stack and lists every planned action — which resources will be added, modified, or removed, and critically whether a modification requires replacement, meaning CloudFormation will create a new resource and delete the old one (new physical ID, and possible data loss for stateful resources). Nothing changes until the change set is executed, so automation commonly splits deployment into a create-change-set step, an approval, and an execute step. When a question says "preview changes before applying them," the answer is a change set.

Rollback behavior differs by operation:

  • Stack creation fails — CloudFormation rolls back by deleting everything it created, leaving the stack in ROLLBACK_COMPLETE; you must delete the stack before retrying the create.
  • Stack update fails — CloudFormation automatically rolls the stack back to its previous working template and state, ending in UPDATE_ROLLBACK_COMPLETE. Your last good environment comes back on its own.

For automated testing this is a safety net, not a substitute for tests: a rolled-back stack is healthy, but the deployment still failed, and the stage that attempted it should surface that failure loudly rather than quietly continuing to run tests against the old environment as if the release had happened.

Dev, test, and prod inside individual services

Managing environments in individual services means knowing which isolation lever each service offers, because the exam asks it service by service:

  • API Gateway separates environments with stages — one API, with distinct dev, test, and prod snapshots, each having its own URL, settings, and stage variables.
  • Lambda uses aliases over published versions — the alias name is the environment, the version it points to is the pinned build.
  • AWS Amplify maps Git branches to environments, each branch deploying independently with its own configuration.

All three share one AWS account, which keeps operations simple but shares quotas, IAM boundaries, and blast radius. The strongest isolation is a separate AWS account per environment: production quotas cannot be exhausted by a runaway load test, an over-broad test role cannot touch production data, and cost is cleanly attributable. At the Associate level you need the concept and the trade-off, not the multi-account tooling itself.

Whichever lever you use, keep the environment difference in configuration — template parameters, stage variables, environment variables — never in code. A build that must be recompiled per environment cannot be the "approved version" you pinned earlier in this lesson, because each environment would be running different bytes, and your integration results would prove nothing about production.

Tip. Expect scenario questions that name a service and ask for its environment lever: stages for API Gateway, aliases over versions for Lambda, branches for Amplify. "Preview changes before applying" points to CloudFormation change sets, "test against an approved version" points to Lambda aliases or immutable image tags, and an API change that "doesn't show up" means nobody created a new deployment to the stage. Also know that SAM's transform expands to plain CloudFormation and that a failed stack update rolls back automatically to the last working state.

Key takeaways
  • Lambda receives a service-specific JSON event — API Gateway wraps the whole HTTP request, while SQS and S3 deliver a Records array.
  • sam local generate-event prints realistic sample payloads you can commit to the repo and replay in automated tests.
  • Shareable test events are stored in the EventBridge schema registry so the whole team tests with identical payloads.
  • A Lambda version is an immutable snapshot; an alias is a movable pointer — test against aliases, never $LATEST.
  • Mutable image tags like latest can change underneath you; immutable tags or digests pin test environments to approved builds.
  • SAM is a CloudFormation superset (via its Transform) and the CDK synthesizes to CloudFormation — one engine, one rollback model.
  • A change set previews an update before execution; a failed update automatically rolls the stack back to its last working state.
  • API Gateway changes go live only when you create a new deployment and attach it to a stage.

Frequently asked questions

What is the difference between a Lambda version and an alias?

A published Lambda version is an immutable snapshot of the function's code and configuration; once published it never changes. An alias is a named, movable pointer to one version, such as staging or live. Environments and event sources should invoke the alias ARN, so promoting a release is just repointing the alias — no caller configuration changes.

What does sam local generate-event do?

It prints a realistic sample JSON event for a chosen service integration — for example an S3 put notification or an API Gateway proxy request — so you can save the payload to a file, commit it, and replay it in automated tests or Lambda invocations instead of hand-writing event documents from memory.

How do I preview what a CloudFormation update will change before running it?

Create a change set. It compares the new template and parameters against the running stack and lists every add, modify, and remove — including whether a change forces resource replacement — without touching anything. The update happens only when you execute the change set, which is why automated release processes put an approval between the create and execute steps.

What happens when a CloudFormation stack update fails?

CloudFormation automatically rolls the stack back to its previous working state using the last successful template, ending in UPDATE_ROLLBACK_COMPLETE. A failed initial creation behaves differently: the stack rolls back to ROLLBACK_COMPLETE and must be deleted before you can try creating it again.

Why do container image tags matter for integration testing?

A mutable tag such as latest can be overwritten in Amazon ECR, so the image your test environment pulls can change without any deployment happening. Pinning environments to unique, immutable tags or image digests guarantees the integration tests ran against exactly the build that was approved — the same guarantee a Lambda alias over a published version provides.

Are shareable Lambda test events different from private ones?

Yes. A private console test event is visible only to the user who created it, while a shareable test event is stored in the account's Amazon EventBridge schema registry, so other users and roles with access can invoke the function with the identical payload. Teams use them to keep everyone testing against the same documents.

Test yourself on this topic
Practice questions with full explanations.
Practice now

Sign up free to mark lessons complete, bookmark topics and track your exam readiness.