Skip to content

Commit a45a792

Browse files
authored
chore(tests): enable end-to-end test workflow (#1470)
1 parent 4dcfb71 commit a45a792

File tree

8 files changed

+286
-817
lines changed

8 files changed

+286
-817
lines changed

Diff for: .github/workflows/run-e2e-tests.yml

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
1-
name: run-e2e-tests
1+
name: Run end-to-end tests
2+
23
on:
34
workflow_dispatch:
5+
6+
push:
7+
branches: [develop]
8+
9+
# Maintenance: Add support for triggering on `run-e2e` label
10+
# and enforce repo origin to prevent abuse
11+
412
env:
513
AWS_DEFAULT_REGION: us-east-1
6-
E2E_TESTS_PATH: tests/e2e/
14+
715
jobs:
816
run:
917
runs-on: ubuntu-latest

Diff for: CONTRIBUTING.md

+53-18
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,20 @@
1-
[![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-Ready--to--Code-blue?logo=gitpod)](https://gitpod.io/from-referrer/)
1+
<!-- markdownlint-disable MD043 MD041 -->
2+
# Table of contents <!-- omit in toc -->
3+
4+
- [Contributing Guidelines](#contributing-guidelines)
5+
- [Reporting Bugs/Feature Requests](#reporting-bugsfeature-requests)
6+
- [Contributing via Pull Requests](#contributing-via-pull-requests)
7+
- [Dev setup](#dev-setup)
8+
- [Local documentation](#local-documentation)
9+
- [Conventions](#conventions)
10+
- [General terminology and practices](#general-terminology-and-practices)
11+
- [Testing definition](#testing-definition)
12+
- [Finding contributions to work on](#finding-contributions-to-work-on)
13+
- [Code of Conduct](#code-of-conduct)
14+
- [Security issue notifications](#security-issue-notifications)
15+
- [Troubleshooting](#troubleshooting)
16+
- [API reference documentation](#api-reference-documentation)
17+
- [Licensing](#licensing)
218

319
# Contributing Guidelines
420

@@ -25,9 +41,11 @@ Contributions via pull requests are much appreciated. Before sending us a pull r
2541

2642
### Dev setup
2743

44+
[![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-Ready--to--Code-blue?logo=gitpod)](https://gitpod.io/from-referrer/)
45+
2846
Firstly, [fork the repository](https://github.com/awslabs/aws-lambda-powertools-python/fork).
2947

30-
To setup your development environment, we recommend using our pre-configured Cloud environment: https://gitpod.io/#https://github.com/YOUR_USERNAME/aws-lambda-powertools-python. Replace YOUR_USERNAME with your GitHub username or organization so the Cloud environment can target your fork accordingly.
48+
To setup your development environment, we recommend using our pre-configured Cloud environment: <https://gitpod.io/#https://github.com/YOUR_USERNAME/aws-lambda-powertools-python>. Replace YOUR_USERNAME with your GitHub username or organization so the Cloud environment can target your fork accordingly.
3149

3250
Alternatively, you can use `make dev` within your local virtual environment.
3351

@@ -47,22 +65,38 @@ GitHub provides additional document on [forking a repository](https://help.githu
4765

4866
You might find useful to run both the documentation website and the API reference locally while contributing:
4967

50-
* **API reference**: `make docs-api-local`
51-
* **Docs website**: `make docs-local`
52-
- If you prefer using Docker: `make docs-local-docker`
68+
- **API reference**: `make docs-api-local`
69+
- **Docs website**: `make docs-local`
70+
- If you prefer using Docker: `make docs-local-docker`
71+
72+
## Conventions
73+
74+
### General terminology and practices
5375

54-
### Conventions
76+
| Category | Convention |
77+
| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
78+
| **Docstring** | We use a slight variation of Numpy convention with markdown to help generate more readable API references. |
79+
| **Style guide** | We use black as well as flake8 extensions to enforce beyond good practices [PEP8](https://pep8.org/). We use type annotations and enforce static type checking at CI (mypy). |
80+
| **Core utilities** | Core utilities use a Class, always accept `service` as a constructor parameter, can work in isolation, and are also available in other languages implementation. |
81+
| **Utilities** | Utilities are not as strict as core and focus on solving a developer experience problem while following the project [Tenets](https://awslabs.github.io/aws-lambda-powertools-python/#tenets). |
82+
| **Exceptions** | Specific exceptions live within utilities themselves and use `Error` suffix e.g. `MetricUnitError`. |
83+
| **Git commits** | We follow [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/). We do not enforce conventional commits on contributors to lower the entry bar. Instead, we enforce a conventional PR title so our label automation and changelog are generated correctly. |
84+
| **API documentation** | API reference docs are generated from docstrings which should have Examples section to allow developers to have what they need within their own IDE. Documentation website covers the wider usage, tips, and strive to be concise. |
85+
| **Documentation** | We treat it like a product. We sub-divide content aimed at getting started (80% of customers) vs advanced usage (20%). We also ensure customers know how to unit test their code when using our features. |
5586

56-
Category | Convention
57-
------------------------------------------------- | ---------------------------------------------------------------------------------
58-
**Docstring** | We use a slight variation of Numpy convention with markdown to help generate more readable API references.
59-
**Style guide** | We use black as well as flake8 extensions to enforce beyond good practices [PEP8](https://pep8.org/). We use type annotations and enforce static type checking at CI (mypy).
60-
**Core utilities** | Core utilities use a Class, always accept `service` as a constructor parameter, can work in isolation, and are also available in other languages implementation.
61-
**Utilities** | Utilities are not as strict as core and focus on solving a developer experience problem while following the project [Tenets](https://awslabs.github.io/aws-lambda-powertools-python/#tenets).
62-
**Exceptions** | Specific exceptions live within utilities themselves and use `Error` suffix e.g. `MetricUnitError`.
63-
**Git commits** | We follow [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/). We do not enforce conventional commits on contributors to lower the entry bar. Instead, we enforce a conventional PR title so our label automation and changelog are generated correctly.
64-
**API documentation** | API reference docs are generated from docstrings which should have Examples section to allow developers to have what they need within their own IDE. Documentation website covers the wider usage, tips, and strive to be concise.
65-
**Documentation** | We treat it like a product. We sub-divide content aimed at getting started (80% of customers) vs advanced usage (20%). We also ensure customers know how to unit test their code when using our features.
87+
### Testing definition
88+
89+
We group tests in different categories
90+
91+
| Test | When to write | Notes | Speed |
92+
| ----------------- | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- |
93+
| Unit tests | Verify the smallest possible unit works. | Networking access is prohibited. Prefer Functional tests given our complexity. | Lightning fast (nsec to ms) |
94+
| Functional tests | Guarantee functionality works as expected. It's a subset of integration test covering multiple units. | No external dependency. Prefer Fake implementations (in-memory) over Mocks and Stubs. | Fast (ms to few seconds at worst) |
95+
| Integration tests | Gain confidence that code works with one or more external dependencies. | No need for a Lambda function. Use our code base against an external dependency _e.g., fetch an existing SSM parameter_. | Moderate to slow (a few minutes) |
96+
| End-to-end tests | Gain confidence that a Lambda function with our code operates as expected. | It simulates how customers configure, deploy, and run their Lambda function - Event Source configuration, IAM permissions, etc. | Slow (minutes) |
97+
| Performance tests | Ensure critical operations won't increase latency and costs to customers. | CI arbitrary hardware can make it flaky. We'll resume writing perf test after our new Integ/End have significant coverage. | Fast to moderate (a few seconds to a few minutes) |
98+
99+
**NOTE**: Functional tests are mandatory. We have plans to create a guide on how to create these different tests. Maintainers will help indicate whether additional tests are necessary and provide assistance as required.
66100

67101
## Finding contributions to work on
68102

@@ -75,6 +109,7 @@ For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of
75109
opensource-codeofconduct@amazon.com with any additional questions or comments.
76110

77111
## Security issue notifications
112+
78113
If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue.
79114

80115
## Troubleshooting
@@ -85,9 +120,9 @@ When you are working on the codebase and you use the local API reference documen
85120

86121
This happens when:
87122

88-
* You did not install the local dev environment yet
123+
- You did not install the local dev environment yet
89124
- You can install dev deps with `make dev` command
90-
* The code in the repository is raising an exception while the `pdoc` is scanning the codebase
125+
- The code in the repository is raising an exception while the `pdoc` is scanning the codebase
91126
- Unfortunately, this exception is not shown to you, but if you run, `poetry run pdoc --pdf aws_lambda_powertools`, the exception is shown and you can prevent the exception from being raised
92127
- Once resolved the documentation should load correctly again
93128

Diff for: MAINTAINERS.md

+81-5
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
- [Releasing a new version](#releasing-a-new-version)
1616
- [Drafting release notes](#drafting-release-notes)
1717
- [Run end to end tests](#run-end-to-end-tests)
18+
- [Structure](#structure)
19+
- [Workflow](#workflow)
1820
- [Releasing a documentation hotfix](#releasing-a-documentation-hotfix)
1921
- [Maintain Overall Health of the Repo](#maintain-overall-health-of-the-repo)
2022
- [Manage Roadmap](#manage-roadmap)
@@ -212,11 +214,85 @@ This will kick off the [Publishing workflow](https://github.com/awslabs/aws-lamb
212214
213215
### Run end to end tests
214216

215-
In order to run end to end tests you need to install CDK CLI first and bootstrap your account with `cdk bootstrap` command. For additional details follow [documentation](https://docs.aws.amazon.com/cdk/v2/guide/bootstrapping.html).
216-
217-
To run locally, export `AWS_PROFILE` environment variable and run `make e2e tests`. To run from GitHub Actions, use [run-e2e-tests workflow](https://github.com/awslabs/aws-lambda-powertools-python/actions/workflows/run-e2e-tests.yml) and pick the branch you want to run tests against.
218-
219-
**NOTE**: E2E tests are run as part of each merge to `develop` branch.
217+
E2E tests are run on every push to `develop` or manually via [run-e2e-tests workflow](https://github.com/awslabs/aws-lambda-powertools-python/actions/workflows/run-e2e-tests.yml).
218+
219+
To run locally, you need [AWS CDK CLI](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html#getting_started_prerequisites) and an [account bootstrapped](https://docs.aws.amazon.com/cdk/v2/guide/bootstrapping.html) (`cdk bootstrap`). With a default AWS CLI profile configured, or `AWS_PROFILE` environment variable set, run `make e2e tests`.
220+
221+
#### Structure
222+
223+
Our E2E framework relies on pytest fixtures to coordinate infrastructure and test parallelization (see [Workflow](#workflow)). You'll notice multiple `conftest.py`, `infrastructure.py`, and `handlers`.
224+
225+
- **`infrastructure`**. Uses CDK to define what a Stack for a given feature should look like. It inherits from `BaseInfrastructure` to handle all boilerplate and deployment logic necessary.
226+
- **`conftest.py`**. Imports and deploys a given feature Infrastructure. Hierarchy matters. Top-level `conftest` deploys stacks only once and blocks I/O across all CPUs. Feature-level `conftest` deploys stacks in parallel, and once complete run all tests in parallel.
227+
- **`handlers`**. Lambda function handlers that will be automatically deployed and exported as PascalCase for later use.
228+
229+
```shell
230+
.
231+
├── __init__.py
232+
├── conftest.py # deploys Lambda Layer stack
233+
├── logger
234+
│ ├── __init__.py
235+
│ ├── conftest.py # deploys LoggerStack
236+
│ ├── handlers
237+
│ │ └── basic_handler.py
238+
│ ├── infrastructure.py # LoggerStack definition
239+
│ └── test_logger.py
240+
├── metrics
241+
│ ├── __init__.py
242+
│ ├── conftest.py # deploys MetricsStack
243+
│ ├── handlers
244+
│ │ ├── basic_handler.py
245+
│ │ └── cold_start.py
246+
│ ├── infrastructure.py # MetricsStack definition
247+
│ └── test_metrics.py
248+
├── tracer
249+
│ ├── __init__.py
250+
│ ├── conftest.py # deploys TracerStack
251+
│ ├── handlers
252+
│ │ ├── async_capture.py
253+
│ │ └── basic_handler.py
254+
│ ├── infrastructure.py # TracerStack definition
255+
│ └── test_tracer.py
256+
└── utils
257+
├── Dockerfile
258+
├── __init__.py
259+
├── data_builder # build_service_name(), build_add_dimensions_input, etc.
260+
├── data_fetcher # get_traces(), get_logs(), get_lambda_response(), etc.
261+
├── infrastructure.py # base infrastructure like deploy logic, Layer Stack, etc.
262+
```
263+
264+
#### Workflow
265+
266+
We parallelize our end-to-end tests to benefit from speed and isolate Lambda functions to ease assessing side effects (e.g., traces, logs, etc.). The following diagram demonstrates the process we take every time you use `make e2e`:
267+
268+
```mermaid
269+
graph TD
270+
A[make e2e test] -->Spawn{"Split and group tests <br>by feature and CPU"}
271+
272+
Spawn -->|Worker0| Worker0_Start["Load tests"]
273+
Spawn -->|Worker1| Worker1_Start["Load tests"]
274+
Spawn -->|WorkerN| WorkerN_Start["Load tests"]
275+
276+
Worker0_Start -->|Wait| LambdaLayerStack["Lambda Layer Stack Deployment"]
277+
Worker1_Start -->|Wait| LambdaLayerStack["Lambda Layer Stack Deployment"]
278+
WorkerN_Start -->|Wait| LambdaLayerStack["Lambda Layer Stack Deployment"]
279+
280+
LambdaLayerStack -->|Worker0| Worker0_Deploy["Launch feature stack"]
281+
LambdaLayerStack -->|Worker1| Worker1_Deploy["Launch feature stack"]
282+
LambdaLayerStack -->|WorkerN| WorkerN_Deploy["Launch feature stack"]
283+
284+
Worker0_Deploy -->|Worker0| Worker0_Tests["Run tests"]
285+
Worker1_Deploy -->|Worker1| Worker1_Tests["Run tests"]
286+
WorkerN_Deploy -->|WorkerN| WorkerN_Tests["Run tests"]
287+
288+
Worker0_Tests --> ResultCollection
289+
Worker1_Tests --> ResultCollection
290+
WorkerN_Tests --> ResultCollection
291+
292+
ResultCollection{"Wait for workers<br/>Collect test results"}
293+
ResultCollection --> TestEnd["Report results"]
294+
ResultCollection --> DeployEnd["Delete Stacks"]
295+
```
220296

221297
### Releasing a documentation hotfix
222298

Diff for: aws_lambda_powertools/event_handler/appsync.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import logging
2-
from abc import ABC
32
from typing import Any, Callable, Optional, Type, TypeVar
43

54
from aws_lambda_powertools.utilities.data_classes import AppSyncResolverEvent
@@ -10,7 +9,7 @@
109
AppSyncResolverEventT = TypeVar("AppSyncResolverEventT", bound=AppSyncResolverEvent)
1110

1211

13-
class BaseRouter(ABC):
12+
class BaseRouter:
1413
current_event: AppSyncResolverEventT # type: ignore[valid-type]
1514
lambda_context: LambdaContext
1615

0 commit comments

Comments
 (0)