Type de VM, production, magasin d'applications, outils de développement, fuseau horaire, interpréteur Python : six réglages qui décrivent l'invité, pas la machine qui le porte. Ils valaient donc déjà sur Proxmox — l'écran n'en offrait que trois. Une VM créée là-bas naissait serveur nu, sans outils et en UTC, et rien ne le disait. La duplication était le mécanisme de la dérive : chaque correctif se posait sur un seul des deux écrans. Les six vivent maintenant dans un socle commun, widgets ET logique, et le contexte qui les nourrit est écrit une fois. L'écran QEMU/KVM perd 330 lignes sans qu'un widget ni une valeur de spec ne bouge — vérifié en montant l'ancien et le nouveau dans le même processus. Trois conséquences se sont propagées seules : le disque annoncé (bureau et outils compris) atteint enfin « qm resize », le parallélisme suit les cœurs de l'hôte au lieu d'un plafond de quatre, et le nom prend le suffixe du bureau — sans lui, une VM graphique et sa jumelle serveur se disputaient le même. Deux défauts nommés au passage. Le fuseau : « qm set » n'en pose pas, il part maintenant par ssh avant l'installation. Et l'architecture d'une VM Proxmox venait de « virsh », qui ne connaît que les domaines d'ici — une VM ARM prise pour x86_64 recevait Android Studio, que Google ne publie pas pour elle. Le test porte sur la PARITÉ, pas sur six comportements : ajouter un réglage à un seul écran le fait échouer. Il a d'abord échoué à se lancer — hors des préfixes du lanceur, douze tests n'ont jamais tourné et le total n'avait pas bougé. La règle de nommage est maintenant dans son en-tête. --- EN --- VM type, production, app store, development tools, timezone, Python interpreter: six settings that describe the guest, not the machine hosting it. They already applied to Proxmox — the screen offered three. A VM created there was born a bare server, no tools, in UTC, and nothing said so. Duplication was the mechanism of the drift: each fix landed on one screen only. The six now live in a shared foundation, widgets AND logic, and the context feeding them is written once. The QEMU/KVM screen loses 330 lines with no widget and no spec value moving — verified by mounting the old and the new in one process. Three consequences followed on their own: the announced disk (desktop and tools included) finally reaches "qm resize", parallelism follows the host's cores instead of a cap of four, and the name takes the desktop suffix — without it a graphical VM and its server twin fought over the same one. Two defects named along the way. The timezone: "qm set" sets none, it now goes over ssh before the install. And a Proxmox VM's architecture came from "virsh", which only knows local domains — an ARM VM taken for x86_64 got Android Studio, which Google does not publish for it. The test covers PARITY, not six behaviours: adding a setting to one screen alone fails it. It first failed to run at all — outside the runner's prefixes, twelve tests never ran and the total had not moved. The naming rule is now in its header. Assisted-by: Claude Opus 5
81 lines
2.8 KiB
Bash
Executable file
81 lines
2.8 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# © 2026 TechnoLibre (http://www.technolibre.ca)
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
|
|
#
|
|
# Tests unitaires python du dépôt : ni base de données, ni Odoo, ni VM.
|
|
#
|
|
# Ils lisent le code et exécutent les fragments de shell que todo.py génère,
|
|
# avec « sudo », « pgrep » et « pkill » bouchonnés — c'est ce qui les rend
|
|
# lançables partout et en quelques secondes, là où « make test » demande une
|
|
# base et plusieurs minutes.
|
|
#
|
|
# DÉPENDANCE DÉCLARÉE : les tests du transfert mobile lisent
|
|
# mobile/erplibre_home_mobile. Absent, ils se disent ignorés plutôt que de
|
|
# passer en silence — un test vert sans son dépôt ne prouve rien. Ce script
|
|
# l'annonce donc avant de commencer.
|
|
#
|
|
# ./script/test/run_unit_test.sh [fichiers...]
|
|
#
|
|
# NOMMER UN NOUVEAU FICHIER : sans argument, ce script ne prend que les
|
|
# préfixes listés plus bas (test_qemu_, test_todo_, test_proxmox_…) — le reste
|
|
# de test/ demande une base de données. Un fichier hors préfixe tombe donc dans
|
|
# le même silence qu'un fichier absent : douze tests écrits, jamais lancés, et
|
|
# un total qui n'a pas bougé. Choisir le préfixe de sa famille, ou l'ajouter
|
|
# ici.
|
|
set -uo pipefail
|
|
|
|
Red='\033[0;31m'
|
|
Green='\033[0;32m'
|
|
Yellow='\033[0;33m'
|
|
Color_Off='\033[0m'
|
|
|
|
cd "$(dirname "$0")/../.." || exit 1
|
|
|
|
PY=./.venv.erplibre/bin/python
|
|
if [[ ! -x "${PY}" ]]; then
|
|
echo -e "${Red}✗ ${PY} absent : lancer l'installation ERPLibre d'abord.${Color_Off}"
|
|
exit 1
|
|
fi
|
|
|
|
MOBILE=mobile/erplibre_home_mobile
|
|
if [[ -d "${MOBILE}" ]]; then
|
|
echo -e " dépendance ${MOBILE} : ${Green}présente${Color_Off}"
|
|
else
|
|
echo -e " dépendance ${MOBILE} : ${Yellow}absente${Color_Off}"
|
|
echo " (les tests du transfert mobile s'en passeront et le diront)"
|
|
fi
|
|
|
|
FILES=("$@")
|
|
if [[ ${#FILES[@]} -eq 0 ]]; then
|
|
# Aucun argument : tout ce que le dépôt sait tester sans base de données.
|
|
mapfile -t FILES < <(ls test/test_qemu_*.py test/test_mobile_*.py \
|
|
test/test_todo_*.py test/test_install_*.py test/test_run_*.py \
|
|
test/test_proxmox_*.py \
|
|
2>/dev/null)
|
|
fi
|
|
|
|
fail=0
|
|
total=0
|
|
for f in "${FILES[@]}"; do
|
|
out=$(PYTHONPATH=. "${PY}" "${f}" 2>&1)
|
|
ran=$(echo "${out}" | grep -oE 'Ran [0-9]+' | grep -oE '[0-9]+' | tail -1)
|
|
skipped=$(echo "${out}" | grep -oE 'skipped=[0-9]+' | tail -1)
|
|
if echo "${out}" | grep -qE '^OK'; then
|
|
state="${Green}OK${Color_Off}"
|
|
else
|
|
state="${Red}ÉCHEC${Color_Off}"
|
|
fail=1
|
|
fi
|
|
total=$((total + ${ran:-0}))
|
|
printf " %-42s %5s tests %-14s %b\n" \
|
|
"$(basename "${f}")" "${ran:-?}" "${skipped:-}" "${state}"
|
|
[[ "${state}" == *"ÉCHEC"* ]] && echo "${out}" | tail -12
|
|
done
|
|
|
|
echo " ─────"
|
|
if [[ ${fail} -eq 0 ]]; then
|
|
echo -e " ${Green}${total} tests, tout vert${Color_Off}"
|
|
else
|
|
echo -e " ${Red}des échecs ci-dessus${Color_Off}"
|
|
fi
|
|
exit ${fail}
|