Skip to content

Testing

This guide describes the test suite for azure-functions-validation, including how to run tests, the structure of the test suite, and guidelines for contributing new tests.

Overview

The azure-functions-validation project maintains a high standard of quality through a comprehensive test suite. The suite ensures that request validation, response serialization, and decorator behavior work correctly across different Python versions and Azure Functions scenarios.

  • Total Tests: 145+
  • Code Coverage: 99%
  • Supported Environments: Python 3.10, 3.11, 3.12, 3.13, and 3.14

The test suite covers unit tests for individual modules, integration tests with real Azure Function handlers, and smoke tests using the provided examples.

Running Tests

The project uses pytest as its primary testing framework. You can run the tests using make targets or directly via hatch.

Using Makefile

The simplest way to run tests is using the provided Makefile targets:

# Run all tests
make test

# Run tests and generate a coverage report
make cov

The make cov command generates a terminal report, an XML report for CI integration, and a detailed HTML report in the htmlcov/ directory.

Direct Commands

If you prefer to run commands manually via hatch:

# Run all tests with verbose output
hatch run test

# Run tests with coverage
hatch run cov

To pass specific arguments to pytest (e.g., to run a single test file):

hatch run pytest tests/test_pipeline.py

Test Structure

Tests are located in the tests/ directory and organized by the functional area they cover:

File Description
test_decorator.py Validates configuration-time errors when applying @validate_http.
test_pipeline.py Tests the runtime behavior including parsing, validation, and response building.
test_errors.py Focuses on the error module and default error formatting logic.
test_integration.py End-to-end tests using real Azure Function handlers and request objects.
test_examples.py Smoke tests that verify the code snippets in the examples/ directory.
test_public_api.py Verifies the public API surface and export stability.
test_adapter.py Tests the adapter layer responsible for interacting with Azure Functions types.
test_placeholder.py Minimal sanity check for the test environment.

The tests/_test_app/ directory contains a sample Azure Functions application used by the integration tests to verify decorator behavior in a realistic environment.

Test Organization

Tests are generally organized into classes to group related functionality and share logic. Common patterns include:

  • TestSuccessfulValidation: Verifies that valid requests result in successful processing and correct responses.
  • TestValidationErrors: Verifies that invalid input (body, query, path, headers) results in the expected 422 Unprocessable Entity responses.
  • TestAsyncHandlers: Ensures that both synchronous and asynchronous Azure Function handlers are supported correctly.
  • TestCustomErrorFormatter: Validates that users can override the default error response format.
  • TestConfigurationErrors: Checks that improper use of the decorator (e.g., conflicting parameters) is caught at decoration time.

Fixtures

The project uses pytest fixtures to simplify test setup. The most important fixture is mock_request_factory.

mock_request_factory

Located in tests/test_pipeline.py, this fixture provides a factory function to create mock azure.functions.HttpRequest objects. It allows you to specify the method, URL, body, and various parameters without manually setting up complex mock objects.

def test_example(mock_request_factory):
    request = mock_request_factory(
        method="POST",
        body=b'{"name": "Alice"}',
        params={"debug": "true"}
    )
    # Use the mock request in your test

Integration Test Patterns

MockHttpRequest Class

For tests that require a more robust representation of a request than a simple unittest.mock.Mock, the tests/test_integration.py file defines a MockHttpRequest class. This class implements the HttpRequest interface, providing realistic behavior for methods like get_json() and get_body().

This is particularly useful when testing how the validation layer interacts with the internal state of an Azure Functions request object.

Writing New Tests

When contributing new features or fixing bugs, please follow these guidelines:

  1. Location: Place unit tests in the file corresponding to the module being tested. If it's a new functional area, create a new test_*.py file.
  2. Naming: Use descriptive names for test functions, starting with test_. Use class-based grouping for related tests.
  3. Mocking: Use the mock_request_factory for unit tests. For integration tests that need to verify handler behavior, refer to the patterns in test_integration.py.
  4. Async: If testing async functionality, mark the test with @pytest.mark.anyio.

Example of a new test:

@pytest.mark.anyio
async def test_my_new_feature(mock_request_factory):
    @validate_http(body=MyModel)
    async def handler(req, body):
        return {"result": body.value}

    request = mock_request_factory(body=b'{"value": 42}')
    response = await handler(request)
    assert response.status_code == 200

Coverage Configuration

Coverage settings are defined in pyproject.toml. The project tracks branch coverage to ensure all logical paths are exercised.

  • Source: src/azure_functions_validation
  • Reports: Terminal (missing lines), XML (for CI), and HTML.
  • Branch Coverage: Enabled (branch = true).

You can view the coverage configuration under the [tool.coverage.run] and [tool.coverage.report] sections of pyproject.toml.

CI Test Matrix

The test suite runs automatically on every pull request and push to the main branch. The CI matrix ensures compatibility across:

  • OS: ubuntu-latest
  • Python Versions: 3.10, 3.11, 3.12, 3.13, 3.14

This is managed via the .github/workflows/ci-test.yml configuration.

Troubleshooting

Common Test Failures

  • PYTHONPATH Issues: If tests cannot find the src or examples modules, ensure your environment is set up correctly. Running via hatch run test or make test handles this automatically via the pythonpath setting in pyproject.toml.
  • Pydantic Version: The project supports Pydantic v2. Tests may fail if an older version of Pydantic is installed.
  • Async Setup: Ensure pytest-anyio is installed and tests are correctly marked with @pytest.mark.anyio.
  • Missing Dependencies: If you see import errors for azure.functions, ensure you have installed the development dependencies using pip install -e .[dev].