I have created a GitHub repository that contains a working example on our organisations account. If you wish to see all of the code when following through this post then go to GitHub and checkout the repository https://github.com/Chorograph/ansible-role-molecule-example
If you would like to understand more about TestInfra and how run tests before you start reading through this post then read our post https://chorograph.com/running-tests-on-infrastructure-using-testinfra
Molecule is a python package so we can install it using pip. In the example below we create a python virtual environment called
molecule-venv, we source the activate file to enable the virtual environment and then we install molecule and testinfra packages using pip. If you do not want to use a virtual environment then just run the pip commands however we recommend using a virtual environment because it keeps package management easy and clean.
$ python3 -m venv molecule-venv $ source molecule-venv/bin/activate (molecule-venv) $ pip install testinfra (molecule-venv) $ pip install molecule (molecule-venv) $ pip install docker
Now we have installed the packages we can test that they are installed using
pip list and
Jamess-MBP:ansible-role-molecule-example jamesalford$ pip list|egrep "molecule|testinfra|docker" docker 4.2.0 molecule 3.0.2 testinfra 3.4.0 (molecule-venv) Jamess-MBP:molecule jamesalford$ molecule --version molecule 3.0.2 ansible==2.9.5 python==3.7
To initialize a new ansible role with molecule, we use the
molecule init role command and can pass in variables for the driver, verifier and the role name. In this scenario we use docker to build a container where we can run the ansible role and then run our tests.
(molecule-venv) Jamess-MBP:molecule jamesalford$ molecule init role --driver-name docker --verifier-name testinfra jamesalford.ansible-role-molecule-example --> Initializing new role jamesalford.ansible-role-molecule-example... Initialized role in /private/tmp/molecule/jamesalford.ansible-role-molecule-example successfully.
The command builds an ansible role, the main difference to a normal ansible role is the molecule folder that contains another folder called default. Molecule uses
ansible-galaxy much like you would when generating a role to make the normal ansible role files/folders and then injects the molecule folder and its contents. The folder under molecule called default is the name of the test scenario and the default one is already created for us.
(molecule-venv) Jamess-MBP:molecule jamesalford$ ls jamesalford.ansible-role-molecule-example/molecule/default/ INSTALL.rst converge.yml molecule.yml tests
Once molecule is configured to run you can simply run
molecule test from the ansible role directory to execute a test. When you run the test, molecule will output the test matrix which shows the test scenarios and the tests that will be run under each scenario.
(molecule-venv) Jamess-MBP:ansible-role-molecule-example jamesalford$ molecule test --> Test matrix └── default ├── dependency ├── lint ├── cleanup ├── destroy ├── syntax ├── create ├── prepare ├── converge ├── idempotence ├── side_effect ├── verify ├── cleanup └── destroy --> Scenario: 'default' --> Action: 'dependency' Skipping, missing the requirements file. --> Scenario: 'default' --> Action: 'lint' ...
When building a new role as we have done in the steps above, linting is not enabled so we need to enable it.
In earlier versions of molecule there were multiple places that you could specify linting which included a lint option on the provisioner and the verifier however it has since been adjusted to take one command under the main lint section in the yaml file
molecule.yml. If we include the code below then we will perform yamllint, ansible-lint and python linting on the files in the role.
lint: | set -e yamllint . ansible-lint flake8
molecule.yml file, the scenario can be defined. Once defined, you can adjust the test sequence order or remove steps by removing or commenting out the line. You may wish to do this if there is a role that you know will fail a certain type of check such as lint or idempotence and wish to not test that.
scenario: name: default test_sequence: - lint - destroy - dependency - syntax - create - prepare - converge - idempotence - side_effect - verify - destroy
molecule/default folder there is a folder called
tests, this is where the test cases for TestInfra are stored. The default test file is called
test_default.py but any files in this folder that start with
test_ and end with python extention
.py will get executed as shown in below snippet.
--> Executing Testinfra tests found in /private/tmp/molecule/jamesalford.ansible-role-molecule-example/molecule/default/tests/... ============================= test session starts ============================== platform darwin -- Python 3.7.3, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 rootdir: /private/tmp/molecule/jamesalford.ansible-role-molecule-example/molecule/default plugins: testinfra-4.1.0 collected 4 items tests/test_default.py .. [ 50%] tests/test_2.py .. [100%] ============================== 4 passed in 3.71s =============================== Verifier completed successfully.
Tests are defined inside each file and TestInfra will look through these test files and will try to find the tests to run. It is expected that there is a function per test case however you can run the same test case with multiple values using parameterize. So if you wanted to test a batch of ports are open, you would write a test that takes a variable of port number and then pass in an array of ports to test. TestInfra would then run one test per parameter.
If you wish to see how using arrays and tuples can help you run the same test with multiple values then please checkout my other post https://chorograph.com/running-tests-on-infrastructure-using-testinfra under the ‘Using variables in tests’ section
If you didn’t check it out already and you would like to see a working example of molecule then please clone our example repo from GitHub and have a look. https://github.com/Chorograph/ansible-role-molecule-example
Once checked out, run
molecule test inside the role directory and watch molecule execute the tests