Testing Ansible Roles Using Molecule

Martin Chrobot
The Startup
Published in
5 min readJul 20, 2020

Quick guide to show how easy it is to test Ansible roles using Molecule

Image from the Molecule GitHub repo

Why are we testing?

As we work on our Ansible roles we have an idea what we want the role to do and we test it throughout the development process. This is often manual and time consuming and often works fine…. initially. The problem is that one day someone else might make changes to your role and might accidentally break it without noticing it. When automated tests are in place, failing tests will alert the person making the change, to any breaking changes to the role.

What is Molecule?

Molecule is a tool designed to help with development and automated testing of Ansible roles. You can use it to test with multiple operating systems, virtualization providers, test scenarios etc. You can easily run your tests locally and in the cloud.

To get started you’ll need to have python, pip & virtualenv installed.

Setting up python venv & installing packages using pip

Go to the directory where you want to create your role and create a python virtual environment.

python3 -m venv env

The whole idea of python virtual environments is to create isolated environments for python projects where you can install packages and even test out multiple versions within the same project.

Activate the virtual environment to make sure all actions remain within this environment

source env/bin/activate

Once you activate an environment you should see the environment name in parentheses in your command line

(env) ➜  TestingAnsibleUsingMolecule git:(initial-dev) ✗

Installing Molecule and Docker using pip

pip install molecule docker

This will install both packages including any dependencies to the python environment

Creating the Ansible role

(env) ➜  TestingAnsibleUsingMolecule git:(initial-dev) ✗ molecule init role my-role           
--> Initializing new role my-role...
Initialized role in TestingAnsibleUsingMolecule/my-role successfully.

This has created the directory structure for our Ansible role

Change into the role directory

(env) ➜  TestingAnsibleUsingMolecule git:(initial-dev) ✗ cd my-role 
(env) ➜ my-role git:(initial-dev) ✗

Molecule magic

Run molecule test to make sure everything works as expected. This should run without any errors and the output should be similar to this:

(env) ➜  my-role git:(initial-dev) ✗ molecule test
--> Test matrix

└── default
├── dependency
├── lint
├── cleanup
├── destroy
├── syntax
├── create
├── prepare
├── converge
├── idempotence
├── side_effect
├── verify
├── cleanup
└── destroy

...

Because the role is empty and doesn’t really do anything the only thing that happens when we run molecule test is a docker container is spun up and the Example assertion test runs. If you open the molecule.yml file in molecule/default it looks like this

Here you can see that we’re using the docker driver & CentOS 7 image from pycontribs. You can change this to any image you’d like to use. We’re also using ansible as the verifier. This is different from molecule v2 where the default verifier was TestInfra

Lets add a simple task to our role which installs Nginx.

Open the main.yml file in the tasks directory and add the following task

Feel free to run molecule test to make sure the role runs without any errors. The play recap should look something like this

PLAY RECAP *********************************************************************
localhost : ok=2 changed=2 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

Now lets add a test to check if Nginx is installed

Open verify.yml in molecule/default and replace the current test with

All we’re doing here is

  • Get a list of all installed packages
  • Loop through the list of packages and check if they’re installed (nginx being the only thing in this case)

Now if you run molecule test the following happens

  • Docker container starts up
  • Updates are installed
  • Nginx is installed
  • Molecule tests run — in our case we only check to make sure nginx is installed on the container

If you look at the output from molecule test there’s a stage named Running Ansible Verifier. Here you can see what is being tested and if it passed or failed

--> Running Ansible Verifier

PLAY [Verify] ******************************************************************

TASK [Gathering Facts] *********************************************************
ok: [instance]

TASK [Gather package facts] ****************************************************
ok: [instance]

TASK [Verify Packages] *********************************************************
ok: [instance] => (item=nginx) => {
"ansible_loop_var": "item",
"changed": false,
"item": "nginx",
"msg": "All assertions passed"
}

PLAY RECAP *********************************************************************
instance : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

Verifier completed successfully.

Looking at the above output everything ran successfully. Great! Now let’s break the test to make sure it actually works.

Change nginx to my_imaginary_nginx in molecule/default/verify.yml

When you run molecule test you should now see an error message as our my_imaginary_nginx package isn’t installed

--> Running Ansible Verifier

PLAY [Verify] ******************************************************************

TASK [Gathering Facts] *********************************************************
ok: [instance]

TASK [Gather package facts] ****************************************************
ok: [instance]

TASK [Verify Packages] *********************************************************
failed: [instance] (item=my_imaginary_nginx) => {
"ansible_loop_var": "item",
"assertion": "'my_imaginary_nginx' in ansible_facts.packages",
"changed": false,
"evaluated_to": false,
"item": "my_imaginary_nginx",
"msg": "Assertion failed"
}

PLAY RECAP *********************************************************************
instance : ok=2 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0

ERROR:
An error occurred during the test sequence action: 'verify'. Cleaning up.

If any of your tests are failing, you can bring up the container by running molecule converge. This will only bring up the container. It won’t run any tests and the container will continue running. You can then run molecule verify to run the tests and easily jump onto it and troubleshoot anything that’s failing. Once you’re happy everything is as it should be you can run molecule test and then molecule destroy.

That’s all there is. Fairly straight forward. You can easily create tests using ansible and check for installed packages, services, files, directories etc.

Summary

In this tutorial we have created an Ansible role using Molecule, added a task to install nginx, added a test to make sure nginx is installed, and we’ve also proven that the test works by testing for an imaginary nginx package which wasn’t installed, and as expected, caused our test to fail.

Bonus — Systemd

If you require systemd you need to change the platform config in molecule/default/molecule.yml to

You can use the image from jrei/systemd-centos as an example or build your own.

P.S: If you are looking for a challenge, — Get in touch! We’re hiring!

--

--