How do you test Ansible playbooks with Molecule and ansible-lint?
Quick Answer
Ansible playbooks are tested in layers: ansible-lint catches style and syntax issues without running anything, Molecule tests roles against real or containerized instances, and --check/--diff mode previews changes on live infrastructure.
Detailed Answer
Think of testing Ansible playbooks like quality control in a car factory. Ansible-lint is the blueprint reviewer who catches design errors before a single part is built -- wrong bolt sizes, missing safety features, non-standard parts. Molecule is the test track where a fully assembled car is driven through real-world conditions -- acceleration, braking, cornering -- to make sure everything works together. And --check mode is the final inspection where a trained eye looks at the production car and notes what would need fixing, without actually turning any wrenches.
Ansible-lint is a static analysis tool that scans playbooks, roles, and task files for best-practice violations, outdated syntax, and common mistakes without running anything. It flags issues like using the command module when a purpose-built module exists, missing name attributes on tasks, using bare variables in conditions, bad YAML formatting, and risky file permissions. It is usually the first check in a CI pipeline -- fast, needs no infrastructure, and catches the most obvious problems. You can customize its rules through a .ansible-lint config file and even write custom rules for your organization's standards.
Molecule is the full integration testing framework for Ansible roles. It creates temporary test instances (using Docker, Vagrant, Podman, or cloud providers), runs your role against those instances, checks the results, and then tears everything down. The typical Molecule lifecycle is: create (spin up test instances), converge (apply the role), idempotence (run the role again to verify nothing changes), verify (run assertions to check the result), and destroy (clean up). Each phase can be customized in the molecule.yml config. Molecule scenarios let you test the same role under different conditions -- different operating systems, different variable combinations, or different dependency setups.
In production CI/CD pipelines, teams run these tools in layers. The first stage runs ansible-lint and yamllint for fast feedback -- these finish in seconds and catch syntax errors and style issues. The second stage runs Molecule tests against Docker containers for each role individually -- these take minutes and verify the role actually works. The third stage runs playbooks against staging environments in --check --diff mode to preview what changes would hit real infrastructure. Some teams add a fourth stage using --syntax-check as a pre-commit hook for instant developer feedback. The whole pipeline lives in version control and runs on every pull request.
A common mistake is assuming Molecule Docker tests perfectly match production behavior. Docker containers do not run systemd by default, so service-related tasks may behave differently than on real VMs. You can work around this with special systemd-enabled container images, but it adds complexity. Another pitfall is leaning too hard on ansible-lint while skipping integration tests -- lint catches style issues but cannot verify that your template generates valid nginx configuration or that your database migration actually runs. Also, watch out for flaky Molecule tests caused by network issues during package installation in containers; use local package caches or mock repositories for reliable CI runs.