How to Run Molecule Tests¶
This guide shows you how to run Molecule tests locally to validate your changes before submitting pull requests.
🎯 Goal¶
Learn to effectively use Molecule for:
Running individual role tests
Testing across multiple scenarios
Debugging test failures
Creating custom test scenarios
Validating changes before CI/CD
📋 Prerequisites¶
Completed Set Up Development Environment
Container runtime (Podman/Docker) configured
Molecule and dependencies installed
Basic understanding of Ansible roles
🧪 Understanding Molecule Testing¶
Test Scenarios Available¶
The collection includes several Molecule scenarios:
# List all available scenarios
molecule list
# Common scenarios:
# - default: Basic functionality testing
# - idempotency: Idempotency validation
# - modular: Modular role testing
# - rhel8/rhel9/rhel10: Platform-specific testing
Test Sequence¶
Molecule follows this test sequence:
dependency: Install role dependencies
create: Create test containers
prepare: Prepare test environment
converge: Run the role
idempotence: Test idempotency
verify: Run verification tests
cleanup: Clean up test environment
destroy: Remove test containers
🚀 Step 1: Prepare Testing Environment¶
Activate Testing Environment¶
# Navigate to project root
cd qubinode_kvmhost_setup_collection
# Activate Python environment
source venv/bin/activate
# Activate Molecule environment
source scripts/activate-molecule-env.sh
# Verify setup
molecule --version
Check Container Images¶
# Pull required test images
podman pull docker.io/rockylinux/rockylinux:9-ubi-init
podman pull registry.redhat.io/ubi9-init:latest
# List available images
podman images | grep -E "(rocky|ubi)"
🔧 Step 2: Run Basic Role Tests¶
Test Individual Role¶
# Navigate to specific role
cd roles/kvmhost_base
# Run complete test suite
molecule test
# Run specific test phases
molecule create # Create test containers
molecule converge # Run the role
molecule verify # Run verification tests
molecule destroy # Clean up
Test with Different Scenarios¶
# Test with specific scenario
molecule test --scenario-name rhel9
# List scenarios for current role
molecule list
# Test all scenarios
for scenario in $(molecule list --format plain | awk '{print $2}' | tail -n +2); do
echo "Testing scenario: $scenario"
molecule test --scenario-name $scenario
done
🔍 Step 3: Debug Test Failures¶
Interactive Debugging¶
# Create containers without destroying on failure
molecule create
molecule converge
# Connect to test container for debugging
molecule login
# Inside container, check what went wrong:
systemctl status SERVICE_NAME
journalctl -u SERVICE_NAME
cat /var/log/messages
Verbose Testing¶
# Run with verbose output
molecule test --debug
# Run with Ansible verbose mode
ANSIBLE_VERBOSITY=3 molecule test
# Run specific test with maximum verbosity
ANSIBLE_VERBOSITY=4 molecule converge --scenario-name default
Check Test Logs¶
# View Molecule logs
cat ~/.cache/molecule/ROLE_NAME/default/ansible.log
# Check container logs
podman logs CONTAINER_NAME
# View systemd logs in container
molecule login
journalctl --no-pager
🧩 Step 4: Test Multiple Roles¶
Test Collection-Wide¶
# Return to project root
cd qubinode_kvmhost_setup_collection
# Run collection-wide tests
scripts/test-local-molecule.sh
# Test specific roles only
scripts/test-local-molecule.sh kvmhost_base kvmhost_networking
Parallel Testing¶
# Test multiple roles in parallel (use with caution)
for role in kvmhost_base kvmhost_networking kvmhost_storage; do
(cd roles/$role && molecule test --scenario-name default) &
done
wait
⚙️ Step 5: Custom Test Scenarios¶
Create Custom Scenario¶
# Navigate to role directory
cd roles/kvmhost_base
# Create new scenario
molecule init scenario custom-test
# Edit scenario configuration
vim molecule/custom-test/molecule.yml
Example Custom Scenario Configuration¶
dependency:
name: galaxy
options:
requirements-file: requirements.yml
driver:
name: podman
platforms:
- name: custom-test-instance
image: docker.io/rockylinux/rockylinux:9-ubi-init
dockerfile: ../default/Dockerfile.rhel
pre_build_image: false
systemd: always
command: "/usr/sbin/init"
capabilities:
- SYS_ADMIN
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
environment:
CUSTOM_TEST_VAR: "test_value"
provisioner:
name: ansible
env:
ANSIBLE_FORCE_COLOR: "true"
ANSIBLE_VERBOSITY: "2"
config_options:
defaults:
callback_whitelist: profile_tasks, timer
inventory:
host_vars:
custom-test-instance:
custom_variable: "custom_value"
verifier:
name: testinfra
📊 Step 6: Performance and Coverage Testing¶
Performance Testing¶
# Run with timing information
ANSIBLE_CALLBACK_WHITELIST=profile_tasks molecule test
# Monitor resource usage during tests
htop # In another terminal while tests run
# Check container resource usage
podman stats
Test Coverage Analysis¶
# Run tests with coverage
pytest --cov=roles/ tests/
# Generate coverage report
pytest --cov=roles/ --cov-report=html tests/
# View coverage report
open htmlcov/index.html # or xdg-open on Linux
🔄 Step 7: Continuous Testing Workflow¶
Pre-Commit Testing¶
# Create pre-commit test script
cat > scripts/pre-commit-test.sh << 'EOF'
#!/bin/bash
set -e
echo "🧪 Running pre-commit tests..."
# Lint checks
echo "📝 Running ansible-lint..."
ansible-lint .
echo "📝 Running yamllint..."
yamllint .
# Quick Molecule test on changed roles
echo "🧪 Running Molecule tests on changed roles..."
CHANGED_ROLES=$(git diff --name-only HEAD~1 | grep "^roles/" | cut -d'/' -f2 | sort -u)
for role in $CHANGED_ROLES; do
if [ -d "roles/$role/molecule" ]; then
echo "Testing role: $role"
cd "roles/$role"
molecule test --scenario-name default
cd ../..
fi
done
echo "✅ Pre-commit tests completed!"
EOF
chmod +x scripts/pre-commit-test.sh
Automated Testing Setup¶
# Set up Git hooks for automatic testing
cat > .git/hooks/pre-push << 'EOF'
#!/bin/bash
echo "🚀 Running pre-push validation..."
source venv/bin/activate
source scripts/activate-molecule-env.sh
scripts/pre-commit-test.sh
EOF
chmod +x .git/hooks/pre-push
📋 Testing Best Practices¶
Test Organization¶
Unit Tests: Test individual tasks and functions
Integration Tests: Test role interactions
System Tests: Test complete collection functionality
Performance Tests: Validate performance requirements
Test Data Management¶
# Use consistent test data
mkdir -p tests/fixtures
cat > tests/fixtures/test-vars.yml << 'EOF'
test_kvm_host_ipaddr: "192.168.1.100"
test_admin_user: "testuser"
test_bridge_name: "testbr0"
EOF
Test Environment Isolation¶
# Use unique container names
export MOLECULE_EPHEMERAL_DIRECTORY=/tmp/molecule-$(date +%s)
# Clean up between tests
molecule destroy
podman system prune -f
🚨 Troubleshooting Test Issues¶
Common Test Failures¶
Problem: “Container creation failed” Solution:
# Check container runtime
podman info
systemctl --user status podman.socket
# Clean up stale containers
podman system prune -a -f
Problem: “Ansible connection failed” Solution:
# Check container is running
podman ps
# Test manual connection
podman exec -it CONTAINER_NAME /bin/bash
# Check Ansible inventory
molecule list --format yaml
Problem: “Role dependencies not found” Solution:
# Install dependencies
ansible-galaxy collection install -r requirements.yml
# Check role path
echo $ANSIBLE_ROLES_PATH
Debug Container Issues¶
# Start container manually for debugging
molecule create
molecule login
# Check container logs
podman logs CONTAINER_NAME
# Inspect container configuration
podman inspect CONTAINER_NAME
📈 Advanced Testing Techniques¶
Matrix Testing¶
# Test across multiple platforms
for platform in rhel8 rhel9 rhel10; do
molecule test --scenario-name $platform
done
Parallel Testing with Resource Limits¶
# Limit parallel tests to avoid resource exhaustion
export MOLECULE_PARALLEL=2
molecule test --parallel
Custom Verification Tests¶
Create custom testinfra tests in molecule/default/tests/
:
def test_service_running(host):
service = host.service("libvirtd")
assert service.is_running
assert service.is_enabled
def test_bridge_exists(host):
cmd = host.run("ip link show qubibr0")
assert cmd.rc == 0