# Testing

### Pytest library

>

The [Pytest](https://docs.pytest.org/en/stable/contents.html) framework is used to write and run the tests for the API.&#x20;

### unittest.mock library

The [unittest.mock](https://docs.python.org/3/library/unittest.mock.html) library is used to replace parts of code that are not relevant to a test. For example, for the protected routes in the User Management API, unit tests are written for the helpers that check for valid user attributes and user roles. After testing these helpers independently, there is no need to test them again in tests for the protected routes.&#x20;

The return values of these checks can be patched using [patchers](https://docs.python.org/3/library/unittest.mock.html#the-patchers) and/or the [Mock class](https://docs.python.org/3/library/unittest.mock.html#the-mock-class). These tools help tests focus on specific aspects of a method and avoid complicated logic that is unrelated to the test.

### Test implementation

The base of the test implementation is the `TestApp` class that instantiates a test client that can be exposed within tests through `self.client`. The test client is an instance of the [Werkzeug](https://werkzeug.palletsprojects.com/en/1.0.x/) `Client` class documented [here](https://werkzeug.palletsprojects.com/en/1.0.x/test/#werkzeug.test.Client). Through the client, tests can make requests to the Flask app as one would from it on a local or hosted server. More details can be found in the [Test Driven Development section](https://github.com/cityofaustin/atd-moped/tree/main/moped-api#test-driven-development) of the Moped API readme.

### Extending the TestApp class

In order to create tests for different [Flask blueprints](https://github.com/cityofaustin/atd-moped/tree/main/moped-api#blueprint-architecture) of the API, a new class that inherits `TestApp` can be created and written in a separate Python file. For example, to test the `users` blueprint, create a new file called `test_users.py` within the `/tests/` folder. In that file, a new class called `TestUsers` can be defined.

```bash
class TestExamples(TestApp):
    def test_example(self):
        """Test that tests something."""
        result = test_something(arg)

        assert result is True
```

### Testing AWS resources

In order to test API routes that employ AWS resources, the [moto](https://github.com/spulec/moto) library is used to mock AWS resources and isolate any side effects of the tests away from the staging or production AWS environments.&#x20;

{% hint style="info" %}
It is important to take the [documented precautions](https://github.com/spulec/moto#very-important----recommended-usage) in order to avoid accessing live AWS resources from the test environment.
{% endhint %}

An important pattern to successfully test AWS resources is mocking a resource, seeding it with any needed data, and then patching `boto` method calls with `moto`. As an example, to test a route or method that sends a request to a Cognito user pool, a test user pool with mock users must be initialized prior to patching the `boto` methods in that route. The patched `boto` methods will then interact with the mocked user pool for CRUD actions.

The easiest way to start tests with a mocked resource already initialized is with [Pytest fixtures](https://docs.pytest.org/en/stable/fixture.html) as documented in the [moto usage example](https://github.com/spulec/moto#example-on-usage). These fixtures allow individual tests to access a reusable and consistent mocked AWS resources and avoid repetition in tests that use the same AWS resources.
