Testing and running Ansible at scale: ansible-lint, Molecule and AWX
In short: Before automation touches production, lint it, syntax-check it, test roles with Molecule and preview changes in check mode. At scale, run playbooks from AWX or automation controller so credentials are protected, access is role based and every job is logged.
Why testing automation matters
A playbook that runs against 300 switches deserves at least as much testing as a manual change on one. Testing Ansible is about catching problems at the cheapest point: style and syntax errors on your laptop, logic errors in a disposable lab, and unexpected changes in a dry run, before the real deployment.
Linting and static checks
pip install ansible-lint yamllint
yamllint .
ansible-lint # checks against best-practice rules
ansible-playbook site.yml --syntax-check
ansible-lint flags issues such as missing task names, short module names instead of FQCNs, use of command where a module exists, risky file permissions and tasks that are not idempotent. You can choose a profile (for example production) in .ansible-lint to set how strict it is.
Molecule and check mode
Molecule tests roles by creating a temporary instance, usually a container, applying the role, running it a second time to confirm idempotency, verifying the result and destroying the instance.
pip install molecule molecule-plugins[docker]
cd roles/base_linux
molecule init scenario default --driver-name docker
molecule test # create, converge, idempotence, verify, destroy
Molecule works best for Linux server roles. For network roles, teams often test against virtual devices in a lab built with Containerlab or vendor virtual images, or use the rendered state of resource modules to compare generated commands with expected output. Before production runs, --check --diff --limit on a small group is the final preview. Remember that check mode depends on module support and cannot predict everything, for example the result of a task that needs a previous change to have happened.
A CI pipeline
# .gitlab-ci.yml (simplified)
stages: [lint, test]
lint:
stage: lint
image: python:3.12
script:
- pip install ansible-core ansible-lint yamllint
- yamllint .
- ansible-lint
molecule:
stage: test
script:
- pip install molecule molecule-plugins[docker] ansible-core
- cd roles/base_linux && molecule test
Running these checks on every merge request means reviewers see test results before approving, and the main branch stays deployable.
Running at scale with AWX or automation controller
AWX is the open-source upstream project; automation controller is the supported version within Red Hat Ansible Automation Platform. Both provide a web interface and REST API in front of Ansible. A job template combines a project (playbooks from Git), an inventory, credentials and an execution environment. Helpdesk staff can be allowed to run "Bounce access port" without ever seeing the device password, and every run is logged with who started it and what changed.
Jobs run inside execution environments: container images holding ansible-core, collections and Python dependencies. You build them with ansible-builder and test them locally with ansible-navigator, so the same versions run on your laptop, in CI and in the controller.
| Need | Controller feature |
|---|---|
| Stop secrets leaking to users | Credentials with encrypted storage |
| Let juniors run approved jobs only | Role-based access control on job templates |
| Chain backup, change and verify | Workflow templates with approval nodes |
| Nightly compliance checks | Schedules and notifications |
Tip: you can run AWX in a home lab on a small Kubernetes cluster using the AWX Operator, which is good practice for interviews that mention Ansible Automation Platform.
Practice
What does Molecule check that a single playbook run does not?
Why use execution environments?
How does a controller let helpdesk staff run a job without knowing device passwords?
Key takeaways
- Catch errors early with yamllint, ansible-lint and --syntax-check.
- Use Molecule to test roles and prove idempotency.
- Preview real changes with --check --diff on a limited group.
- Run lint and tests in CI on every merge request.
- Use AWX or automation controller for credentials, RBAC, scheduling and audit.
Original content written by Mohamed Fayas for FM TecHub. © 2026 FM TecHub. You're welcome to share a link to this page; please don't copy the text elsewhere without permission.