This guide shows you how to run Molecule tests locally to validate your changes before submitting pull requests.
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
- Completed Set Up Development Environment
- Container runtime (Podman/Docker) configured
- Molecule and dependencies installed
- Basic understanding of Ansible roles
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 testingMolecule 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
# 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# 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)"# 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 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# 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# 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# 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# 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# 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# Navigate to role directory
cd roles/kvmhost_base
# Create new scenario
molecule init scenario custom-test
# Edit scenario configuration
vim molecule/custom-test/molecule.ymldependency:
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# 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# 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# 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# 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- Unit Tests: Test individual tasks and functions
- Integration Tests: Test role interactions
- System Tests: Test complete collection functionality
- Performance Tests: Validate performance requirements
# 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# Use unique container names
export MOLECULE_EPHEMERAL_DIRECTORY=/tmp/molecule-$(date +%s)
# Clean up between tests
molecule destroy
podman system prune -fProblem: "Container creation failed" Solution:
# Check container runtime
podman info
systemctl --user status podman.socket
# Clean up stale containers
podman system prune -a -fProblem: "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 yamlProblem: "Role dependencies not found" Solution:
# Install dependencies
ansible-galaxy collection install -r requirements.yml
# Check role path
echo $ANSIBLE_ROLES_PATH# Start container manually for debugging
molecule create
molecule login
# Check container logs
podman logs CONTAINER_NAME
# Inspect container configuration
podman inspect CONTAINER_NAME# Test across multiple platforms
for platform in rhel8 rhel9 rhel10; do
molecule test --scenario-name $platform
done# Limit parallel tests to avoid resource exhaustion
export MOLECULE_PARALLEL=2
molecule test --parallelCreate 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- Previous: Set Up Development Environment
- Next: Contributing Guidelines
- Reference: Testing Configuration
- Explanation: Testing Framework Selection
This guide covered comprehensive Molecule testing. For contributing your tested changes, see the contributing guidelines. For understanding the testing architecture, check the explanations section.