July 25, 2023     15 min read

Let's Try - AWS Greengrass Testing Framework

Let's Try - AWS Greengrass Testing Framework

Get the code for this post!

t04glovern/aws-greengrass-json-gzip

Updated 19th August 2023: Upgraded to unpublished Open Test Framework v1.2.0 - It is recommended that you replace "otf_version" : "1.1.0" in the gdk-config.json within this post with 1.2.0, along with ensuring otf.version in the pom.xml is set to <otf.version>1.2.0-SNAPSHOT</otf.version>

With the recent release of Greengrass Development Kit (GDK CLI) v1.3.0 comes a new feature that I've been looking forward to seeing for a while now - end to end testing of Greengrass components with the Open Test Framework (OFT).

This suite of building blocks allows for true integration testing of Greengrass components by deploying real Greengrass resources to AWS as part of testing.

While this framework isn't new, the ease of use and integration with the GDK CLI is. And I'm hoping that the barrier of entry to testing Greengrass components is now low enough so that I'll enjoy this exercise!

Existing Project

For this post I'll be using an existing Greengrass component that I've been working on for a while now - t04glovern/aws-greengrass-json-gzip. This component is a simple Greengrass component that takes in a JSON payload over StreamManager, compresses it using GZIP and then outputs the compressed payload.

I wanted to use this component as it's simple but also has a few different moving parts that I can test.

Getting Started with OTF and the GDK CLI

Starting off, I install version 1.3.0 of the GDK CLI

pip3 install git+https://github.com/aws-greengrass/aws-greengrass-gdk-cli.git@v1.3.0

The documentation for this version of the CLI is squirreled away in the Greengrass developer guide currently - I hope to eventually see it surfaced better in the GDK CLI repository.

$ gdk
# usage: gdk [-h] [-d] [-v] {component,test-e2e} ...

# Greengrass development kit - CLI for developing AWS IoT GreengrassV2 components.

# positional arguments:
#   {component,test-e2e}
#     component           Initialize, build and publish GreengrassV2 components using this command.
#     test-e2e            Test component features using open-source test framework

# options:
#   -h, --help            show this help message and exit
#   -d, --debug           Increase command output to debug level
#   -v, --version         show program's version number and exit

Referring to the docs we learn that running the following will initialise an existing GDK CLI project with a testing module that uses Open Test Framework (OTF).

$ gdk test-e2e init
# [2023-07-25 12:52:29] INFO - Using the OTF version provided in the GDK test config 1.1.0
# [2023-07-25 12:52:30] INFO - Downloading the E2E testing template from GitHub into gg-e2e-tests directory...

This command pulls down a testing template from https://github.com/aws-greengrass/aws-greengrass-component-templates/tree/main/templates/java/TestTemplateForCLI and lands it into a new folder called gg-e2e-tests.

By default, the testing template that was setup will work without any modification to your existing gdk-config.json, however taking a look at the GDK CLI configuration file documentation, I found that you are able to customise your configuration file to be explicit.

Adding the test-e2e block to my gdk-config.json file, I can now specify the version of the OTF that I want to use - in this case v1.1.0.

{
  "component": {
    "com.devopstar.json.gzip": {
      ...
    }
  },
  "test-e2e":{
    "build":{
      "build_system": "maven"
    },
    "otf_version" : "1.1.0",
    "otf_options" : { 
        "tags": "Sample"
     }
  },
  "gdk_version": "1.3.0"
}

With this configuration in place, we can run the following commands to:

  1. Build the component
  2. Build the test suite

NOTE: You will need to have Maven installed to build the test suite.

$ gdk component build
# [2023-07-25 12:59:33] INFO - Building the component 'com.devopstar.json.gzip' with the given project configuration.
# [2023-07-25 12:59:33] INFO - Using 'zip' build system to build the component.
# [2023-07-25 12:59:33] WARNING - This component is identified as using 'zip' build system. If this is incorrect, please exit and specify custom build command in the 'gdk-config.json'.
# [2023-07-25 12:59:33] INFO - Copying over the build artifacts to the greengrass component artifacts build folder.
# [2023-07-25 12:59:33] INFO - Updating artifact URIs in the recipe.

$ gdk test-e2e build
# [2023-07-25 12:59:57] INFO - Updating feature file: file:///workspaces/aws-greengrass-json-gzip/greengrass-build/gg-e2e-tests/target/classes/greengrass/features/component.feature
# [2023-07-25 12:59:57] INFO - Updating feature file: file:///workspaces/aws-greengrass-json-gzip/greengrass-build/gg-e2e-tests/src/main/resources/greengrass/features/component.feature
# [2023-07-25 12:59:57] INFO - Creating the E2E testing recipe file: /workspaces/aws-greengrass-json-gzip/greengrass-build/recipes/e2e_test_recipe.yaml
# [2023-07-25 12:59:57] INFO - Building the E2E testing module
# [2023-07-25 12:59:57] INFO - Running the build command 'mvn package'
# [INFO] Scanning for projects...
# [INFO] 
# [INFO] ------------------< com.aws.greengrass:uat-features >-------------------
# [INFO] Building OTF 1.0.0
# [INFO]   from pom.xml
# [INFO] --------------------------------[ jar ]---------------------------------
# [INFO]
# ...

We should now be in a position to run our tests! You will need AWS Credentials available in your environment for this to work - The credentials will need to have pretty broad permissions that as of right now I cannot find a full list of.

For some reason, I found that I also needed to set the default region in my environment variables for the tests to run without error also. I tried using the otf_options.aws-region however this didn't seem to work.

export AWS_REGION=ap-southeast-2

Running the following command will run the tests and output the results to the console.

$ gdk test-e2e run
# [2023-07-25 13:09:53] INFO - Running test jar with command java -jar /workspaces/aws-greengrass-json-gzip/greengrass-build/gg-e2e-tests/target/uat-features-1.0.0.jar --tags=Sample --ggc-archive=/workspaces/aws-greengrass-json-gzip/greengrass-build/greengrass-nucleus-latest.zip
# WARNING: sun.reflect.Reflection.getCallerClass is not supported. This will impact performance.
# 13:09:55.902 [] [] [] [INFO] com.aws.greengrass.testing.modules.GreengrassContextModule - Extracting /workspaces/aws-greengrass-json-gzip/greengrass-build/greengrass-nucleus-latest.zip into /tmp/gg-testing-10194968955318536500/greengrass
# 13:09:56.601 [otf-1.1.0-SNAPSHOT] [] [] [INFO] com.aws.greengrass.testing.features.LoggerSteps - OTF Version is otf-1.1.0-SNAPSHOT
# 13:09:56.602 [otf-1.1.0-SNAPSHOT] [component] [gg-f72b345ad39e69dbe12d] [INFO] com.aws.greengrass.testing.features.LoggerSteps - Attaching thread context to scenario: 'As a developer, I can create a component and deploy it on my device'
# 13:09:58.690 [otf-1.1.0-SNAPSHOT] [component] [gg-f72b345ad39e69dbe12d] [INFO] com.aws.greengrass.testing.resources.AbstractAWSResourceLifecycle - Created IotPolicy in IotLifecycle
...
# 13:10:01.686 [otf-1.1.0-SNAPSHOT] [component] [gg-f72b345ad39e69dbe12d] [INFO] greengrass/features/component.feature - Finished step: 'my device is registered as a Thing' with status PASSED
# 13:10:03.220 [otf-1.1.0-SNAPSHOT] [component] [gg-f72b345ad39e69dbe12d] [INFO] com.aws.greengrass.testing.DefaultGreengrass - Starting Greengrass on pid 27163
# 13:10:03.220 [otf-1.1.0-SNAPSHOT] [component] [gg-f72b345ad39e69dbe12d] [INFO] greengrass/features/component.feature - Finished step: 'my device is running Greengrass' with status PASSED
# 13:10:05.352 [otf-1.1.0-SNAPSHOT] [component] [gg-f72b345ad39e69dbe12d] [INFO] com.aws.greengrass.testing.resources.AbstractAWSResourceLifecycle - Created S3Bucket in S3Lifecycle
# 13:10:06.124 [otf-1.1.0-SNAPSHOT] [component] [gg-f72b345ad39e69dbe12d] [INFO] com.aws.greengrass.testing.resources.AbstractAWSResourceLifecycle - Created S3Object in S3Lifecycle
# 13:10:06.124 [otf-1.1.0-SNAPSHOT] [component] [gg-f72b345ad39e69dbe12d] [INFO] com.aws.greengrass.testing.component.RecipeComponentPreparationService - Uploaded /workspaces/aws-greengrass-json-gzip/greengrass-build/artifacts/com.devopstar.json.gzip/NEXT_PATCH/aws-greengrass-json-gzip.zip to s3://gg-f72b345ad39e69dbe12d-gg-component-store///workspaces/aws-greengrass-json-gzip/greengrass-build/artifacts/com.devopstar.json.gzip/NEXT_PATCH/aws-greengrass-json-gzip.zip
# 13:10:06.943 [otf-1.1.0-SNAPSHOT] [component] [gg-f72b345ad39e69dbe12d] [INFO] com.aws.greengrass.testing.resources.AbstractAWSResourceLifecycle - Created GreengrassComponent in GreengrassV2Lifecycle
# 13:10:06.943 [otf-1.1.0-SNAPSHOT] [component] [gg-f72b345ad39e69dbe12d] [INFO] com.aws.greengrass.testing.component.RecipeComponentPreparationService - Created component com.devopstar.json.gzip:1.0.0-f72b345ad39e69dbe12d from ///workspaces/aws-greengrass-json-gzip/greengrass-build/recipes/e2e_test_recipe.yaml
# 13:10:06.945 [otf-1.1.0-SNAPSHOT] [component] [gg-f72b345ad39e69dbe12d] [INFO] greengrass/features/component.feature - Finished step: 'I create a Greengrass deployment with components' with status PASSED
# 13:10:07.277 [otf-1.1.0-SNAPSHOT] [component] [gg-f72b345ad39e69dbe12d] [INFO] com.aws.greengrass.testing.resources.AbstractAWSResourceLifecycle - Created GreengrassDeployment in GreengrassV2Lifecycle
# 13:10:07.277 [otf-1.1.0-SNAPSHOT] [component] [gg-f72b345ad39e69dbe12d] [INFO] com.aws.greengrass.testing.features.DeploymentSteps - Created Greengrass deployment: 1bbce6f1-3c82-4f43-b659-85bc5a9f6065
# 13:10:07.278 [otf-1.1.0-SNAPSHOT] [component] [gg-f72b345ad39e69dbe12d] [INFO] greengrass/features/component.feature - Finished step: 'I deploy the Greengrass deployment configuration' with status PASSED
# 13:10:20.660 [otf-1.1.0-SNAPSHOT] [component] [gg-f72b345ad39e69dbe12d] [INFO] greengrass/features/component.feature - Finished step: 'the Greengrass deployment is COMPLETED on the device after 180 seconds' with status PASSED
# My custom step was called 
# 13:10:20.663 [otf-1.1.0-SNAPSHOT] [component] [gg-f72b345ad39e69dbe12d] [INFO] greengrass/features/component.feature - Finished step: 'I call my custom step' with status PASSED
# 13:10:21.453 [otf-1.1.0-SNAPSHOT] [component] [gg-f72b345ad39e69dbe12d] [INFO] com.aws.greengrass.testing.DefaultGreengrass - Stopped Greengrass on pid 27163
# 13:10:21.842 [otf-1.1.0-SNAPSHOT] [component] [gg-f72b345ad39e69dbe12d] [INFO] com.aws.greengrass.testing.resources.AbstractAWSResourceLifecycle - Removed GreengrassDeployment in GreengrassV2Lifecycle
...
# 13:10:24.543 [otf-1.1.0-SNAPSHOT] [component] [gg-f72b345ad39e69dbe12d] [INFO] com.aws.greengrass.testing.features.AWSResourcesSteps - Successfully removed externally created resources
# 13:10:24.548 [otf-1.1.0-SNAPSHOT] [component] [gg-f72b345ad39e69dbe12d] [INFO] com.aws.greengrass.testing.features.LoggerSteps - Clearing thread context on scenario: 'As a developer, I can create a component and deploy it on my device'
# 13:10:24.552 [] [component] [gg-f72b345ad39e69dbe12d] [INFO] com.aws.greengrass.testing.launcher.reporting.StepTrackingReporting - Passed: 'As a developer, I can create a component and deploy it on my device'
# 13:10:24.814 [] [] [] [INFO] com.aws.greengrass.testing.modules.AWSResourcesCleanupModule - Cleaned up com.aws.greengrass.testing.resources.AWSResources@e406cac6

The output of the tests is pretty verbose, but it's great to see that the tests have passed! There's a few things that happen:

  1. Under the hood a bunch of AWS IoT resources are created, including:
    • IoT Thing
    • IoT Certificate
    • IoT Policy
    • Greengrass V2 Resources
    • S3 Bucket for storing the component and ancillary files
  2. A Greengrass deployment is then created and deployed to a Greengrass Core device, and the status of the deployment is checked.
  3. Then the resources are cleaned up whether the tests pass or fail.

You will probably also notice a bunch of new files and folders existing in your project now - These are test artifacts that are created as part of the test run.

testResults
├── aws.greengrass.Nucleus.log
├── aws.greengrass.StreamManager.log
├── com.devopstar.json.gzip.log
├── greengrass.log
├── main.log
cucumber.json
TEST-greengrass-results.xml

An explanation of these files and folders can be summarized quickly as:

  • testResults - A folder containing the logs from the Greengrass Core device and the component itself.
  • cucumber.json - Cucumber test results in JSON format - Cucumber is the BDD framework that is used by the OTF.
  • TEST-greengrass-results.xml - JUint test results in XML format

Exploring the Test Suite

Checking out the template project in gg-e2e-tests we'll focus on the main/resources/greengrass/features/component.feature file. By default it should look something like this:

Feature: Testing features of Greengrassv2 GDK_COMPONENT_NAME

    Background:
        Given my device is registered as a Thing
        And my device is running Greengrass

    @Sample
    Scenario: As a developer, I can create a component and deploy it on my device
        When I create a Greengrass deployment with components
            | GDK_COMPONENT_NAME | GDK_COMPONENT_RECIPE_FILE |
        And I deploy the Greengrass deployment configuration
        Then the Greengrass deployment is COMPLETED on the device after 180 seconds
        And I call my custom step

It doesn't look like much but the cucumber definition is pretty powerful. Based entirely on the way that the feature file is written, the OTF will bring up cloud resources to support a GreenGrass deployment which lets you write tests that are as close to the real world as possible.

Variables like GDK_COMPONENT_NAME and GDK_COMPONENT_RECIPE_FILE are replaced with values from the gdk-config.json file, and the @Sample tag is used to filter which tests are run - If you remember back to the gdk-config.json file, we specified a tag of Sample in the otf_options block. This means that only scenarios with the @Sample tag will be run.

Most of the scenarios in this file are pretty self explanatory, but the one that I want to focus on is the last one:

And I call my custom step

This is a custom step that we can define ourselves in supporting Java code. Taking a quick look at the main/java/com/aws/greengrass/CustomSteps.java file, we can see that this step is defined as:

@ScenarioScoped
public class CustomSteps {

    @And("I call my custom step")
    public void customStep() {
        System.out.println("My custom step was called ");
    }
}

The @ScenarioScoped annotation means that this class will be instantiated once per scenario, and the @And annotation means that this method will be called when the step And I call my custom step is called.

Customizing the Test Suite

Now that we have a working test suite and some vague understanding, let's dive into customizing the test suite to test our component.

The component that I'm testing is a simple component that does the following:

  1. Receives a JSON payload over StreamManager
  2. Compresses the payload in batches using GZIP and writes the file to disk
  3. Uploads the files to S3 using StreamManager S3 export
  4. Deletes the file from disk once the upload is complete

For the purpose of this scenario I am going to be using a component I've already written that generates a JSON payload and sends it over StreamManager - com.devopstar.Robocat.

I know that I'm going to need a bucket to upload the GZIP files to, so we can start by modifying the scenario to create a bucket for use, along with deploying my existing com.devopstar.Robocat component that generates data.

    @Sample
    Scenario: As a developer, I can create a component and deploy it on my device
        When I create an S3 bucket for testing
        And I create a Greengrass deployment with components
            | GDK_COMPONENT_NAME           | GDK_COMPONENT_RECIPE_FILE |
            | com.devopstar.Robocat        | LATEST                    |

The line When I create an S3 bucket for testing is a special step that will create an S3 bucket for use in the test. We will reference it later on.

Next we modify the scenario to alter the deployed configuration for each of the components. This is also where the bucket reference comes in under aws.resources:s3:bucket:bucketName.

        And I update my Greengrass deployment configuration, setting the component GDK_COMPONENT_NAME configuration to:
            """
            {
                "MERGE": {
                    "Processor": {
                        "StreamName": "BatchMessageStream",
                        "BatchSize": "20",
                        "Interval": "1",
                        "Path": "/tmp/greengrass/gzip"
                    },
                    "Uploader": {
                        "BucketName": "${aws.resources:s3:bucket:bucketName}",
                        "Prefix": "robocat",
                        "Interval": "1",
                        "Path": "/tmp/greengrass/gzip/*"
                    },
                    "LogLevel": "DEBUG"
                }
            }
            """
        And I update my Greengrass deployment configuration, setting the component com.devopstar.Robocat configuration to:
            """
            {
                "MERGE": {
                    "Enabled": "true",
                    "Frequency": "0.1"
                }
            }
            """

The final modification I will make it to check the logs of the component to ensure that it is working as expected. This is done by adding the following step:

        And the com.devopstar.json.gzip log on the device contains the line "Successfully wrote batch_0 to /tmp/greengrass/gzip/batch_0.jsonl.gz" within 60 seconds

Running this test again requires us to rebuild the test suite (and the component if we modified it at all).

gdk component build
gdk test-e2e build

Then the test can be run again.

$ gdk test-e2e run
# [2023-07-25 13:42:27] INFO - Downloading latest nucleus archive from url https://d2s8p88vqu9w66.cloudfront.net/releases/greengrass-latest.zip
# [2023-07-25 13:42:29] INFO - Running test jar with command java -jar /workspaces/aws-greengrass-json-gzip/greengrass-build/gg-e2e-tests/target/uat-features-1.0.0.jar --tags=Sample --ggc-archive=/workspaces/aws-greengrass-json-gzip/greengrass-build/greengrass-nucleus-latest.zip
# WARNING: sun.reflect.Reflection.getCallerClass is not supported. This will impact performance.
# 13:42:32.295 [] [] [] [INFO] com.aws.greengrass.testing.modules.GreengrassContextModule - Extracting /workspaces/aws-greengrass-json-gzip/greengrass-build/greengrass-nucleus-latest.zip into /tmp/gg-testing-15600816885281339431/greengrass
# 13:42:32.977 [otf-1.1.0-SNAPSHOT] [] [] [INFO] com.aws.greengrass.testing.features.LoggerSteps - OTF Version is otf-1.1.0-SNAPSHOT
# 13:42:32.977 [otf-1.1.0-SNAPSHOT] [component] [gg-37c841babc08fc7e7e96] [INFO] com.aws.greengrass.testing.features.LoggerSteps - Attaching thread context to scenario: 'As a developer, I can create a component and deploy it on my device'
# 13:42:34.903 [otf-1.1.0-SNAPSHOT] [component] [gg-37c841babc08fc7e7e96] [INFO] com.aws.greengrass.testing.resources.AbstractAWSResourceLifecycle - Created IotPolicy in IotLifecycle
...
# 13:42:37.494 [otf-1.1.0-SNAPSHOT] [component] [gg-37c841babc08fc7e7e96] [INFO] greengrass/features/component.feature - Finished step: 'my device is registered as a Thing' with status PASSED
# 13:42:38.761 [otf-1.1.0-SNAPSHOT] [component] [gg-37c841babc08fc7e7e96] [INFO] com.aws.greengrass.testing.DefaultGreengrass - Starting Greengrass on pid 48160
# 13:42:38.761 [otf-1.1.0-SNAPSHOT] [component] [gg-37c841babc08fc7e7e96] [INFO] greengrass/features/component.feature - Finished step: 'my device is running Greengrass' with status PASSED
# 13:42:40.656 [otf-1.1.0-SNAPSHOT] [component] [gg-37c841babc08fc7e7e96] [INFO] com.aws.greengrass.testing.resources.AbstractAWSResourceLifecycle - Created S3Bucket in S3Lifecycle
# 13:42:40.656 [otf-1.1.0-SNAPSHOT] [component] [gg-37c841babc08fc7e7e96] [INFO] greengrass/features/component.feature - Finished step: 'I create an S3 bucket for testing' with status PASSED
# 13:42:41.666 [otf-1.1.0-SNAPSHOT] [component] [gg-37c841babc08fc7e7e96] [INFO] com.aws.greengrass.testing.resources.AbstractAWSResourceLifecycle - Created S3Object in S3Lifecycle
# 13:42:41.666 [otf-1.1.0-SNAPSHOT] [component] [gg-37c841babc08fc7e7e96] [INFO] com.aws.greengrass.testing.component.RecipeComponentPreparationService - Uploaded /workspaces/aws-greengrass-json-gzip/greengrass-build/artifacts/com.devopstar.json.gzip/NEXT_PATCH/aws-greengrass-json-gzip.zip to s3://gg-37c841babc08fc7e7e96-gg-component-store///workspaces/aws-greengrass-json-gzip/greengrass-build/artifacts/com.devopstar.json.gzip/NEXT_PATCH/aws-greengrass-json-gzip.zip
# 13:42:42.381 [otf-1.1.0-SNAPSHOT] [component] [gg-37c841babc08fc7e7e96] [INFO] com.aws.greengrass.testing.resources.AbstractAWSResourceLifecycle - Created GreengrassComponent in GreengrassV2Lifecycle
# 13:42:42.382 [otf-1.1.0-SNAPSHOT] [component] [gg-37c841babc08fc7e7e96] [INFO] com.aws.greengrass.testing.component.RecipeComponentPreparationService - Created component com.devopstar.json.gzip:1.0.0-37c841babc08fc7e7e96 from ///workspaces/aws-greengrass-json-gzip/greengrass-build/recipes/e2e_test_recipe.yaml
# 13:42:42.652 [otf-1.1.0-SNAPSHOT] [component] [gg-37c841babc08fc7e7e96] [INFO] greengrass/features/component.feature - Finished step: 'I create a Greengrass deployment with components' with status PASSED
# 13:42:42.661 [otf-1.1.0-SNAPSHOT] [component] [gg-37c841babc08fc7e7e96] [INFO] greengrass/features/component.feature - Finished step: 'I update my Greengrass deployment configuration, setting the component com.devopstar.json.gzip configuration to:' with status PASSED
# 13:42:42.663 [otf-1.1.0-SNAPSHOT] [component] [gg-37c841babc08fc7e7e96] [INFO] greengrass/features/component.feature - Finished step: 'I update my Greengrass deployment configuration, setting the component com.devopstar.Robocat configuration to:' with status PASSED
# 13:42:42.976 [otf-1.1.0-SNAPSHOT] [component] [gg-37c841babc08fc7e7e96] [INFO] com.aws.greengrass.testing.resources.AbstractAWSResourceLifecycle - Created GreengrassDeployment in GreengrassV2Lifecycle
# 13:42:42.976 [otf-1.1.0-SNAPSHOT] [component] [gg-37c841babc08fc7e7e96] [INFO] com.aws.greengrass.testing.features.DeploymentSteps - Created Greengrass deployment: b75cd9b7-d4cc-4658-8b8f-de0ae6ce82d3
# 13:42:42.976 [otf-1.1.0-SNAPSHOT] [component] [gg-37c841babc08fc7e7e96] [INFO] greengrass/features/component.feature - Finished step: 'I deploy the Greengrass deployment configuration' with status PASSED
# 13:45:25.135 [otf-1.1.0-SNAPSHOT] [component] [gg-37c841babc08fc7e7e96] [INFO] greengrass/features/component.feature - Finished step: 'the Greengrass deployment is COMPLETED on the device after 180 seconds' with status PASSED
# 13:45:26.843 [otf-1.1.0-SNAPSHOT] [component] [gg-37c841babc08fc7e7e96] [INFO] greengrass/features/component.feature - Finished step: 'the com.devopstar.json.gzip log on the device contains the line "Successfully wrote batch_0 to /tmp/greengrass/gzip/batch_0.jsonl.gz" within 60 seconds' with status PASSED
# My custom step was called 
# 13:45:26.847 [otf-1.1.0-SNAPSHOT] [component] [gg-37c841babc08fc7e7e96] [INFO] greengrass/features/component.feature - Finished step: 'I call my custom step' with status PASSED
# 13:45:27.591 [otf-1.1.0-SNAPSHOT] [component] [gg-37c841babc08fc7e7e96] [INFO] com.aws.greengrass.testing.DefaultGreengrass - Stopped Greengrass on pid 48160
# 13:45:27.994 [otf-1.1.0-SNAPSHOT] [component] [gg-37c841babc08fc7e7e96] [INFO] com.aws.greengrass.testing.resources.AbstractAWSResourceLifecycle - Removed GreengrassDeployment in GreengrassV2Lifecycle
...
# 13:45:31.617 [otf-1.1.0-SNAPSHOT] [component] [gg-37c841babc08fc7e7e96] [INFO] com.aws.greengrass.testing.features.AWSResourcesSteps - Successfully removed externally created resources
# 13:45:31.621 [otf-1.1.0-SNAPSHOT] [component] [gg-37c841babc08fc7e7e96] [INFO] com.aws.greengrass.testing.features.LoggerSteps - Clearing thread context on scenario: 'As a developer, I can create a component and deploy it on my device'
# 13:45:31.624 [] [component] [gg-37c841babc08fc7e7e96] [INFO] com.aws.greengrass.testing.launcher.reporting.StepTrackingReporting - Passed: 'As a developer, I can create a component and deploy it on my device'
# 13:45:31.821 [] [] [] [INFO] com.aws.greengrass.testing.modules.AWSResourcesCleanupModule - Cleaned up com.aws.greengrass.testing.resources.greengrass.GreengrassV2Lifecycle$$EnhancerByGuice$$21196200@330ac85b

Great! This test verifies that data is being generated by the com.devopstar.Robocat component, and that the com.devopstar.json.gzip component is receiving the data and compressing it.

Summary

Overall I'm pretty impressed with the OTF and the new integration with GDK. It's a great way to get started with testing your components and I'm looking forward to seeing how it evolves over time.

I think currently, the biggest limitation is the lack of documentation around the OTF and what it can do. I found myself having to dig through the source code to figure out how to do certain things, and I'm sure there's a lot more that I haven't even touched on.

I'm keen to hear what you think about the OTF and if you have any questions or comments, please feel free to reach out to me on Twitter @nathangloverAUS or leave a comment below!

devopstar

DevOpStar by Nathan Glover | 2024