Fixing ‘Donor sign-up’ tests

Our “Donor sign-up” functionality was finished and working a long time ago, several breaks ago, actually. As the page on testing states, if your code is working but you haven’t tested it, is it really working?.

Running pytest tests from within savealife reveals the ugly truth:

and looking at the traceback we see that a ValueError was raised:

Right about now would be a good time to fix it.

ValueError: Required parameter name not set

If the error messages was formatted just a bit better it would make it more clear:

ValueError: Required parameter 'name' not set

Now it is much more clear that the NAME of the DynamoDB table was not set. And how are we setting it? Through an environment variable.

import json
import os
from unittest import mock

from chalice.test import Client

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


@mock.patch.dict(os.environ, {"TABLE_NAME": f"{first_name}-savealife-{ENV}"})
def test_donor_signup():
    from app import app

    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.get("success")

We changed quite a bit in the test so let’s go through the changes one by one:

  1. Four changed lines in the beginning are imports and variables setup. Nothing we haven’t seen so far.
  2. @mock.patch line is where the first half of the magic happens: that is where we’re setting the value of the TABLE_NAME variable
  3. You probably noticed that the from app import app moved inside the function. We had to do it that way since @mock.patch must happen before the TABLE_NAME environment variable is read in chalicelib/db.py
  4. The second assert statement was changed to expect a successful operation

It will work :)

Real DynamoDB table was used. Instead of emulating the cloud for our tests we embraced the cloud and used real resources. If you, for whatever reason, prefer to use local resources the possibility is there with LocalStack. Not every AWS service is supported but DynamoDB is supported quite well.

LocalStack

This workshop will not focus on setting up LocalStack or tests that use it. If you wish to do so you may need to:

  1. Have docker-compose to run LocalStack on your machine
  2. Change the code in chalicelib/db.py slightly so that the line boto3.resource("dynamodb").Table(TABLE_NAME) becomes boto3.resource("dynamodb", endpoint_url=LOCALSTACK_DYNAMO_ENDPOINT_HERE).Table(TABLE_NAME)