Slide 1

Slide 1 text

Cloud Integration Testing Made easy with LocalStack and Testcontainers Vienna 14.10.2023 localstack.cloud

Slide 2

Slide 2 text

Anca Ghenade - Developer Advocate - [email protected] @tinyg210

Slide 3

Slide 3 text

Testing…

Slide 4

Slide 4 text

Some things cannot just easily be tested, for example plane sensors. Landing gear sensors to be more precise.

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

So what’s the first thing we take away from this? Testing must be realistic.

Slide 7

Slide 7 text

But how realistic?

Slide 8

Slide 8 text

The truth is we’ve gotten very used to being “fake”. ● Test data → a runner that cleans a database on every test run. We get green tests with migration problems. ● Selenium → a fake user, using a mouse and keyboard, over and over again. We assume it’s realistic. ● Stamina → the runtime is always fresh for tests. What about subtle memory leaks? ● Scaling → tests run against a single process web server. Reality: a multi-thread environment.

Slide 9

Slide 9 text

Sometimes you have no choice.

Slide 10

Slide 10 text

WE INTERRUPT THE REGULAR SCHEDULED PRESENTATION TO BRING YOU THIS IMPORTANT STORY TIME

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

What about applications with dependencies in the cloud?

Slide 13

Slide 13 text

We want to keep it as real as possible when we’re testing our AWS-powered applications and the interaction between various components.

Slide 14

Slide 14 text

The reality:

Slide 15

Slide 15 text

Environment Setup: - AWS Account: Ensure you have access to an AWS account for testing purposes. - Separate Test Environment: Create a separate AWS environment for integration testing to avoid affecting your production environment. - Use of AWS Services: Set up the AWS services you need for testing (databases, storage buckets, queues, Lambda functions, etc). Test Data Preparation: - Data Generation: Prepare test data to use during your integration tests. This data should mimic real-world scenarios and cover different use cases. - Data Isolation: Isolate test data from production data to prevent accidental data loss or corruption.

Slide 16

Slide 16 text

Automate Integration Tests: - Write integration tests using test automation frameworks such as JUnit, TestNG, or a tool specific to your programming language or AWS services (e.g., AWS SDK for Java, AWS CDK). - Use testing libraries that support AWS services to interact with your resources programmatically (e.g., AWS SDKs, AWS Amplify, AWS CDK constructs). - Perform tests that exercise interactions between AWS services, such as Lambda functions invoking other services, S3 bucket operations, or SQS queue processing. Test Scenarios: - Test various scenarios, including both positive and negative cases. Ensure that your tests cover different service interactions, error handling, and edge cases.

Slide 17

Slide 17 text

Service Isolation: - Isolate AWS services as needed to ensure that your tests do not interfere with each other or the production environment. This can involve using separate AWS accounts or resource tagging. Testing AWS Lambda Functions: - Test AWS Lambda functions locally using a local development environment or tools like the AWS SAM CLI. - Automate the deployment and invocation of Lambda functions during testing.

Slide 18

Slide 18 text

Security Testing: - Include security testing in your integration tests to identify vulnerabilities and ensure that AWS security configurations are correct. - Test IAM roles, security groups, and network configurations. Cleanup and Resource Management: - Implement resource cleanup procedures to ensure that resources created during testing are properly disposed of to avoid unnecessary costs and resource leakage. Continuous Integration (CI): - Integrate integration tests into your CI/CD pipeline to ensure that tests are executed automatically whenever code changes are pushed.

Slide 19

Slide 19 text

Documentation and Reporting: - Document test scenarios, results, and any issues encountered during integration testing. - Use reporting and visualization tools to present test results in a clear and actionable format. Regression Testing: Periodically rerun integration tests to catch regressions as you make changes or updates to your AWS infrastructure and application code.

Slide 20

Slide 20 text

So things are kind of… complicated. 󰤆

Slide 21

Slide 21 text

What are some of the common approaches to testing with cloud dependencies?

Slide 22

Slide 22 text

The “let’s prove it works”

Slide 23

Slide 23 text

Focus on: ● Mostly end-to-end and integration testing ● Mocking only the necessities

Slide 24

Slide 24 text

Pros: ● Confidence → Passing tests = it works ● Fewer tests = less effort Cons: ● Tests can’t provide many design cues ● Slow feedback ● High coverage is infeasible

Slide 25

Slide 25 text

No content

Slide 26

Slide 26 text

The “mocking the boundaries”

Slide 27

Slide 27 text

Focus on: ● Mock/fake remote systems ● Mostly unit and end-to-end testing

Slide 28

Slide 28 text

Pros: ● Every object is exercised by many tests → high regression value ● Practical tests without deep knowledge of your mocks Cons: ● One change and everything needs to be adjusted ● End-to-end tests become redundant ● Limited feedback/knowledge about interaction if you do TDD

Slide 29

Slide 29 text

No content

Slide 30

Slide 30 text

Circling back to reality… reality is expensive, so we also want to test on a budget.

Slide 31

Slide 31 text

How much of your system you can test Cloud emulation Staging environments Real AWS Mocking So how much reality can we have in cloud application testing? 3 4 Service emulation 2 1

Slide 32

Slide 32 text

And how can we bring the ease and speed of unit tests into our integration tests?

Slide 33

Slide 33 text

What is LocalStack and how can it help you? A fully functional local cloud stack that was born out of these exact concerns.

Slide 34

Slide 34 text

● Enables a highly efficient dev & test loop for cloud apps ● Ships as a Docker image, easy to install and start up ● Support for 90-ish services (and growing): ○ compute (Lambda, ECS, EKS) ○ various databases (DynamoDB, RDS) ○ messaging (SQS, Kinesis, MSK) ○ some sophisticated/exotic APIs (Athena, Glue) ● CI integrations & advanced collaboration features ○ redefining the way cloud apps are developed across the lifecycle!

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

No content

Slide 37

Slide 37 text

I’ll show you some stuff

Slide 38

Slide 38 text

The “getting started with my app” example Source (Application): https://github.com/localstack-samples/sample-shipment-list-demo-lambda-dynamod b-s3 Source (Testcontainers): https://github.com/tinyg210/testcontainers-shipment-list-demo

Slide 39

Slide 39 text

No content

Slide 40

Slide 40 text

Your application runs locally.

Slide 41

Slide 41 text

Scenario 1 Scenario 2

Slide 42

Slide 42 text

It all boils down to this:

Slide 43

Slide 43 text

No content

Slide 44

Slide 44 text

Configuring your container *Resources are created programmatically in the @BeforeAll method

Slide 45

Slide 45 text

1/2

Slide 46

Slide 46 text

2/2

Slide 47

Slide 47 text

No content

Slide 48

Slide 48 text

The “my apps is pretty much ready” example Source: https://github.com/tinyg210/stack-bytes-apigw-lambda-s3 Folder: github-actions-testcontainers

Slide 49

Slide 49 text

Test successful POST Test successful GET Test fails validation on incorrect values Test 404 on wrong param

Slide 50

Slide 50 text

No content

Slide 51

Slide 51 text

No content

Slide 52

Slide 52 text

Your application is deployed on LocalStack.

Slide 53

Slide 53 text

Tips and Tricks

Slide 54

Slide 54 text

Use init hooks to create your AWS resources.

Slide 55

Slide 55 text

No content

Slide 56

Slide 56 text

No content

Slide 57

Slide 57 text

Use a waiter to make sure your Lambdas are in state ACTIVE and not just created.

Slide 58

Slide 58 text

Source: https://aws.amazon.com/blogs/compute/coming-soon-expansion-of-aws-lambda-states-to-all-functions/

Slide 59

Slide 59 text

No content

Slide 60

Slide 60 text

Use this nifty configuration to scan the LocalStack logs and make sure your instance is in the right state before the tests are allowed to start:

Slide 61

Slide 61 text

No content

Slide 62

Slide 62 text

No content

Slide 63

Slide 63 text

Streaming container output to an SLF4J logger

Slide 64

Slide 64 text

No content

Slide 65

Slide 65 text

Lastly, here’s a workaround to shut down your Lambda containers

Slide 66

Slide 66 text

No content

Slide 67

Slide 67 text

No content

Slide 68

Slide 68 text

“Your application won’t even know the difference”

Slide 69

Slide 69 text

No content

Slide 70

Slide 70 text

In the end…

Slide 71

Slide 71 text

testing I have no doubt that you would be bored senseless by therapy, the same way I'm bored when I brush my teeth and wipe my ass. Because the thing about repairing, maintaining, and cleaning is it's not an adventure. There's no way to do it so wrong you might die. It's just work. And the bottom line is, some people are okay going to work, and some people, well, some people would rather die.

Slide 72

Slide 72 text

Thank You!

Slide 73

Slide 73 text

Questions…

Slide 74

Slide 74 text

…for you

Slide 75

Slide 75 text

Just FYI - Top 3 podium - Game of correctness and agility - You can play as many times as you want

Slide 76

Slide 76 text

Answers

Slide 77

Slide 77 text

No content

Slide 78

Slide 78 text

No content

Slide 79

Slide 79 text

How much of your system you can test Cloud emulation Staging environments Real AWS Mocking 3 4 Service emulation 2 1

Slide 80

Slide 80 text

No content