[ADD] make: une cible pour les tests unitaires, dépendance mobile déclarée
Ces 382 tests ne tournaient que lancés à la main, donc jamais. « make test »
demande une base de données et plusieurs minutes ; ceux-ci lisent le code et
exécutent les fragments de shell générés, sudo, pgrep et pkill bouchonnés, en
une dizaine de secondes. Deux cibles : test_unit, et test_unit_file pour la
boucle d'écriture.
La dépendance à mobile/erplibre_home_mobile est DITE plutôt que supposée : le
lanceur l'annonce présente ou absente, et les tests du vrai transfert se
déclarent ignorés — avec la commande qui manque — au lieu de passer en silence.
Vérifié dans les trois états : dépôt absent, présent non compilé, compilé.
Au passage, compile_and_run.sh vérifie le transfert des dépôts, comme
l'installation d'une VM et par le même script.
--- EN ---
These 382 tests only ran when invoked by hand, so never. "make test" wants a
database and several minutes; these read the code and run the generated shell
fragments with sudo, pgrep and pkill stubbed, in about ten seconds. Two targets:
test_unit, and test_unit_file for the writing loop.
The dependency on mobile/erplibre_home_mobile is STATED rather than assumed: the
runner announces it present or absent, and the real-transfer tests declare
themselves skipped — naming the missing command — instead of passing quietly.
Checked in all three states: repo absent, present but unbuilt, built.
Along the way, compile_and_run.sh verifies the repo transfer, like a VM install
and through the same script.
Assisted-by: Claude Opus 5
2026-08-21 20:06:23 -04:00
|
|
|
#!/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...]
|
[REF] déploiement : un seul socle pour ce qui décrit le système invité
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
2026-08-24 22:45:50 -04:00
|
|
|
#
|
|
|
|
|
# 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.
|
[ADD] make: une cible pour les tests unitaires, dépendance mobile déclarée
Ces 382 tests ne tournaient que lancés à la main, donc jamais. « make test »
demande une base de données et plusieurs minutes ; ceux-ci lisent le code et
exécutent les fragments de shell générés, sudo, pgrep et pkill bouchonnés, en
une dizaine de secondes. Deux cibles : test_unit, et test_unit_file pour la
boucle d'écriture.
La dépendance à mobile/erplibre_home_mobile est DITE plutôt que supposée : le
lanceur l'annonce présente ou absente, et les tests du vrai transfert se
déclarent ignorés — avec la commande qui manque — au lieu de passer en silence.
Vérifié dans les trois états : dépôt absent, présent non compilé, compilé.
Au passage, compile_and_run.sh vérifie le transfert des dépôts, comme
l'installation d'une VM et par le même script.
--- EN ---
These 382 tests only ran when invoked by hand, so never. "make test" wants a
database and several minutes; these read the code and run the generated shell
fragments with sudo, pgrep and pkill stubbed, in about ten seconds. Two targets:
test_unit, and test_unit_file for the writing loop.
The dependency on mobile/erplibre_home_mobile is STATED rather than assumed: the
runner announces it present or absent, and the real-transfer tests declare
themselves skipped — naming the missing command — instead of passing quietly.
Checked in all three states: repo absent, present but unbuilt, built.
Along the way, compile_and_run.sh verifies the repo transfer, like a VM install
and through the same script.
Assisted-by: Claude Opus 5
2026-08-21 20:06:23 -04:00
|
|
|
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 \
|
[ADD] run: choisir la base au démarrage, sans jamais bloquer
« ./run.sh » sans argument partait sans base et l'on choisissait dans le
gestionnaire web. Il choisit maintenant : une seule base, il démarre
dessus ; plusieurs, il affiche un menu numéroté.
Ce qui décide n'est pas le menu mais l'endroit où il ne doit PAS s'ouvrir.
systemd écrit « ExecStart=/bin/bash …/run.sh » sans argument, avec
Restart=always : une question posée là serait une boucle de redémarrage.
Le défaut implicite exige donc un terminal sur stdin ET sur stderr — pas
stdout, qui est toujours un tube dans la substitution qui nous lit.
Mesuré : sans terminal, la ligne d'arguments est identique à l'octet et
la sonde, qui coûte 0,8 s, n'est jamais appelée.
--- EN ---
« ./run.sh » with no argument started without a database and one picked
in the web manager. It now picks: a single database, it starts on it;
several, it shows a numbered menu.
What decides is not the menu but where it must NOT open. systemd writes
« ExecStart=/bin/bash …/run.sh » with no argument and Restart=always: a
question asked there would be a restart loop. The implicit default
therefore requires a terminal on stdin AND on stderr — not stdout, which
is always a pipe inside the substitution that reads us. Measured: with no
terminal the argument line is byte-for-byte identical and the 0.8 s probe
is never called.
Assisted-by: Claude Opus 5
2026-08-23 17:26:41 -04:00
|
|
|
test/test_todo_*.py test/test_install_*.py test/test_run_*.py \
|
[ADD] git : un garde-fou commit-msg pour le sujet
Rien ne tenait la convention sur le sujet : le tag est respecté partout,
c'est la longueur qui glisse. Le hook refuse le mécanique et rien de plus
— tag absent, plus de 72 caractères, sujet ouvrant sur une citation ; dire
sur quoi porte le code reste un jugement qu'aucun hook ne rendra. Il compte
des caractères et non des octets, sans quoi un sujet français de 72
caractères tomberait sur ses accents. Le refus enseigne le repli vers des
mots-clés plutôt que la troncature, et nomme `--no-verify` : un garde-fou
qui refuse trop est désinstallé. Les tests pèsent donc autant les
acceptations, « Merge branch » ou fixup de rebase. Le lanceur balaie le
préfixe test_git_ : 32 tests jamais exécutés, le total va de 1021 à 1071.
--- EN ---
Nothing held the subject convention: the tag is respected everywhere, it
is the length that slips. The hook refuses the mechanical and nothing more
— no tag, over 72 characters, a subject opening on a quotation; whether it
says what the code is about stays a judgement no hook will make. It counts
characters, not bytes, or a 72-character French subject would fall on its
accents. The refusal teaches the fallback to keywords rather than
truncation, and names `--no-verify`: a guard rail that refuses too much
gets uninstalled. So the tests weigh the acceptances as much, a "Merge
branch" or a rebase fixup. The runner sweeps the test_git_ prefix: 32
tests never ran, and the total goes from 1021 to 1071.
Assisted-by: Claude Opus 5
(cherry picked from commit c9abf4d1b723ae8ff3762d39bfe1d6982400d12d)
2026-08-25 05:48:54 -04:00
|
|
|
test/test_proxmox_*.py test/test_git_*.py \
|
[ADD] run: choisir la base au démarrage, sans jamais bloquer
« ./run.sh » sans argument partait sans base et l'on choisissait dans le
gestionnaire web. Il choisit maintenant : une seule base, il démarre
dessus ; plusieurs, il affiche un menu numéroté.
Ce qui décide n'est pas le menu mais l'endroit où il ne doit PAS s'ouvrir.
systemd écrit « ExecStart=/bin/bash …/run.sh » sans argument, avec
Restart=always : une question posée là serait une boucle de redémarrage.
Le défaut implicite exige donc un terminal sur stdin ET sur stderr — pas
stdout, qui est toujours un tube dans la substitution qui nous lit.
Mesuré : sans terminal, la ligne d'arguments est identique à l'octet et
la sonde, qui coûte 0,8 s, n'est jamais appelée.
--- EN ---
« ./run.sh » with no argument started without a database and one picked
in the web manager. It now picks: a single database, it starts on it;
several, it shows a numbered menu.
What decides is not the menu but where it must NOT open. systemd writes
« ExecStart=/bin/bash …/run.sh » with no argument and Restart=always: a
question asked there would be a restart loop. The implicit default
therefore requires a terminal on stdin AND on stderr — not stdout, which
is always a pipe inside the substitution that reads us. Measured: with no
terminal the argument line is byte-for-byte identical and the 0.8 s probe
is never called.
Assisted-by: Claude Opus 5
2026-08-23 17:26:41 -04:00
|
|
|
2>/dev/null)
|
[ADD] make: une cible pour les tests unitaires, dépendance mobile déclarée
Ces 382 tests ne tournaient que lancés à la main, donc jamais. « make test »
demande une base de données et plusieurs minutes ; ceux-ci lisent le code et
exécutent les fragments de shell générés, sudo, pgrep et pkill bouchonnés, en
une dizaine de secondes. Deux cibles : test_unit, et test_unit_file pour la
boucle d'écriture.
La dépendance à mobile/erplibre_home_mobile est DITE plutôt que supposée : le
lanceur l'annonce présente ou absente, et les tests du vrai transfert se
déclarent ignorés — avec la commande qui manque — au lieu de passer en silence.
Vérifié dans les trois états : dépôt absent, présent non compilé, compilé.
Au passage, compile_and_run.sh vérifie le transfert des dépôts, comme
l'installation d'une VM et par le même script.
--- EN ---
These 382 tests only ran when invoked by hand, so never. "make test" wants a
database and several minutes; these read the code and run the generated shell
fragments with sudo, pgrep and pkill stubbed, in about ten seconds. Two targets:
test_unit, and test_unit_file for the writing loop.
The dependency on mobile/erplibre_home_mobile is STATED rather than assumed: the
runner announces it present or absent, and the real-transfer tests declare
themselves skipped — naming the missing command — instead of passing quietly.
Checked in all three states: repo absent, present but unbuilt, built.
Along the way, compile_and_run.sh verifies the repo transfer, like a VM install
and through the same script.
Assisted-by: Claude Opus 5
2026-08-21 20:06:23 -04:00
|
|
|
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}
|