Test Runner¶
perfshop-test-runner est le container d'exécution où tous les tests Robot Framework et pytest tournent réellement. C'est une image custom buildée localement à partir du Dockerfile dans test-runner/ — elle n'est pas pullable depuis un registry public.
Son rôle unique : recevoir des scripts Python (pytest) ou Robot Framework par deux canaux distincts (SSH pour Squash Orchestrator, docker exec pour Scripts UI), les exécuter en pilotant Selenium, et produire des artefacts (logs, rapports) lisibles par les autres services de la stack.
Source de vérité
Cette page est tirée du fichier test-runner/Dockerfile, du bloc perfshop-test-runner dans les fichiers compose, et de test-runner/docker-entrypoint.sh.
Dockerfile custom¶
Base et dépendances système¶
FROM python:3.11-slim
RUN apt-get update && apt-get install -y --no-install-recommends \
openssh-server \
git \
&& rm -rf /var/lib/apt/lists/*
Trois paquets système uniquement :
| Paquet | Usage |
|---|---|
python:3.11-slim (base) |
Runtime Python et pip |
openssh-server |
Permet à Squash Orchestrator de se connecter via SSH |
git |
Nécessaire pour squash-tf-services qui peut cloner des dépôts SCM |
Pas de navigateur local dans le container — Selenium tourne dans perfshop-selenium, le test-runner est client WebDriver uniquement.
Dépendances Python — deux profils pédagogiques¶
RUN pip install --no-cache-dir \
robotframework==7.0 \
robotframework-seleniumlibrary==6.3.0 \
robotframework-requests==0.9.6 \
robotframework-jsonlibrary==0.5 \
pytest==8.0 \
selenium==4.18.1 \
requests==2.31.0 \
allure-robotframework \
squash-tf-services
Le commentaire du Dockerfile est explicite : « Dépendances QA — deux profils d'étudiants. Profil débutant : robotframework + SeleniumLibrary + RequestsLibrary + JsonLibrary. Profil avancé : pytest + selenium ».
| Profil | Librairies | Usage typique |
|---|---|---|
| Débutant | Robot Framework 7.0 + SeleniumLibrary 6.3.0 + RequestsLibrary 0.9.6 + JsonLibrary 0.5 | Tests rédigés en syntaxe mot-clé (table-driven), facile à lire sans expérience Python |
| Avancé | pytest 8.0 + selenium 4.18.1 + requests 2.31.0 | Tests rédigés en Python, fixtures, paramétrisation, contrôle fin |
Les deux profils cohabitent dans le même container — rien n'empêche un étudiant de commencer par Robot Framework puis de migrer progressivement vers pytest à mesure qu'il monte en compétence.
Deux dépendances complémentaires :
allure-robotframework: génère des rapports Allure à partir des résultats Robot Framework — peut être utilisé par les étudiants qui veulent expérimenter un reporting visuel alternatif.squash-tf-services: services côté client nécessaires pour que le test-runner soit compatible avec l'orchestration Squash TF (clone SCM automatique, retour structuré des résultats).
Versions verrouillées¶
Toutes les versions sont pinnées dans le Dockerfile. C'est volontaire — la reproductibilité est essentielle pour l'usage pédagogique : un étudiant qui apprend avec RF 7.0 doit retrouver exactement le même comportement le lendemain, et un formateur doit pouvoir se fier aux comportements documentés.
Configuration OpenSSH¶
RUN mkdir -p /var/run/sshd && \
echo 'root:perfshop' | chpasswd && \
sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config && \
sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config
Trois modifications :
| Action | Effet |
|---|---|
echo 'root:perfshop' \| chpasswd |
Définit le mot de passe root à perfshop (pour l'orchestrateur) |
PermitRootLogin yes |
Autorise le login SSH direct en root |
PasswordAuthentication yes |
Autorise l'authentification par mot de passe (par défaut désactivée sur les images Debian récentes) |
Accès root par mot de passe — cadre strictement pédagogique
Le commentaire du Dockerfile est explicite : « Accès root avec password "perfshop" — usage pédagogique uniquement. Le container n'est pas exposé vers l'extérieur (réseau Docker interne) ». Dans un déploiement production réel (même interne), il faudrait basculer sur l'authentification par clé SSH et créer un utilisateur dédié non-root. Pour PerfShop, cette configuration est acceptable parce que le container n'expose aucun port à l'hôte (le 22 est interne), et que l'objectif est pédagogique.
Entrypoint et propagation des variables¶
COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
Le commentaire du Dockerfile explique : « sshd n'hérite pas des variables Docker. docker-entrypoint.sh écrit /etc/environment au démarrage pour que robot et pytest les voient dans les sessions SSH lancées par l'orchestrateur ».
C'est un piège classique de l'intégration SSH dans un container Docker : quand sshd accepte une connexion entrante et forke un shell, ce shell n'hérite pas des variables d'environnement positionnées par Docker Compose (elles sont uniquement dans le process PID 1). L'entrypoint contourne ce problème en écrivant toutes les variables utiles dans /etc/environment, qui est lu par pam_env à chaque login.
Concrètement, les variables SELENIUM_REMOTE_URL, PERFSHOP_FRONTEND_INTERNAL, PUBLIC_API_URL, PERFSHOP_LANG sont ainsi disponibles à la fois dans une session docker exec et dans une session SSH — garantissant un comportement cohérent entre les deux canaux d'exécution.
Le service dans le compose¶
perfshop-test-runner:
image: perfshop-test-runner:latest
build:
context: ./test-runner
dockerfile: Dockerfile
container_name: perfshop-test-runner
environment:
- SELENIUM_REMOTE_URL=http://perfshop-selenium:4444/wd/hub
- PERFSHOP_FRONTEND_INTERNAL=${PERFSHOP_FRONTEND_INTERNAL:-http://perfshop-frontend:80}
- PUBLIC_API_URL=${PUBLIC_API_URL:-http://localhost:8080}
- PERFSHOP_LANG=${PERFSHOP_LANG:-fr}
volumes:
- ./test-runner/scripts:/scripts
- ./test-runner/logs:/rf-logs
entrypoint: ["/usr/local/bin/docker-entrypoint.sh"]
command: ["/usr/sbin/sshd", "-D", "-e"]
Commande et entrypoint¶
L'entrypoint écrit /etc/environment puis lance /usr/sbin/sshd -D -e :
| Flag | Effet |
|---|---|
-D |
Daemon mode — reste en foreground (obligatoire pour que le container ne se termine pas) |
-e |
Logs sur stderr (au lieu de syslog) — capturés par Docker et donc par Promtail / Vector |
Le container ne fait rien d'autre que tourner sshd et attendre des connexions (SSH ou docker exec). C'est le même principe que perfshop-jmeter qui tourne tail -f /dev/null en attendant des tirs — le container n'a pas de « service métier » propre, il sert uniquement de substrat d'exécution.
Variables d'environnement propagées¶
| Variable | Rôle | Visibilité |
|---|---|---|
SELENIUM_REMOTE_URL |
URL du hub WebDriver | Utilisée par Robot Framework et pytest pour ouvrir un navigateur distant |
PERFSHOP_FRONTEND_INTERNAL |
URL interne du frontend | Les tests naviguent vers http://perfshop-frontend:80 (DNS Docker) |
PUBLIC_API_URL |
URL publique du backend | Utile si un test fait des assertions sur une URL canonique |
PERFSHOP_LANG |
Langue courante | Permet à un test de choisir les bons sélecteurs i18n (FR ou EN) |
Volumes¶
| Volume | Montage | Rôle |
|---|---|---|
./test-runner/scripts (bind mount) |
/scripts |
Scripts de test partagés — volume lu par le test-runner (exécution) et écrit par Forgejo-seed (push initial des scripts dans le dépôt Git) |
./test-runner/logs (bind mount) |
/rf-logs |
Logs et rapports — écrits par Robot Framework et pytest à chaque exécution, lus par Promtail (Loki) et Vector (OpenSearch) |
Le WORKDIR du Dockerfile est /scripts, donc toute exécution docker exec ou SSH démarre directement dans le dossier des scripts.
Les deux modes d'exécution¶
Mode 1 — docker exec depuis Scripts UI¶
sequenceDiagram
autonumber
participant SUI as perfshop-scripts-ui<br/>(Node.js)
participant SOCK as /var/run/docker.sock
participant TR as perfshop-test-runner
participant SEL as perfshop-selenium
SUI->>SOCK: POST /containers/perfshop-test-runner/exec<br/>{cmd: ["robot", "--outputdir", "/rf-logs/...", "login.robot"]}
SOCK->>TR: exec dans /scripts
TR->>TR: Lit variables depuis /etc/environment
TR->>SEL: POST /wd/hub/session
SEL-->>TR: Session Chrome
TR->>SEL: Commands WebDriver
TR->>TR: Écrit log.html, report.html, output.xml dans /rf-logs/
TR-->>SUI: Exit code + stdout
Avantages : - Pas de credentials à gérer côté Scripts UI (utilise le socket Docker) - Rapide et léger
Mode 2 — SSH depuis Squash Orchestrator¶
sequenceDiagram
autonumber
participant ORCH as perfshop-orchestrator
participant TR as perfshop-test-runner (sshd)
participant SEL as perfshop-selenium
ORCH->>TR: SSH root@perfshop-test-runner<br/>(password perfshop)
TR->>TR: pam_env lit /etc/environment
ORCH->>TR: SCP script.robot → /scripts/tmp/
ORCH->>TR: exec "robot --outputdir /rf-logs/... script.robot"
TR->>SEL: POST /wd/hub/session
SEL-->>TR: Session Chrome
TR->>TR: Exécute le test
TR-->>ORCH: Exit code + output.xml
ORCH-->>ORCH: Parse output.xml et retourne à Squash TM
Avantages :
- Compatible avec l'architecture distribuée Squash TF (le runner pourrait théoriquement être sur une autre machine)
- Format de résultats structuré (output.xml) directement parsable par Squash TM
Pas d'exposition de ports¶
Le container n'expose aucun port à l'hôte. Le port 22 est uniquement accessible depuis le réseau Docker interne — l'orchestrateur s'y connecte via perfshop-test-runner:22. Aucun utilisateur externe ne peut atteindre sshd.
Logs collectés par deux pipelines¶
Les fichiers écrits dans /rf-logs/ sont collectés simultanément par Promtail et Vector :
- Promtail → Loki : le job
rf-runner-logde Promtail tail les fichiers/rf-logs/*.log(voir../observability/loki.md) - Vector → OpenSearch : Vector collecte les logs du container
perfshop-test-runnervia son Docker source (sortie stdout + stderr du sshd)
Ces deux flux sont complémentaires : - Loki est optimal pour « chercher toutes les exécutions du test login.robot des 10 dernières minutes » - OpenSearch permet des agrégations structurées type « combien de tests PASS vs FAIL par jour sur la dernière semaine »
Image non pullable depuis un registry public¶
Le tag perfshop-test-runner:latest est local au poste de build. Aucun push vers Docker Hub ou autre registry n'est effectué. Le build.sh lance docker build sur le dossier test-runner/ à chaque déploiement. C'est aligné avec la philosophie PerfShop : tout est reproductible à partir du code source, aucune dépendance à un registry tiers.
Pour aller plus loin¶
- Selenium — le moteur WebDriver piloté par le test-runner
- Squash Orchestrator — l'un des deux déclencheurs
- Scripts UI — l'autre déclencheur (via
docker exec) - Loki — pipeline de collecte des logs
/rf-logs/*.log - OpenSearch — pipeline alternatif via Vector