|
| 1 | +[](https://img.shields.io/badge/Python-3.10-green) |
| 2 | +[](https://img.shields.io/badge/AWS-Step%20Functions-orange) |
| 3 | +[](https://img.shields.io/badge/Language-ASL-blue) |
| 4 | +[](https://img.shields.io/badge/Test-Pytest-red) |
| 5 | +[](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) |
0 commit comments