11import os
2+ import shutil
23import subprocess
4+ from collections .abc import Callable
35from pathlib import Path
4- from typing import Callable
56
67import pytest
78from boto3 import Session
1213
1314
1415def get_project_root () -> Path :
15- """Finds the project root by looking for the 'dist' directory or a git folder ."""
16+ """Find the project root by locating 'dist' or '. git' ."""
1617 current = Path (__file__ ).resolve ()
1718 for parent in current .parents :
1819 if (parent / "dist" ).exists () or (parent / ".git" ).exists ():
1920 return parent
2021 return Path (__file__ ).resolve ().parents [3 ]
2122
23+
2224@pytest .fixture (scope = "session" )
2325def lambda_zip () -> Path :
26+ """Build the lambda.zip artifact using `make build`."""
2427 project_root = get_project_root ()
2528
26- build_result = subprocess .run (
27- ["make" , "build" ],
29+ make_path = shutil .which ("make" )
30+ if not make_path :
31+ pytest .fail ("The 'make' executable was not found in the system PATH." )
32+
33+ build_result = subprocess .run ( # noqa: S603
34+ [make_path , "build" ],
2835 cwd = project_root ,
2936 capture_output = True ,
3037 text = True ,
@@ -34,61 +41,81 @@ def lambda_zip() -> Path:
3441 if build_result .returncode != 0 :
3542 pytest .fail (
3643 f"'make build' failed with code { build_result .returncode } .\n "
37- f"STDOUT: { build_result .stdout } \n "
38- f"STDERR: { build_result .stderr } "
44+ f"STDOUT:\n { build_result .stdout } \n "
45+ f"STDERR:\n { build_result .stderr } "
3946 )
4047
41- zip_path = project_root / "dist/ lambda.zip"
48+ zip_path = project_root / "dist" / " lambda.zip"
4249 if not zip_path .exists ():
4350 pytest .fail (f"Build succeeded but { zip_path } was not created." )
4451
4552 return zip_path
4653
54+
4755@pytest .fixture (scope = "session" )
48- def lambda_runtime_url (request , lambda_zip ):
56+ def lambda_runtime_url (request , lambda_zip ): # noqa: ARG001
4957 """
50- kick-starts the lambda simulation
58+ Start the lambda simulation using docker compose.
5159 """
5260 docker_services = request .getfixturevalue ("docker_services" )
5361 docker_ip = request .getfixturevalue ("docker_ip" )
5462 project_root = get_project_root ()
5563 compose_file = project_root / "tests/docker-compose.yml"
5664
65+ # Activate the profile without using the --profile flag
5766 env = os .environ .copy ()
5867 env ["COMPOSE_PROFILES" ] = "lambda-test"
5968
60- subprocess .run (
69+ docker_path = shutil .which ("docker" )
70+ if not docker_path :
71+ pytest .fail ("Docker executable not found in PATH" )
72+
73+ result = subprocess .run ( # noqa: S603
6174 [
62- "docker" , "compose" ,
63- "-f" , str (compose_file ),
64- "up" , "-d" , "--build" , "--force-recreate" ,
65- "lambda-api" , "api-gateway-mock" ,
75+ docker_path ,
76+ "compose" ,
77+ "-f" ,
78+ str (compose_file ),
79+ "up" ,
80+ "-d" ,
81+ "--build" ,
82+ "--force-recreate" ,
83+ "lambda-api" ,
84+ "api-gateway-mock" ,
6685 ],
6786 env = env ,
68- check = True ,
6987 capture_output = True ,
7088 text = True ,
89+ check = False ,
7190 )
7291
92+ if result .returncode != 0 :
93+ pytest .fail (
94+ f"Docker compose failed with code { result .returncode } .\n STDOUT:\n { result .stdout } \n STDERR:\n { result .stderr } "
95+ )
96+
7397 port = docker_services .port_for ("lambda-api" , 8080 )
7498 base_url = URL (f"http://{ docker_ip } :{ port } " )
7599
76100 docker_services .wait_until_responsive (
77- timeout = 30.0 , pause = 0.5 , check = lambda : is_responsive (base_url )
101+ timeout = 30.0 ,
102+ pause = 0.5 ,
103+ check = lambda : is_responsive (base_url ),
78104 )
79105
80106 return base_url
81107
82108
83-
84109@pytest .fixture (scope = "session" )
85110def lambda_client (boto3_session : Session , lambda_runtime_url : URL ) -> BaseClient :
111+ """Return a boto3 Lambda client pointing at the simulated lambda runtime."""
86112 return boto3_session .client ("lambda" , endpoint_url = str (lambda_runtime_url ))
87113
114+
88115@pytest .fixture (scope = "session" )
89- def api_gateway_endpoint (request : pytest .FixtureRequest , lambda_runtime_url ) -> URL :
116+ def api_gateway_endpoint (request : pytest .FixtureRequest , lambda_runtime_url ): # noqa: ARG001
90117 """
91- kick-starts the api-gateway lambda simulation
118+ Start and validate the API Gateway mock.
92119 """
93120 docker_services = request .getfixturevalue ("docker_services" )
94121 docker_ip = request .getfixturevalue ("docker_ip" )
@@ -101,26 +128,45 @@ def api_gateway_endpoint(request: pytest.FixtureRequest, lambda_runtime_url) ->
101128 docker_services .wait_until_responsive (
102129 timeout = 30.0 ,
103130 pause = 1.0 ,
104- check = lambda : is_responsive (health_url )
131+ check = lambda : is_responsive (health_url ),
105132 )
133+
106134 return base_url
107135
108136
109137@pytest .fixture
110138def lambda_logs (docker_services ) -> Callable [[], list [str ]]:
111- """Returns a callable that fetches the latest lambda-api logs,
112- allowing tests to inspect runtime output on demand."""
139+ """Return a callable that fetches the latest lambda-api logs."""
113140
114141 def _get_messages () -> list [str ]:
115142 return get_lambda_logs (docker_services )
116143
117144 return _get_messages
118145
119146
120- def get_lambda_logs (docker_services ) -> list [str ]:
121- """returns logs from lambda-api container"""
147+ def get_lambda_logs (docker_services ) -> list [str ]: # noqa :ARG001
148+ """Fetch logs from the lambda-api container."""
149+ raw_docker = shutil .which ("docker" )
150+ if not raw_docker :
151+ return ["Error: Docker not found" ]
122152
123- result : bytes = docker_services ._docker_compose .execute ("logs --no-color lambda-api" )
124- raw_lines = result .decode ("utf-8" ).splitlines ()
125- return [line .partition ("|" )[- 1 ].strip () for line in raw_lines ]
153+ docker_path = Path (raw_docker ).resolve ()
154+ project_root = get_project_root ()
155+ compose_file = (project_root / "tests" / "docker-compose.yml" ).resolve ()
156+
157+ result = subprocess .run ( # noqa: S603
158+ [
159+ str (docker_path ),
160+ "compose" ,
161+ "-f" ,
162+ str (compose_file ),
163+ "logs" ,
164+ "--no-color" ,
165+ "lambda-api" ,
166+ ],
167+ capture_output = True ,
168+ text = True ,
169+ check = False ,
170+ )
126171
172+ return [line .partition ("|" )[- 1 ].strip () for line in result .stdout .splitlines ()]
0 commit comments