Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvement: run tests with pytest #1

Open
Robin-Castellani opened this issue Jan 3, 2025 · 0 comments
Open

Improvement: run tests with pytest #1

Robin-Castellani opened this issue Jan 3, 2025 · 0 comments

Comments

@Robin-Castellani
Copy link

Thank you @charliermarsh for this example, I found it during an experimentation with uv and lambdas.

In my workflow, I usually run tests before deployment.
Based on your example, I'd have to add few lines to the Dockerfile:

# Place executables in the environment at the front of the path
ENV PATH="${LAMBDA_TASK_ROOT}/bin:$PATH"  # actually taken from uv + docker example
# Add PYTHONPATH to point to Lambda task root where packages are installed
ENV PYTHONPATH="${LAMBDA_TASK_ROOT}:${PYTHONPATH}"

These are needed when I want to run RUN pytest. Of course, I have a tests folder copied in the lambda's root folder.

A fully working example involves:

  • adding pytest as dev dependency
  • adding a tests folder with a basic test
This is the working Dockerfile:
FROM ghcr.io/astral-sh/uv:latest AS uv

# First, bundle the dependencies into the task root.
FROM public.ecr.aws/lambda/python:3.13 AS builder

# Enable bytecode compilation.
ENV UV_COMPILE_BYTECODE=1

# Enable copy mode to support bind mount caching.
ENV UV_LINK_MODE=copy

# Bundle the dependencies into the Lambda task root via `uv pip install --target`.
#
# Omit any local packages (`--no-emit-workspace`) and development dependencies (`--no-dev`).
# This ensures that the Docker layer cache is only invalidated when the `pyproject.toml` or `uv.lock`
# files change, but remains robust to changes in the application code.
RUN --mount=from=uv,source=/uv,target=/bin/uv \
    --mount=type=cache,target=/root/.cache/uv \
    --mount=type=bind,source=uv.lock,target=uv.lock \
    --mount=type=bind,source=pyproject.toml,target=pyproject.toml \
    uv export --frozen --no-emit-workspace --dev --no-editable -o requirements.txt && \  # ⚠️ install dev group
    uv pip install -r requirements.txt --target "${LAMBDA_TASK_ROOT}"

FROM public.ecr.aws/lambda/python:3.13

# Copy the runtime dependencies from the builder stage.
COPY --from=builder ${LAMBDA_TASK_ROOT} ${LAMBDA_TASK_ROOT}

# Copy the application code.
COPY ./app ${LAMBDA_TASK_ROOT}/app
COPY ./tests ${LAMBDA_TASK_ROOT}/tests  # ⚠️ copy the tests to run

# ⚠️ the path modification mentioned above
# Place executables in the environment at the front of the path
ENV PATH="${LAMBDA_TASK_ROOT}/bin:$PATH"
# Add PYTHONPATH to point to Lambda task root where packages are installed
ENV PYTHONPATH="${LAMBDA_TASK_ROOT}:${PYTHONPATH}"

RUN pytest tests  # ⚠️ run the tests


# Set the AWS Lambda handler.
CMD ["app.main.handler"]

I recognize the downside of the modifications I propose:

  • you get the dev dependencies installed, which usually isn't something everyone desire; maybe --only-dev would help in this case
  • your build process is slower
  • the tests folder can be considerably big, depending maybe on fixtures; it should be deleted after the test session
    Probably a smarter multi-stage build would solve the first and third downsides... 🤔 But it's more related to Docker than to uv 😌

Do you think it would be valuable to add this case to the example?
Thanks again 🤗

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant