Blog

How to Speedup Your CDK Test Feedback

08 May, 2024
Xebia Background Header Wave

When you deploy lambda functions using CDK and a test-driven approach, you might have noticed that the test feedback takes longer each time you add a new function. That’s because each function will be bundled with its own set of dependencies. These dependencies need to be downloaded before CDK can bundle them into a single package.

CDK Synth

Before you can deploy your infrastructure you need to synthesize your code. This will transform your code into a CloudFormation template plus some assets. When you have a lambda function the content of this function will be bundled into one of these assets.

This all makes sense when you deploy your code. You need to ship the actual lambda code to AWS in the correct format with the correct dependencies. Otherwise, your solution will not work.

But the synth step is also used when you test your infrastructure code. The process is like the deploy step. Instead of deploying your templates, you will inspect the outcome. For example, you are expecting a Lambda function. This function will use a certain runtime. And, for production environments, you want to confirm that the backup tags are applied.

Skip the bundling when you run the tests!

It might be an obvious answer. Skip the bundling when you run the tests! Assume we use the following code to create a Lambda function:

const sampleFunction = new lambda.Function(this, 'SampleFunction', {
  code: lambda.Code.fromAsset('./sample_function/', {
    bundling: {
      command: ['bash', '-c', 'pip install --target /asset-output -r ./requirements.txt && cp -au . /asset-output'],
      image: lambda.Runtime.PYTHON_3_12.bundlingImage,
    },
  }),
  runtime: lambda.Runtime.PYTHON_3_12,
  handler: 'index.handler',
  timeout: cdk.Duration.seconds(60),
  memorySize: 1024,
 });

You can see that we are loading the code from a folder called sample_function. Then we pass the options on how CDK needs to bundle the function:

  • First, the dependencies will be downloaded and installed.
  • Next, the content from the sample_function is copied.
  • The content of the asset_output folder will be the bundled function.

Now, these steps will become part of the test. You can skip the bundling by defining the test as followed:

import * as cdk from 'aws-cdk-lib';
import { Template } from 'aws-cdk-lib/assertions';
import { AppStack } from './AppStack';


test('Sample unit test on how to skip bundling', () => {
 // Setup the application
 const app = new cdk.App({
   context: {
     'aws:cdk:bundling-stacks': [],
   },
 });


 // Setup the CDK stack
 const stack = new AppStack(app, 'MyTestStack', {
   backups: true, // For production we enable backups
 });


 // Synth the code
 const template = Template.fromStack(stack);


 // Confirm that the Lambda function uses python 3.12 runtime
 template.hasResourceProperties('AWS::Lambda::Function', {
   Runtime: 'python3.12',
 });


 // Confirm that the DynamoDB table has the Backup tag
 template.hasResourceProperties('AWS::DynamoDB::Table', {
   Tags: [
     {
       Key: 'Backup',
       Value: 'YES',
     },
   ],
 });
});

A few things are happening in this example:

  • When the app object is being created, some specific context is supplied. This context will overwrite the aws:cdk:bundling-stacks option. This means that the bundling options are overwritten with nothing.
  • Then the stack object is created and a template is synthesized.
  • We will confirm that we have a lambda function with the Python 3.12 runtime.
  • We will also confirm that the DynamoDB table has the Backup tag with the value YES.

Because we skipped the bundling the test will execute immediately. Giving you instant feedback on the code that you have been writing. You can now run the test after each change. This enables you to create a nice development cycle:

  1. Adding a test implementation.
  2. Adding the business logic.
  3. Running the tests to confirm the implementation.
  4. Repeat

Why is it ok to skip the bundling?

When you write tests you should confirm your business logic. The bundling logic has already been tested by the team that is maintaining CDK. So you don’t need to test it and it’s safe to skip the bundling.

You could argue that the options in the bundling need validation too. And yes, that is now skipped. Yet the bundling of these functions is usually always the same for each runtime. And when you deploy you will catch any bundling mistakes anyway. Next to that, you have tests for your lambda code as well. These tests are not executed against the bundled version of your code. These are executed against the source version of your code. So there is no need to bundle them from a testing perspective.

Conclusion

When it takes too long to run tests, you will run them less. This has a negative impact on your quality and efficiency. You can solve this by excluding heavy operations. Operations like downloading dependencies and bundling your lambda functions. This also helps with focussing on the tests that matter. The tests that actually confirm your business value.

Follow me if you want to learn more about improving your efficiency and code quality.

Photo by Pixabay

Joris Conijn
Joris has been working with the AWS cloud since 2009 and focussing on building event driven architectures. While working with the cloud from (almost) the start he has seen most of the services being launched. Joris strongly believes in automation and infrastructure as code and is open to learn new things and experiment with them, because that is the way to learn and grow. In his spare time he enjoys running and runs a small micro brewery from his home.
Questions?

Get in touch with us to learn more about the subject and related solutions

Explore related posts