Skip to content

Commit d441561

Browse files
heitorlessarubenfonseca
authored andcommitted
chore(tests): build and deploy Lambda Layer stack once (aws-powertools#1466)
1 parent 762193f commit d441561

14 files changed

+219
-377
lines changed

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ unit-test:
3535
poetry run pytest tests/unit
3636

3737
e2e-test:
38-
poetry run pytest -rP -n 3 --dist loadscope --durations=0 --durations-min=1 tests/e2e
38+
poetry run pytest -rP -n auto --dist loadfile -o log_cli=true tests/e2e
3939

4040
coverage-html:
4141
poetry run pytest -m "not perf" --ignore tests/e2e --cov=aws_lambda_powertools --cov-report=html

poetry.lock

+39-39
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

+8-8
Original file line numberDiff line numberDiff line change
@@ -52,20 +52,20 @@ flake8-bugbear = "^22.7.1"
5252
mkdocs-git-revision-date-plugin = "^0.3.2"
5353
mike = "^0.6.0"
5454
mypy = "^0.971"
55-
mypy-boto3-secretsmanager = "^1.24.11"
56-
mypy-boto3-ssm = "^1.24.0"
57-
mypy-boto3-appconfig = "^1.24.29"
58-
mypy-boto3-dynamodb = "^1.24.27"
5955
retry = "^0.9.2"
6056
pytest-xdist = "^2.5.0"
6157
aws-cdk-lib = "^2.23.0"
6258
pytest-benchmark = "^3.4.1"
63-
mypy-boto3-cloudwatch = "^1.24.35"
64-
mypy-boto3-lambda = "^1.24.0"
65-
mypy-boto3-xray = "^1.24.0"
66-
mypy-boto3-s3 = { version = "^1.24.0", python = ">=3.7" }
59+
mypy-boto3-appconfig = { version = "^1.24.29", python = ">=3.7" }
6760
mypy-boto3-cloudformation = { version = "^1.24.0", python = ">=3.7" }
61+
mypy-boto3-cloudwatch = { version = "^1.24.35", python = ">=3.7" }
62+
mypy-boto3-dynamodb = { version = "^1.24.27", python = ">=3.7" }
63+
mypy-boto3-lambda = { version = "^1.24.0", python = ">=3.7" }
6864
mypy-boto3-logs = { version = "^1.24.0", python = ">=3.7" }
65+
mypy-boto3-secretsmanager = { version = "^1.24.11", python = ">=3.7" }
66+
mypy-boto3-ssm = { version = "^1.24.0", python = ">=3.7" }
67+
mypy-boto3-s3 = { version = "^1.24.0", python = ">=3.7" }
68+
mypy-boto3-xray = { version = "^1.24.0", python = ">=3.7" }
6969
types-requests = "^2.28.8"
7070
typing-extensions = { version = "^4.3.0", python = ">=3.7" }
7171
python-snappy = "^0.6.1"

tests/e2e/conftest.py

+33-64
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,35 @@
1-
import datetime
2-
import sys
3-
import uuid
4-
from dataclasses import dataclass
5-
6-
import boto3
7-
8-
from tests.e2e.utils import data_fetcher, infrastructure
9-
10-
# We only need typing_extensions for python versions <3.8
11-
if sys.version_info >= (3, 8):
12-
from typing import TypedDict
13-
else:
14-
from typing_extensions import TypedDict
15-
16-
from typing import Dict, Generator, Optional
17-
181
import pytest
192

20-
21-
class LambdaConfig(TypedDict):
22-
parameters: dict
23-
environment_variables: Dict[str, str]
24-
25-
26-
@dataclass
27-
class InfrastructureOutput:
28-
arns: Dict[str, str]
29-
execution_time: datetime.datetime
30-
31-
def get_lambda_arns(self) -> Dict[str, str]:
32-
return self.arns
33-
34-
def get_lambda_function_arn(self, cf_output_name: str) -> Optional[str]:
35-
return self.arns.get(cf_output_name)
36-
37-
def get_lambda_function_name(self, cf_output_name: str) -> Optional[str]:
38-
lambda_arn = self.get_lambda_function_arn(cf_output_name=cf_output_name)
39-
return lambda_arn.split(":")[-1] if lambda_arn else None
40-
41-
def get_lambda_execution_time(self) -> datetime.datetime:
42-
return self.execution_time
43-
44-
def get_lambda_execution_time_timestamp(self) -> int:
45-
return int(self.execution_time.timestamp() * 1000)
46-
47-
48-
@pytest.fixture(scope="module")
49-
def create_infrastructure(config, request) -> Generator[Dict[str, str], None, None]:
50-
stack_name = f"test-lambda-{uuid.uuid4()}"
51-
test_dir = request.fspath.dirname
52-
handlers_dir = f"{test_dir}/handlers/"
53-
54-
infra = infrastructure.Infrastructure(stack_name=stack_name, handlers_dir=handlers_dir, config=config)
55-
yield infra.deploy(Stack=infrastructure.InfrastructureStack)
56-
infra.delete()
57-
58-
59-
@pytest.fixture(scope="module")
60-
def execute_lambda(create_infrastructure) -> InfrastructureOutput:
61-
execution_time = datetime.datetime.utcnow()
62-
session = boto3.Session()
63-
client = session.client("lambda")
64-
for _, arn in create_infrastructure.items():
65-
data_fetcher.get_lambda_response(lambda_arn=arn, client=client)
66-
return InfrastructureOutput(arns=create_infrastructure, execution_time=execution_time)
3+
from tests.e2e.utils.infrastructure import LambdaLayerStack, deploy_once
4+
5+
6+
@pytest.fixture(scope="session")
7+
def lambda_layer_arn(lambda_layer_deployment):
8+
yield lambda_layer_deployment.get("LayerArn")
9+
10+
11+
@pytest.fixture(scope="session")
12+
def lambda_layer_deployment(request: pytest.FixtureRequest, tmp_path_factory: pytest.TempPathFactory, worker_id: str):
13+
"""Setup and teardown logic for E2E test infrastructure
14+
15+
Parameters
16+
----------
17+
request : pytest.FixtureRequest
18+
pytest request fixture to introspect absolute path to test being executed
19+
tmp_path_factory : pytest.TempPathFactory
20+
pytest temporary path factory to discover shared tmp when multiple CPU processes are spun up
21+
worker_id : str
22+
pytest-xdist worker identification to detect whether parallelization is enabled
23+
24+
Yields
25+
------
26+
Dict[str, str]
27+
CloudFormation Outputs from deployed infrastructure
28+
"""
29+
yield from deploy_once(
30+
stack=LambdaLayerStack,
31+
request=request,
32+
tmp_path_factory=tmp_path_factory,
33+
worker_id=worker_id,
34+
layer_arn="",
35+
)

tests/e2e/logger/conftest.py

+10-7
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,28 @@
1+
from pathlib import Path
2+
13
import pytest
24

35
from tests.e2e.logger.infrastructure import LoggerStack
4-
from tests.e2e.utils.infrastructure import deploy_once
56

67

78
@pytest.fixture(autouse=True, scope="module")
8-
def infrastructure(request: pytest.FixtureRequest, tmp_path_factory: pytest.TempPathFactory, worker_id: str):
9+
def infrastructure(request: pytest.FixtureRequest, lambda_layer_arn: str):
910
"""Setup and teardown logic for E2E test infrastructure
1011
1112
Parameters
1213
----------
1314
request : pytest.FixtureRequest
1415
pytest request fixture to introspect absolute path to test being executed
15-
tmp_path_factory : pytest.TempPathFactory
16-
pytest temporary path factory to discover shared tmp when multiple CPU processes are spun up
17-
worker_id : str
18-
pytest-xdist worker identification to detect whether parallelization is enabled
16+
lambda_layer_arn : str
17+
Lambda Layer ARN
1918
2019
Yields
2120
------
2221
Dict[str, str]
2322
CloudFormation Outputs from deployed infrastructure
2423
"""
25-
yield from deploy_once(stack=LoggerStack, request=request, tmp_path_factory=tmp_path_factory, worker_id=worker_id)
24+
stack = LoggerStack(handlers_dir=Path(f"{request.path.parent}/handlers"), layer_arn=lambda_layer_arn)
25+
try:
26+
yield stack.deploy()
27+
finally:
28+
stack.delete()

tests/e2e/logger/infrastructure.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
from pathlib import Path
22

3-
from tests.e2e.utils.infrastructure import BaseInfrastructureV2
3+
from tests.e2e.utils.infrastructure import BaseInfrastructure
44

55

6-
class LoggerStack(BaseInfrastructureV2):
7-
def __init__(self, handlers_dir: Path, feature_name: str = "logger") -> None:
8-
super().__init__(feature_name, handlers_dir)
6+
class LoggerStack(BaseInfrastructure):
7+
FEATURE_NAME = "logger"
8+
9+
def __init__(self, handlers_dir: Path, feature_name: str = FEATURE_NAME, layer_arn: str = "") -> None:
10+
super().__init__(feature_name, handlers_dir, layer_arn)
911

1012
def create_resources(self):
1113
self.create_lambda_functions()

0 commit comments

Comments
 (0)