
Un rôle publié doit fonctionner sur plusieurs versions d'ansible-core (votre utilisateur peut être en 2.16, vous développez en 2.18). tox automatise les tests sur la matrice de versions : tox lance molecule test dans un environnement Python isolé pour chaque version d'Ansible.
Cette page utilise un tox.ini classique (sans le plugin tox-ansible), pattern stable, lisible, et utilisé sur les rôles de production.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Écrire un
tox.iniclassique pour rôle Ansible. - Définir une matrice de versions ansible-core (
envlist = ansible-2.{16,17,18}). - Configurer Python par version d'Ansible.
- Ajouter un env
lintséparé pour fail-fast. - Lancer
toxcomplet ou un environnement ciblé.
Prérequis
Section intitulée « Prérequis »toxinstallé :pipx install tox.- Molecule + Podman opérationnels.
- Avoir un rôle avec un scénario Molecule fonctionnel.
Structure tox.ini
Section intitulée « Structure tox.ini »Le fichier se place à la racine du rôle, à côté de meta/ et de
molecule/. Il déclare quatre environnements : trois pour les versions
d'ansible-core visées, un pour le lint. Ce dernier n'apparaît pas dans
envlist, il ne s'exécute donc que si vous l'appelez explicitement. Les blocs
[testenv:ansible-2.X] héritent de [testenv] et n'y ajoutent que ce qui
change : le Python de base et les dépendances épinglées.
; tox.ini : pattern classique multi-versions ansible-core[tox]envlist = ansible-2.{16,17,18}skipsdist = true
[testenv]commands = molecule testsetenv = TOX_ENVNAME={envname} PY_COLORS=1 ANSIBLE_FORCE_COLOR=1 ANSIBLE_ROLES_PATH=../passenv = *
[testenv:ansible-2.16]basepython = python3.10deps = ansible-core==2.16.* ansible-lint==24.* molecule>=25.0 molecule-plugins[podman]>=25.0 requests pytest
[testenv:ansible-2.17]basepython = python3.10deps = ansible-core==2.17.* ansible-lint==24.* molecule>=25.0 molecule-plugins[podman]>=25.0 requests pytest
[testenv:ansible-2.18]basepython = python3.12deps = ansible-core==2.18.* ansible-lint==25.* molecule>=26.0 molecule-plugins[podman]>=25.0 requests pytest
; Lint séparé, fail-fast (s'exécute en premier, isolé)[testenv:lint]basepython = python3.12deps = ansible-lint==25.* yamllintcommands = yamllint roles/ ansible-lint --profile=production roles/Anatomie
Section intitulée « Anatomie »Les trois sections ci-dessous se lisent dans l'ordre où tox les applique :
d'abord la matrice globale, puis la configuration partagée, enfin les
surcharges propres à chaque version. Comprendre cet héritage évite de répéter
inutilement commands et setenv dans chaque bloc.
[tox], section globale
Section intitulée « [tox], section globale »C'est ici que se décide quels environnements tournent quand vous lancez
tox sans argument.
envlist = ansible-2.{16,17,18}skipsdist = trueenvlist= matrice. La syntaxe2.{16,17,18}génère 3 environnements :ansible-2.16,ansible-2.17,ansible-2.18.skipsdist = true= pas de package Python à distribuer (un rôle n'a pas desetup.py).
[testenv], config commune
Section intitulée « [testenv], config commune »Tout ce qui est déclaré ici s'applique aux trois environnements de la matrice, sans avoir à le recopier.
commands = molecule testsetenv = ANSIBLE_ROLES_PATH=../passenv = *commands: ce qui s'exécute (molecule testpour le cycle complet).setenv: variables d'env exposées à Ansible.passenv = *: laisse passer toutes les variables d'env (utile pour tokens, etc.).
[testenv:ansible-2.X], par version
Section intitulée « [testenv:ansible-2.X], par version »Un bloc par version, dont le nom doit correspondre exactement à celui généré
par envlist. C'est le seul endroit où l'on épingle ansible-core.
basepython = python3.10deps = ansible-core==2.16.* molecule>=25.0basepython: version Python compatible avec ansible-core ciblée. Ansible 2.16 exige Python 3.10+, Ansible 2.18 exige 3.12+.deps: pinning des versions exactes.
Lancer les tests
Section intitulée « Lancer les tests »tox crée un environnement virtuel Python par environnement déclaré, y
installe les dépendances, puis exécute commands. Ces venv sont conservés dans
.tox/ entre deux exécutions, ce qui rend le premier lancement long et les
suivants beaucoup plus rapides. Les trois formes ci-dessous couvrent le
quotidien : matrice complète, version unique, lint isolé.
Complet, toutes les versions
Section intitulée « Complet, toutes les versions »Les environnements s'exécutent séquentiellement ; comptez le temps d'un
molecule test multiplié par trois.
toxTox crée 3 environnements virtuels Python, installe les deps, lance molecule test dans chacun.
Une seule version
Section intitulée « Une seule version »Le nom passé à -e est celui d'une section [testenv:...], pas un numéro de
version d'Ansible.
tox -e ansible-2.18Cible une version spécifique, utile en dev.
Lint seul (fail-fast)
Section intitulée « Lint seul (fail-fast) »L'environnement lint ne figure pas dans envlist : il ne tourne jamais lors
d'un tox sans argument, il faut l'appeler.
tox -e lintLance ansible-lint --profile=production + yamllint. À mettre en premier dans une CI (s'il échoue, pas la peine de lancer Molecule).
Pattern CI/CD typique
Section intitulée « Pattern CI/CD typique »L'ordre compte : le lint dure quelques secondes là où la matrice complète
prend plusieurs minutes, autant échouer tôt. Attention, l'environnement
publish de la troisième étape n'existe pas dans le tox.ini présenté plus
haut ; il faut lui ajouter une section [testenv:publish] avec la commande
ansible-galaxy de votre choix, sinon tox s'arrête sur un environnement
inconnu.
# Étape 1 : lint (rapide)tox -e lint
# Étape 2 : matrice complètetox
# Étape 3 (sur tag Git) : publication Galaxytox -e publishComparaison avec d'autres outils
Section intitulée « Comparaison avec d'autres outils »Le critère de choix n'est pas la richesse fonctionnelle mais le type
d'artefact que vous publiez. Un rôle standalone n'a ni tests de sanity ni
tests unitaires à orchestrer, ce qui rend le tox.ini classique suffisant. Une
collection change la donne et justifie tox-ansible. La dernière ligne
n'est pas une alternative : la matrice GitHub Actions pilote les jobs, tox
reste ce qui tourne à l'intérieur de chacun.
| Outil | Périmètre | Recommandation 2026 |
|---|---|---|
tox classique | Rôles standalone | ✅ Recommandé |
tox-ansible | Collections Ansible | Quand vous publiez une collection |
nox | Alternative Python à tox | Utilisable mais moins courant en Ansible |
| GitHub Actions matrix | CI/CD natif | Complémentaire (voir page CI) |
Mettre en pratique
Section intitulée « Mettre en pratique »Un rôle qui passe sur une seule version d'Ansible ne dit rien de son comportement sur les autres. Le lab vous fait écrire un tox.ini qui épingle une version d'ansible-core par environnement, associe à chacun le basepython compatible, et lance molecule test sur toute la matrice en une seule commande. La validation relit envlist, les dépendances de chaque environnement et la présence d'un environnement lint séparé.
Pièges courants
Section intitulée « Pièges courants »Les deux premiers symptômes viennent du même point : basepython désigne un
interpréteur qui doit exister sur la machine, tox ne l'installe pas. Deux
autres lignes portent sur la durée d'exécution, principal frein à
l'adoption d'une matrice en local, et la dernière sur les variables
d'environnement absentes du runner de CI. Repérez votre message d'erreur dans
la colonne de gauche, la correction se trouve à droite.
| Symptôme | Cause | Fix |
|---|---|---|
Python 3.10 not found | basepython absent du système | Installer Python 3.10 ou utiliser pyenv |
ansible-core 2.16 incompatible avec Python 3.13 | Trop récent | Utiliser Python 3.10 pour Ansible 2.16/2.17 |
| Lent à chaque run | tox recrée les venv | Utiliser tox -r (recreate) seulement si deps changent |
| Tests passent locallement mais ratent en CI | Variables d'env manquantes | Ajouter passenv = * ou lister les vars critiques |
molecule test lent en local | Container recreate à chaque env | Cycle dev : molecule converge puis molecule verify |
À retenir
Section intitulée « À retenir »tox.iniclassique >tox-ansiblepour rôles standalone.envlist = ansible-2.{16,17,18}= matrice de versions.basepythonpar version d'Ansible (2.16 → 3.10, 2.18 → 3.12).- Env
lintséparé pour fail-fast en CI. tox -e <env>pour cibler une version en dev.
Pour aller plus loin
Section intitulée « Pour aller plus loin »- CI GitHub Actions : porter la matrice tox dans un workflow, avec des permissions minimales.
- CI GitLab : la même matrice en
parallel:matrix, avec release automatique sur tag. - Versionner et publier : l'étape qui suit une matrice verte : tag semver, changelog, publication.