Skip to content

Integration Testing in Ansible

Overview

Integration testing verifies that multiple components of your Ansible automation work together correctly. This includes testing playbooks, roles, and their interactions with the target systems.

Test Structure

Directory Layout

integration_tests/
├── inventory/
│   ├── group_vars/
│   │   └── all.yml
│   └── hosts
├── roles/
│   └── role_under_test/
├── playbooks/
│   ├── test_playbook.yml
│   └── verify_playbook.yml
└── pytest.ini

Example Integration Tests

Test Inventory

# inventory/hosts
[webservers]
webserver1 ansible_host=localhost ansible_connection=docker
webserver2 ansible_host=localhost ansible_connection=docker

[databases]
db1 ansible_host=localhost ansible_connection=docker

Test Playbook

# playbooks/test_playbook.yml
---
- name: Test web server setup
  hosts: webservers
  roles:
    - role: nginx_role
    - role: php_role

  tasks:
    - name: Verify nginx installation
      ansible.builtin.service:
        name: nginx
        state: started
      register: nginx_status

    - name: Verify PHP installation
      ansible.builtin.command: php --version
      register: php_version
      changed_when: false

- name: Test database setup
  hosts: databases
  roles:
    - role: mysql_role

  tasks:
    - name: Verify MySQL installation
      ansible.builtin.service:
        name: mysql
        state: started
      register: mysql_status

Verification Playbook

# playbooks/verify_playbook.yml
---
- name: Verify web stack
  hosts: webservers
  tasks:
    - name: Check nginx configuration
      ansible.builtin.stat:
        path: /etc/nginx/sites-enabled/default
      register: nginx_config

    - name: Test nginx response
      ansible.builtin.uri:
        url: http://localhost
        return_content: yes
      register: webpage
      until: webpage.status == 200
      retries: 3
      delay: 5

    - name: Verify PHP functionality
      ansible.builtin.shell: |
        echo "<?php phpinfo(); ?>" > /var/www/html/info.php
        curl -s http://localhost/info.php | grep -i "PHP Version"
      register: php_info
      changed_when: false

- name: Verify database
  hosts: databases
  tasks:
    - name: Check MySQL connection
      ansible.builtin.command: mysqladmin ping
      register: mysql_ping
      changed_when: false

Running Integration Tests

Using pytest-ansible

# test_integration.py
import pytest
from ansible.parsing.dataloader import DataLoader
from ansible.inventory.manager import InventoryManager
from ansible.vars.manager import VariableManager
from ansible.executor.playbook_executor import PlaybookExecutor

def test_playbook_execution(ansible_runner):
    result = ansible_runner.run(
        playbook='playbooks/test_playbook.yml',
        inventory='inventory/hosts'
    )
    assert result.rc == 0

def test_nginx_installation(ansible_adhoc):
    result = ansible_adhoc.command('nginx -v')
    assert result.is_successful

def test_mysql_connection(ansible_adhoc):
    result = ansible_adhoc.shell('mysql -e "SELECT VERSION();"')
    assert result.is_successful

Infrastructure Testing

Using Testinfra

# test_infrastructure.py
def test_nginx_is_installed(host):
    nginx = host.package("nginx")
    assert nginx.is_installed
    assert nginx.version.startswith("1.18")

def test_nginx_is_running(host):
    nginx = host.service("nginx")
    assert nginx.is_running
    assert nginx.is_enabled

def test_ports_are_listening(host):
    assert host.socket("tcp://0.0.0.0:80").is_listening

def test_php_config(host):
    php_config = host.file("/etc/php/7.4/fpm/php.ini")
    assert php_config.exists
    assert php_config.contains("memory_limit = 256M")

CI/CD Integration Example

# .github/workflows/integration-tests.yml
name: Integration Tests
on: [push, pull_request]

jobs:
  integration-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2

      - name: Set up Python
        uses: actions/setup-python@v2
        with:
          python-version: '3.9'

      - name: Install dependencies
        run: |
          pip install ansible pytest pytest-ansible testinfra docker

      - name: Start test containers
        run: |
          docker-compose -f tests/docker-compose.yml up -d

      - name: Run integration tests
        run: |
          pytest tests/integration/ -v

      - name: Run infrastructure tests
        run: |
          pytest tests/infrastructure/ -v --connection=docker

Best Practices

  1. Environment Isolation
  2. Use containers or VMs for testing
  3. Reset environment between tests
  4. Use appropriate wait conditions

  5. Test Coverage

  6. Test all major configuration changes
  7. Verify service states
  8. Check actual functionality
  9. Test failure scenarios

  10. CI/CD Integration

  11. Automate test execution
  12. Maintain test environments
  13. Archive test results
  14. Set up notifications

  15. Performance Considerations

  16. Use parallel testing where possible
  17. Implement test timeouts
  18. Cache dependencies
  19. Clean up test resources