Open-Source Wikis

/

Ansible

/

Plugins

/

Test plugins

ansible/ansible

Test plugins

Test plugins implement Jinja's {{ x is foo }} syntax. They answer boolean questions about a value.

Where they live

lib/ansible/plugins/test/
├── __init__.py
├── core.py        # Most built-in test implementations
├── files.py
├── mathstuff.py
├── uri.py
├── *.yml          # Per-test sidecar docs

Built-in tests include defined, undefined, none, truthy, falsy, match, search, regex, version, version_compare, succeeded, successful, failed, unreachable, skipped, changed, finished, started, string, mapping, sequence, iterable, directory, file, link, exists, abs, same_file, nan, contains, any, all, etc.

Tests vs. filters

Both run inside Jinja, but they're separate registries:

  • Filter: {{ x | foo }} — transforms a value.
  • Test: {{ x is foo }} — returns a boolean.

You can't use a filter where a test is expected and vice versa. The Jinja parser knows which is which based on syntax.

Common idioms

when: my_var is defined
when: my_var is not none
when: result is failed
when: result is changed
when: result is succeeded
when: ansible_distribution_version is version('22.04', '>=')
when: ip is match('^10\.')

The version test (lib/ansible/plugins/test/core.py:version_compare) is one of the most useful — it interprets both strings as packaging.version.Version and supports operators <, <=, ==, >=, >, !=, plus loose mode.

Writing a test

def is_even(value):
    return value % 2 == 0

class TestModule:
    def tests(self):
        return {
            'even': is_even,
        }

The function returns a bool. The TestModule class with a tests() dict is the legacy form; the modern form uses sidecar YAML files alongside Python implementations, just like filters.

Result-introspection tests

Several tests look at the structured result dict that comes back from a task. succeeded, failed, unreachable, skipped, changed, finished, started all check the standard result fields:

def succeeded(result):
    if isinstance(result, Mapping):
        return result.get('failed', False) is False and 'msg' not in result.get('skipped_reason', '')
    return False

These are designed to work with register: results:

- name: do something
  command: foo
  register: result

- name: react
  debug: msg="it changed"
  when: result is changed

Integration points

  • Imported by: lib/ansible/_internal/_templating/_jinja_plugins.py for binding into Jinja.
  • Loaded by: test_loader in lib/ansible/plugins/loader.py.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Test plugins – Ansible wiki | Factory