Integration Testing Guide
Relevant source files
The following files were used as context for generating this wiki page:
Integration tests in the opsmill.infrahub collection verify end-to-end functionality by executing Ansible modules and plugins against a live Infrahub instance. These tests ensure that the full path from the Ansible controller through the infrahub-sdk to the Infrahub API functions correctly.
Sources: dev/guidelines/testing.md:12, tests/AGENTS.md:9
Test Architecture and Environment
Integration tests run within a Dockerized environment managed by docker-compose.yml. This setup uses multi-stage builds where the integration stage provides the necessary network access to communicate with Infrahub.
Communication Flow
The integration tests utilize a dedicated Docker network called integration_network. This allows the test container to reach the Infrahub instance.
The diagram above illustrates the data flow from the test runner to the Infrahub API over the integration network.
Sources: dev/guidelines/testing.md:46-51, dev/guidelines/testing.md:104-106
Test Categories
The project implements two primary styles of integration tests:
- Playbook-based Tests: These are standard Ansible playbooks located in
tests/integration/targets/that exercise full module functionality. - Pytest-based Integration: Found in
tests/integration/processor/andtests/integration/inventory/, these tests usepytestagainst a real Infrahub instance started via theinfrahub-testcontainershelper.
Sources: dev/guidelines/testing.md:95-102, dev/guidelines/testing.md:107-112, pyproject.toml:44-48
Directory Structure
Integration tests are organized by their target module or plugin name within the targets directory.
| Directory Path | Content Description |
|---|---|
tests/integration/targets/<name>/tasks/ | Contains main.yml with Ansible tasks to execute. |
tests/integration/targets/playbooks/ | Shared playbooks for common testing scenarios (e.g., node creation). |
tests/integration/processor/ | Pytest integration tests for data processors. |
tests/integration/inventory/ | Pytest integration tests for dynamic inventory plugins. |
Sources: dev/guidelines/testing.md:95-102, tests/integration/targets/playbooks/create_node1.yml
Execution Procedures
Using the Invoke Task
The recommended method for running integration tests is through the invoke task runner.
- Open a terminal in the project root.
- Run
invoke tests-integration.
Sources: dev/guidelines/testing.md:20-25
Direct Docker Compose Execution
You can bypass the task runner and use Docker Compose directly for more control over the container lifecycle.
docker compose up --build --force-recreate --quiet-pull --exit-code-from integration integration
Sources: dev/guidelines/testing.md:37, tests/AGENTS.md:21
Execution Logic for Playbooks
When a playbook integration test runs, it follows a sequence of authentication, execution, and verification.
The sequence diagram shows the synchronous interaction between Ansible components and the Infrahub API during a test run.
Sources: tests/integration/test_modules_integration.py, tests/integration/targets/playbooks/create_node1.yml
Configuration and Dependencies
Environment Variables
Integration tests can be customized using environment variables passed to the Docker containers.
| Variable | Purpose | Default |
|---|---|---|
ANSIBLE_INTEGRATION_ARGS | Extra arguments passed to ansible-test integration. | Empty |
PYTHON_VER | Specifies the Python version for the Docker build. | 3.12 |
Sources: dev/guidelines/testing.md:40-44
Dependency Groups
Integration tests require specific dependencies defined in the pyproject.toml file under the integration group.
[dependency-groups]
integration = [
"pytest>=9.0.3,<10",
"pytest-mock",
"infrahub-testcontainers>=1.7.3",
]
Sources: pyproject.toml:44-48
Best Practices for Integration Tests
- Round-trip Budgets: Do not hardcode fixed ceilings for request counts. Instead, derive budgets from
pagination_sizeand the actual result size to accommodate changing data in shared containers. - Mutation Checking: Before finalizing a test meant to protect a specific behavior, disable that behavior in the code to ensure the test fails.
- Verification by Collection: Always confirm the test runner detects new tests by running
uv run pytest tests/unit --collect-only -q | grep <test_name>. - Clean Environment: Use
--force-recreatewhen running via Docker Compose to ensure a fresh test environment.
Sources: dev/guidelines/testing.md:118-132, tests/AGENTS.md:21