Automated Ansible testing with Molecule

Infrastructure testing provides some challenges just because of the mere fact you are building machines and not just compiling code. To test Ansible, I used to run Ansible with –syntax-check and –list-tasks. For roles I would run local tests with Vagrant using the tests/ directory in the role. The tests had Ansible test itself with the uri module or other checks. This is ok for simple checks but can be cumbersome and time consuming as it doesn’t catch everything.

Molecule has made this very simple. Install Molecule with pip install molecule. Create your role with molecule init --role-name role --driver-name driver. The current drivers are Docker, OpenStack, Vagrant, EC2, GCE, LXC, LXD, and a few others with Docker being the default. It’s not absolutely required to build the role with molecule init but it adds the molecule dir with default testing and the .yamllint file.

Rather than rewrite their documentation, I’ll just go through what I have set up to test my roles. Currently I’m using the Vagrant driver with a CentOS 7 box ( I don’t do much with non RHEL distros) and the libvirt provider for Vagrant. So here’s what my molecule/molecule.yml file looks like:

  name: galaxy
  name: vagrant
    name: libvirt
  name: yamllint
  - name: bind
    box: centos/7
  name: ansible
    name: ansible-lint
  name: default
  name: testinfra
    sudo: True
    name: flake8

Molecule also uses testinfra to run automated tests against the Vagrant box. Here’s a simple example to check a firewalld role:

import os

import testinfra.utils.ansible_runner

testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(

def test_firewall_installed(host):
    package = host.package("firewalld")
    assert package.is_installed

def test_firewall_service(host):
    service = host.service("firewalld")
    assert service.is_running
    assert service.is_enabled

def test_firewall_config(host):
    config = host.file("/etc/firewalld/zones/public.xml")
    assert config.exists
    assert config.contains('<service name="http"/>')
    assert config.contains('<service name="https"/>')
    assert config.contains('<service name="ssh"/>')

Testinfra will check that the package firewalld is installed, the service is running and enabled, and that the /etc/firewalld/zones/public.xml file contains the services defined.

To start your molecule testing you can run molecule test.

Here’s a video running this setup against a firewalld role: