ansible/ansible
Testing
ansible-core has its own test runner, ansible-test, packaged separately from the engine at test/lib/ansible_test/. It handles three flavors of tests — sanity, unit, integration — across Docker, Podman, virtualenv, and remote-host backends. This page is a tour.
ansible-test, in 60 seconds
bin/ansible-test is a symlink to test/lib/ansible_test/_util/target/cli/ansible_test_cli_stub.py. The stub bootstraps ansible_test from the test/lib/ package and dispatches to the real command (sanity, units, integration, coverage, etc.).
Common entry points:
ansible-test sanity # Lint + static analysis
ansible-test units # pytest-based unit tests
ansible-test integration # Real-world playbook tests
ansible-test coverage # Aggregate coverage across the above
ansible-test env # Print the current ansible-test environment
ansible-test windows-integration # Windows-only integration tests via WinRM
ansible-test network-integration # Network-platform testsAvailable containers are listed in test/lib/ansible_test/_data/completion/docker.txt. Use --docker default for sanity/units; pick a distro-specific container (ubuntu2204, ubuntu2404, fedora41, etc.) for integration.
Sanity tests
Sanity tests live under test/sanity/. They are not "tests" in the unit sense — they're lints, static analysis, and structural checks. The full set is reachable via:
ansible-test sanity --list-testsA non-exhaustive sample:
| Test | What it checks |
|---|---|
pep8 |
PEP-8 with the project's local relaxations (line limit 160, E402 ignored) |
pylint |
Custom pylint plugins under test/sanity/code-smell/ and a curated rule set |
mypy |
Static type-checking for the controller |
validate-modules |
Module documentation correctness and argument-spec validity |
import |
Each Python file is importable (no syntax errors, no missing deps in module_utils) |
no-smart-quotes |
Disallow Unicode smart quotes in source files |
runtime-metadata |
The redirect map in lib/ansible/config/ansible_builtin_runtime.yml is well-formed |
bin-symlinks |
bin/* symlinks all resolve correctly |
boilerplate |
Required from __future__ import annotations and license headers |
Run all of them, scoped to your changes:
ansible-test sanity -v --docker default <changed paths>Unit tests
Unit tests sit under test/units/, mirroring lib/ansible/:
test/units/cli/ ← tests for lib/ansible/cli/
test/units/executor/ ← tests for lib/ansible/executor/
test/units/plugins/ ← tests for lib/ansible/plugins/
test/units/modules/ ← tests for lib/ansible/modules/
test/units/playbook/ ← tests for lib/ansible/playbook/
test/units/parsing/ ← tests for lib/ansible/parsing/
test/units/galaxy/ ← tests for lib/ansible/galaxy/
test/units/inventory/ ← tests for lib/ansible/inventory/
test/units/template/ ← tests for the templating layer
test/units/utils/ ← tests for lib/ansible/utils/
test/units/vars/ ← tests for lib/ansible/vars/
test/units/regex/ ← regex-specific helpersThey use plain pytest. Per the AGENTS.md:
Unit tests should be pytest style, and functional rather than tightly coupled to mocking.
In other words: prefer testing real behavior with real objects where possible. Mocks should be at the I/O boundary (network, filesystem, subprocess) — not at every internal call.
Run a single file:
ansible-test units -v --docker default test/units/modules/test_command.pyWith coverage:
ansible-test units -v --docker default --coverageIntegration tests
Integration tests live under test/integration/targets/<name>/. Each target is a directory of playbooks and supporting files exercising one feature or module against a real (containerized) target.
The structure of a typical target:
test/integration/targets/foo/
├── aliases # Test categorization (controller-only? hidden?)
├── meta/
│ └── main.yml # role-style metadata
├── tasks/
│ └── main.yml # what the test actually does
├── files/
└── vars/The aliases file is small but important. It controls:
- Whether the target is run in CI by default (
disabledopts out). - Whether the test runs on the controller (
context/controller) or a separate target (context/target). - Resource needs (
needs/file/...,needs/target/...). - Distro filters (
skip/macos,skip/freebsd).
Run a target:
ansible-test integration -v --docker ubuntu2404 setup_remote_tmp_dirThe first invocation of --docker will pull or build the relevant image; subsequent runs reuse it.
Per
AGENTS.md: integration tests are required for almost all plugin changes because they exercise the public API. Unit tests alone are not sufficient for action plugin or module changes.
Test isolation
Three backends are available:
--docker— runs everything inside the chosen image. Most reliable, recommended.--podman— same as--dockerbut with Podman. Switch via--remote-stage/--remote-terminate.--venv— runs in a host-local virtualenv. Fallback when containers aren't available; prone to host-environment leaks for unit and integration tests.
For Windows integration:
ansible-test windows-integration -v --windows 2022For network platforms (cisco.ios, arista.eos, etc.) the tests live in those collections, but ansible-test network-integration can drive them.
Test-only support code
test/lib/ansible_test/ is a self-contained CLI of its own:
_internal/— sanity test plugins, dependency manifests, container management, results parsing._data/— payload files (sanity-test rule lists, requirements files for each Python version)._util/— helpers shipped to test environments (target-side scripts, controller bootstrapping).config/— example test configs.
test/support/ contains additional shared test infrastructure (helper roles, integration controller).
Cross-links
- Tooling for the CI pipeline that runs all of this.
- Patterns and conventions for the test-style rules.
- Debugging for what to do when a test fails locally.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.