BOB Docs

Tests

Setting Up

There are end-to-end tests in this solution, located in the _tests directory. We use pytest to run tests. Tests must use environment variables from _env/test.env in the environment.

pytest -v _tests

To simplify tests and ensure all business details of the solution are functioning, tests are written as a customer journey—ordered step-by-step usage of the system by customers, ensuring all functionalities work.

Testing Actors

To facilitate quick testing of endpoints, we have created test actors—special classes that allow making API requests as specific users, either anonymous or logged in.

Actors in tests are primarily responsible for sending requests and providing responses. To simplify future work, we recommend creating additional layers. For example, in Django with pytest, abstract the client into protected values in a class.

Test Helpers

We have also implemented a ResponseChecker abstraction to consolidate rules and eliminate repetitive response checks. This approach uses predefined methods instead of repeating similar checks. Pagination is an excellent example: if your project requires a specific pagination structure, you can add it to ResponseChecker to validate individual elements.

@pytest.mark.usefixtures("use_persistent_db")
@pytest.mark.depends(on=["test_set_customer_as_default"])
@pytest.mark.asyncio
async def test_buy_now_as_anonymous_client(request, mocker, shared_data, anonymous_user_for_testing_store):
    pricing_id = shared_data.get("pricing_id")
    customer_id = shared_data.get("customer_id_to_set_default")
    data = {
        "pricing_id": pricing_id,
        "customer_id": customer_id
    }
    response = await anonymous_user_for_testing_store.post("/api/store/buy-now", data=data)
    response.is_success()
    redirect_url = response.key_value("redirect_url")

Additionally, with normalized errors transformed into responses, you can check their structure and content. In our project, an error class automatically generates a specific response via middleware that catches errors and builds responses. This ensures the API creates user-friendly responses during errors:

def check_exception(self, api_exception: ApiException):
        """
        Verify that the response matches the expected API exception.
        Asserts if the status code or error message does not match.
        """
        exception_status_code = getattr(api_exception, '_status_code')
        assert self._response.status_code == exception_status_code, f"Status is: {self._status} " \
                                                                    f"but should be: {exception_status_code}"
        error_message = getattr(api_exception, '_api_client_message')
        message = self.key_value("message")
        assert error_message == message, f"Message to client is: {message}" \
                                         f"but should be: {error_message}"

Coverage

The current coverage is 80%. To check the current test coverage, use the following pytest command:

pytest --cov=.

On this page