Testing Chalice apps

If your code is working but you haven’t tested it, is it really working?

The year is 2022 and everyone and their grandmas are aware of the testing pyramid.

On this page we will focus on writing a unit test (or two) that will validate that our code is working as intended. Just before that we should setup our testing environment.

Testing environment

Let’s create the file and folder structure that allows testing our application. Run the following commands in the ~/serverless_workshop/savealife folder (on the same level where app.py is):

{
  mkdir tests
  touch tests/{__init__.py,test_app.py}
}

As for running the tests, trusty pytest will be used, which was installed in the project setup Verify that you have it with:

pip freeze | grep pytest
which pytest

Writing the first test

The function we’re going to test is our simple donor_signup function.

from os import getenv
from chalice import Chalice

try:
    from dotenv import load_dotenv

    load_dotenv()
except ImportError:
    pass

first_name = getenv("WORKSHOP_NAME", "ivica")  # replace with your own name of course

app = Chalice(app_name=f"{first_name}-savealife")

@app.route("/donor/signup", methods=["POST"])
def donor_signup():
    body = app.current_request.json_body

    return body

Chalice provides a test client that can be used to test Lambda functions and REST APIs as well. Since our donor_signup Lambda function serves as a backend to a REST API we will test the whole flow.

In its current form it:

  • Receives a JSON payload
  • Returns the same payload to the caller

And this is something we can test.

Put the following code into ~/serverless_workshop/savealife/tests/test_app.py:

import json

from app import app
from chalice.test import Client


def test_donor_signup():
    json_payload = {
        "first_name": "ivica",
        "city": "Amsterdam",
        "type": "A+",
        "email": "ivica@server.com"
    }

    with Client(app) as client:
        response = client.http.post(
            "/donor/signup",
            headers={"Content-Type": "application/json"},
            body=json.dumps(json_payload)
        )

        assert response.status_code == 200
        assert response.json_body == json_payload

When pytest is executed it will discover and run the test.

pytest

Output should be similar to:

The following page will deal with another important practice in software development which is logging.