Skip to content

Commit 61c1839

Browse files
authored
Merge pull request #367 from enmata/local-test-samples
Initial commit
2 parents 75614a5 + dfeeb04 commit 61c1839

33 files changed

+1816
-0
lines changed

README.md

100644100755
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ Event-driven architectures (EDA) are an architecture style that uses events and
6767
|System Under Test|Language|Description|
6868
|---|---|---|
6969
| [Step Functions](./java-test-samples/step-functions-local) [External] |Java|This project shows a technique for testing an AWS Step Functions workflow in a local desktop environment.|
70+
| [Step Functions](./java-test-samples/step-functions-local-helloworld) |Python|This project demostrates how to test a "Hello World" AWS Step Functions workflow locally using Docker and PyTest.|
71+
| [Step Functions](./java-test-samples/step-functions-local-lambda) |Python|This project shows a technique for testing an AWS Step Functions state machines that integrate with Lambda functions locally.|
72+
| [Step Functions](./java-test-samples/step-functions-local-mock) |Python|This project shows a technique for testing an AWS Step Functions workflows locally using service mocks.|
7073

7174
## Data Processing
7275
| System Under Test|Language|Description|
@@ -92,3 +95,4 @@ Emulation is not a replacement for testing against actual cloud resources, and i
9295
# How do I contribute?
9396

9497
See our [Contributing](./CONTRIBUTING.md) guide for more detail providing additions, enhancements, and edits.
98+
Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
[![python: 3.10](https://img.shields.io/badge/Python-3.10-green)](https://img.shields.io/badge/Python-3.10-green)
2+
[![AWS: Step Functions](https://img.shields.io/badge/AWS-Step%20Functions-orange)](https://img.shields.io/badge/AWS-Step%20Functions-orange)
3+
[![Language: ASL](https://img.shields.io/badge/Language-ASL-blue)](https://img.shields.io/badge/Language-ASL-blue)
4+
[![test: pytest](https://img.shields.io/badge/Test-Pytest-red)](https://img.shields.io/badge/Test-Pytest-red)
5+
[![test: local](https://img.shields.io/badge/Test-Local-red)](https://img.shields.io/badge/Test-Local-red)
6+
7+
# AWS Step Functions: Hello World with PyTest
8+
9+
## Introduction
10+
11+
This project demonstrates how to test AWS Step Functions state machines locally using Docker and PyTest. It focuses on a simple "Hello World" state machine with a Pass state, showing how to create and validate automated tests for AWS Step Functions locally.
12+
13+
14+
---
15+
16+
## Contents
17+
- [AWS Step Functions: Hello World with PyTest](#aws-step-functions-hello-world-with-pytest)
18+
- [Introduction](#introduction)
19+
- [Contents](#contents)
20+
- [Architecture Overview](#architecture-overview)
21+
- [Project Structure](#project-structure)
22+
- [Prerequisites](#prerequisites)
23+
- [Test Scenarios](#test-scenarios)
24+
- [About the Test Process](#about-the-test-process)
25+
- [Testing Workflows](#testing-workflows)
26+
- [Additional Resources](#additional-resources)
27+
28+
---
29+
30+
## Architecture Overview
31+
<p align="center">
32+
<img src="img/stepfunctions-helloworld.png" alt="Hello World Step Functions" width="300"/>
33+
</p>
34+
35+
Components:
36+
- Simple Step Functions state machine with a Pass state
37+
- Testcontainers for container management
38+
- PyTest for automated testing
39+
- AWS Step Functions Local for local execution
40+
41+
<p align="center">
42+
<img src="img/stepfunctions-helloworld-states.png" alt="Hello World Step Functions - States" width="300"/>
43+
</p>
44+
45+
---
46+
47+
## Project Structure
48+
```
49+
├── img/
50+
│ ├── stepfunctions-helloworld-states.png _# Step Functions state flow_
51+
│ └── stepfunctions-mock.png _# visual architecture diagram_
52+
├── statemachine/
53+
│ ├── local_testing.asl.json _# json file containing "Hello World" state machine definition_
54+
│ └── test/valid_input.json _# json file containing "Hello World" state machine input_
55+
├── tests/
56+
│ ├── unit/src/test_step_functions_local.py _# python PyTest test definition_
57+
│ ├── aws-stepfunctions-local-credentials.txt _# Step Functions Docker image environment vars_
58+
│ └── requirements.txt _# pip requirments dependencies file_
59+
└── README.md _# instructions file_
60+
```
61+
62+
---
63+
64+
## Prerequisites
65+
- Docker
66+
- AWS cli (debugging)
67+
- Python 3.10 or newer
68+
- Basic understanding of Step Functions
69+
- Basic understanding of Amazon States Language (ASL)
70+
71+
---
72+
73+
## Test Scenarios (end to end python test)
74+
75+
### 1. Hello World
76+
- Tests the happy path where a single state in step funtions succeed on the first attempt
77+
- Used to validate the basic functionality of the state machine
78+
79+
---
80+
81+
## About the Test Process
82+
83+
The test process leverages PyTest fixtures to manage the lifecycle of the Step Functions Local container and the state machine:
84+
85+
1. **Container Setup**: The `fixture_container` fixture downloads and starts the `amazon/aws-stepfunctions-local` container.
86+
87+
2. **State Machine Creation**: The `fixture_sfn_client` fixture creates a Boto3 client for Step Functions and creates the state machine using the definition from `local_testing.asl.json`.
88+
89+
3. **Test Execution**: When the test runs, it calls `execute_stepfunction` to start an execution of the state machine and monitor it until completion.
90+
91+
4. **Validation**: The test verifies that:
92+
- The execution completed successfully
93+
- The HelloWorld state was properly exited
94+
95+
5. **Cleanup**: After the test completes, the container is automatically shut down by the finalizer added in the `fixture_container`.
96+
97+
---
98+
99+
## Testing Workflows
100+
101+
### Setup Docker Environment
102+
103+
> Make sure Docker engine is running before running the tests.
104+
105+
```shell
106+
step-functions-local-lambda$ docker version
107+
Client: Docker Engine - Community
108+
Version: 24.0.6
109+
API version: 1.43
110+
(...)
111+
```
112+
113+
### Run the Unit Test - End to end python test
114+
115+
> Set up the python environment
116+
117+
``` shell
118+
step-functions-local-helloworld$ cd tests
119+
export AWS_ACCESS_KEY_ID='DUMMYIDEXAMPLE'
120+
export AWS_SECRET_ACCESS_KEY='DUMMYEXAMPLEKEY'
121+
export AWS_REGION='us-east-1'
122+
python3 -m venv venv
123+
source venv/bin/activate
124+
pip install --upgrade pip
125+
pip install -r requirements.txt
126+
```
127+
128+
#### Run the unit tests
129+
130+
``` shell
131+
step-functions-local-helloworld/tests$
132+
python3 -m pytest -s unit/src/test_step_functions_local.py
133+
```
134+
135+
Expected output:
136+
``` shell
137+
step-functions-local-helloworld/tests$ python3 -m pytest -s unit/src/test_step_functions_local.py
138+
========================================================== test session starts ==========================================================
139+
platform linux -- Python 3.10.12, pytest-8.4.1, pluggy-1.6.0
140+
rootdir: /home/ubuntu/environment/serverless-test-samples-approach-2-pytest-distributed_Try3/step-functions-local-helloworld--OK/tests
141+
collected 1 item
142+
143+
unit/src/test_step_functions_local.py Pulling image testcontainers/ryuk:0.8.1
144+
Container started: ecdd9649b97d
145+
Waiting for container <Container: ecdd9649b97d> with image testcontainers/ryuk:0.8.1 to be ready ...
146+
Pulling image amazon/aws-stepfunctions-local
147+
Container started: d1bd33969e6b
148+
Waiting for container <Container: d1bd33969e6b> with image amazon/aws-stepfunctions-local to be ready ...
149+
.
150+
151+
========================================================== 1 passed in 10.57s ==========================================================
152+
(
153+
```
154+
155+
#### Clean up section
156+
157+
> clean pyenv environment
158+
159+
```sh
160+
step-functions-local-helloworld/tests$
161+
deactivate
162+
rm -rf venv/
163+
```
164+
165+
> unsetting variables
166+
167+
```sh
168+
unset AWS_ACCESS_KEY_ID
169+
unset AWS_SECRET_ACCESS_KEY
170+
unset AWS_REGION
171+
```
172+
173+
> cleanning docker
174+
175+
```sh
176+
docker ps --filter "ancestor=amazon/aws-stepfunctions-local" -q | xargs -r docker kill
177+
docker rmi amazon/aws-stepfunctions-local
178+
```
179+
180+
#### Debug - PyTest Debugging
181+
182+
For more detailed debugging in pytest:
183+
184+
```sh
185+
# Run with verbose output
186+
python -m pytest -s -v unit/src/test_step_functions_local.py
187+
188+
# Run with debug logging
189+
python -m pytest -s -v unit/src/test_step_functions_local.py --log-cli-level=DEBUG
190+
```
191+
192+
---
193+
194+
### Fast local development for Step Functions
195+
196+
#### AWS CLI Commands for Manual Verification
197+
198+
If you need to manually verify the state machine or execution details, you can use these commands:
199+
200+
#### Configure environment variables:
201+
202+
```sh
203+
step-functions-local-helloworld/tests$
204+
export AWS_ACCESS_KEY_ID='DUMMYIDEXAMPLE'
205+
export AWS_SECRET_ACCESS_KEY='DUMMYEXAMPLEKEY'
206+
export AWS_REGION='us-east-1'
207+
```
208+
209+
#### Set up state machine machine manually
210+
211+
```sh
212+
# Runing step functions docker image in the background
213+
step-functions-local-helloworld/tests$
214+
docker run -d \
215+
--name stepfunctions -p 8083:8083 \
216+
--env-file aws-stepfunctions-local-credentials.txt amazon/aws-stepfunctions-local
217+
```
218+
219+
```sh
220+
# Creating Hello World state machine
221+
aws stepfunctions create-state-machine --endpoint-url http://localhost:8083 \
222+
--name "CRUDDynamoDB" --role-arn "arn:aws:iam::012345678901:role/DummyRole" \
223+
--region us-east-1 \
224+
--definition file://../statemachine/local_testing.asl.json
225+
```
226+
227+
#### Debug state machine - aws cli debugging
228+
229+
```sh
230+
# Get state machine ARN
231+
aws stepfunctions list-state-machines --endpoint-url http://localhost:8083
232+
233+
# Check state machine definition
234+
aws stepfunctions describe-state-machine --endpoint-url http://localhost:8083 \
235+
--state-machine-arn [STATE-MACHINE-ARN]
236+
237+
# Start state machine manually
238+
aws stepfunctions start-execution --endpoint-url http://localhost:8083 \
239+
--state-machine-arn [STATE-MACHINE-ARN]
240+
241+
# Check execution details
242+
aws stepfunctions describe-execution --endpoint http://localhost:8083 \
243+
--execution-arn [STATE-MACHINE-EXECUTION-ARN]
244+
245+
# Check execution history
246+
aws stepfunctions get-execution-history --endpoint http://localhost:8083 \
247+
--execution-arn [STATE-MACHINE-EXECUTION-ARN]
248+
```
249+
250+
---
251+
252+
## Additional Resources
253+
- [Step Functions Local Guide](https://docs.aws.amazon.com/step-functions/latest/dg/sfn-local.html)
254+
- [Amazon States Language Documentation](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-amazon-states-language.html)
255+
- [AWS Step Functions Developer Guide](https://docs.aws.amazon.com/step-functions/latest/dg/welcome.html)
256+
- [PyTest Documentation](https://docs.pytest.org/)
257+
- [Testcontainers Python Documentation](https://testcontainers-python.readthedocs.io/en/latest/)
258+
259+
[Top](#contents)
9.39 KB
Loading
51.8 KB
Loading
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"Comment": "Hello World State Machine of the Amazon States Language using a Pass state",
3+
"StartAt": "HelloWorld",
4+
"States": {
5+
"HelloWorld": {
6+
"Type": "Pass",
7+
"End": true
8+
}
9+
}
10+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"data": {
3+
},
4+
"comments": ""
5+
}
6+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
AWS_ACCESS_KEY_ID=DUMMYIDEXAMPLE
2+
AWS_SECRET_ACCESS_KEY=DUMMYEXAMPLEKEY
3+
AWS_DEFAULT_REGION=us-east-1
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
boto3>=1.26.79
2+
pytest>=7.2.1
3+
pathlib
4+
testcontainers

0 commit comments

Comments
 (0)