Testing

Testing #

Playbook tanpa test adalah hutang teknis yang menunggu waktu untuk meledak. Perubahan kecil di role bisa membreak deployment di lingkungan yang tidak terduga. Template yang berubah bisa menghasilkan konfigurasi yang tidak valid. Dependency yang diupdate bisa membawa breaking change. Testing Ansible bukanlah kemewahan — ia adalah praktik yang membuat kamu percaya diri untuk mengubah kode dan mendeploy tanpa rasa takut.

ansible-lint: Static Analysis #

ansible-lint menganalisis playbook dan role untuk menemukan masalah tanpa perlu menjalankannya:

pip install ansible-lint

# Lint satu playbook
ansible-lint site.yml

# Lint seluruh project
ansible-lint

# Dengan output yang lebih detail
ansible-lint -v site.yml

Konfigurasi ansible-lint via file .ansible-lint di root project:

# .ansible-lint
profile: production    # Level keketatan: min, basic, moderate, safety, shared, production

skip_list:
  - yaml[line-length]      # Skip rule panjang baris (sesuaikan dengan preferensi tim)
  - name[template]         # Skip rule template di nama task

warn_list:
  - experimental           # Warning, bukan error untuk rule experimental

exclude_paths:
  - .cache/
  - molecule/
  - tests/

Molecule: Integration Testing untuk Role #

Molecule adalah framework testing khusus untuk Ansible role. Ia menyiapkan environment (container atau VM), menjalankan role, kemudian memverifikasi hasilnya:

pip install molecule molecule-plugins[docker]

Inisialisasi Molecule untuk role yang sudah ada:

cd roles/nginx
molecule init scenario --driver-name docker

Struktur yang dihasilkan:

roles/nginx/
  └── molecule/
      └── default/
          ├── molecule.yml       # Konfigurasi scenario
          ├── converge.yml       # Playbook yang menjalankan role
          └── verify.yml         # Playbook untuk verifikasi hasil
# roles/nginx/molecule/default/molecule.yml
---
dependency:
  name: galaxy

driver:
  name: docker

platforms:
  - name: ubuntu-22
    image: geerlingguy/docker-ubuntu2204-ansible:latest
    pre_build_image: true
  - name: ubuntu-20
    image: geerlingguy/docker-ubuntu2004-ansible:latest
    pre_build_image: true

provisioner:
  name: ansible

verifier:
  name: ansible
# roles/nginx/molecule/default/converge.yml
---
- name: Converge
  hosts: all
  become: true
  vars:
    nginx_port: 80
    nginx_ssl_enabled: false

  roles:
    - role: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}"
# roles/nginx/molecule/default/verify.yml
---
- name: Verify
  hosts: all
  gather_facts: false
  tasks:
    - name: Cek nginx terinstal
      command: nginx -v
      register: nginx_version
      changed_when: false

    - name: Cek nginx berjalan
      systemd:
        name: nginx
      register: nginx_status

    - name: Assert nginx aktif
      assert:
        that:
          - nginx_status.status.ActiveState == "active"
        fail_msg: "nginx tidak berjalan setelah role dieksekusi"

    - name: Cek konfigurasi nginx valid
      command: nginx -t
      changed_when: false

    - name: Verifikasi port 80 terbuka
      wait_for:
        port: 80
        timeout: 10
        state: started

Menjalankan Molecule test:

# Test penuh: create → converge → verify → destroy
molecule test

# Hanya converge (berguna saat develop)
molecule converge

# Hanya verify (setelah converge manual)
molecule verify

# Login ke container untuk debugging
molecule login --host ubuntu-22

testinfra: Verifikasi State Server #

testinfra adalah library Python untuk menulis test yang memverifikasi state server setelah playbook dieksekusi:

pip install pytest-testinfra
# tests/test_nginx.py
import pytest

def test_nginx_installed(host):
    """nginx harus terinstal"""
    nginx = host.package("nginx")
    assert nginx.is_installed

def test_nginx_running(host):
    """nginx service harus berjalan dan aktif"""
    nginx_service = host.service("nginx")
    assert nginx_service.is_running
    assert nginx_service.is_enabled

def test_nginx_listening(host):
    """nginx harus mendengarkan di port 80"""
    socket = host.socket("tcp://0.0.0.0:80")
    assert socket.is_listening

def test_nginx_config_valid(host):
    """konfigurasi nginx harus valid"""
    result = host.run("nginx -t")
    assert result.rc == 0

def test_config_file_exists(host):
    """file konfigurasi harus ada dengan permission yang benar"""
    config = host.file("/etc/nginx/nginx.conf")
    assert config.exists
    assert config.mode == 0o644
    assert config.user == "root"
# Jalankan test terhadap host tertentu
pytest tests/test_nginx.py --hosts=ssh://[email protected]

Integrasikan Testing ke CI Pipeline #

# .github/workflows/test.yml
name: Test Ansible Role

on:
  pull_request:
    paths:
      - 'roles/**'
      - 'playbooks/**'

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: pip install ansible ansible-lint
      - run: ansible-lint

  molecule:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        role: [nginx, postgresql, common]
    steps:
      - uses: actions/checkout@v4
      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.11"
      - name: Install test dependencies
        run: pip install ansible molecule molecule-plugins[docker] pytest-testinfra
      - name: Jalankan Molecule test
        run: |
          cd roles/${{ matrix.role }}
          molecule test          
        env:
          PY_COLORS: "1"
          ANSIBLE_FORCE_COLOR: "1"

Ringkasan #

  • ansible-lint untuk static analysis — temukan masalah syntax, best practice violation, dan potential bug sebelum playbook dijalankan.
  • Molecule untuk integration testing role — test role secara terisolasi di container, verifikasi bahwa role menghasilkan state yang diharapkan.
  • molecule test menjalankan siklus penuh: create → converge → verify → destroy — gunakan molecule converge saat develop untuk loop yang lebih cepat.
  • testinfra untuk verifikasi state server dengan Python test — lebih ekspresif dari verify.yml Molecule untuk kasus kompleks.
  • Integrasikan testing ke CI pipeline pada setiap pull request — pastikan tidak ada role yang bisa di-merge tanpa passing test.
  • Mulai sederhana: ansible-lint dulu, lalu tambahkan Molecule satu role sekaligus — jangan coba setup testing untuk semua role sekaligus.

← Sebelumnya: Performance   Berikutnya: Logging →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact