Scénarios en Gherkin standard validés par l'analyseur officiel ; ADR amendables
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
42ace839d2
commit
2ab30a4abe
@@ -16,7 +16,7 @@ est la feuille de route.
|
||||
- **Licence** : tout le code sous GPLv3. Les contenus pédagogiques (leçons, textes) sous CC BY-SA 4.0.
|
||||
- **Langue** : interface, contenus, commentaires de code et messages de commit en français ; identifiants du code en anglais.
|
||||
- **Architecture et code** : simplicité d'abord, pas de sur-ingénierie ; domaine pur, moteur derrière `engine.h`, parties en journal d'événements ; règles complètes dans l'ADR 0007, à transmettre à chaque sous-agent.
|
||||
- **Glossaire et aide** : chaque terme du jeu a sa fiche dans `docs/glossaire/` (traduction anglaise = nom dans le code) ; chaque fonction visible a son scénario dans `docs/scenarios/`, à la fois aide de l'app et test de bout en bout. Une seule source, jamais dupliquée (ADR 0008).
|
||||
- **Glossaire et aide** : chaque terme du jeu a sa fiche dans `docs/glossaire/` (traduction anglaise = nom dans le code) ; chaque fonction visible a son scénario Gherkin dans `docs/scenarios/`, à la fois aide de l'app et test d'intégration sur le domaine et le moteur. Une seule source, jamais dupliquée (ADR 0008).
|
||||
- **Communauté de départ** : l'app sera d'abord diffusée auprès des joueurs de l'Atelier du Huit, café associatif à Cugnaux. Elle doit être accessible à de vrais débutants.
|
||||
- **Identité visuelle** : définie par le brief créatif (https://claude.ai/artifact/36WMwZWqvMxXvSSVBJTgwd). Les choix de produit, de ton et d'identité appartiennent au porteur du projet ; le rôle de Claude Code est technique : les mettre en œuvre et signaler leurs conséquences techniques.
|
||||
|
||||
@@ -55,7 +55,7 @@ Des cibles plus fines (`make engine`, `make engine-wasm`, `make bench`…) sont
|
||||
4. **Ne jamais masquer un échec.** Pas de test désactivé, pas de résultat simulé. Dire clairement ce qui bloque et la cause probable.
|
||||
5. **Commits fréquents**, messages courts en français, sur une branche dédiée. Jamais de commit direct sur `main` : chaque changement passe par une merge request Gitea (`tea pulls create --login sans-pub`), décrite selon `docs/organisation.md`. Claude Code la fusionne lui-même une fois `make lint` et `make test` au vert.
|
||||
6. **Dépendances** : peu, maintenues, compatibles GPLv3. Signaler chaque nouvelle dépendance et sa licence.
|
||||
7. **Journal** : `docs/journal.md` reçoit une entrée datée à la fin de chaque session (fait, décidé, reste à faire). Les décisions structurantes vont dans un ADR (`docs/adr/`), jamais réécrit une fois accepté.
|
||||
7. **Journal** : `docs/journal.md` reçoit une entrée datée à la fin de chaque session (fait, décidé, reste à faire). Les décisions structurantes vont dans un ADR (`docs/adr/`), amendé (section datée) mais jamais réécrit une fois accepté.
|
||||
|
||||
## Sources du moteur
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@ précisément ici dès que du code en sera repris :
|
||||
## Outils de développement
|
||||
|
||||
- **ShellCheck** (GPLv3), analyse des scripts shell, utilisé via Docker.
|
||||
- **Node.js** (MIT), image `node:22.11.0-alpine3.20`, et **@cucumber/gherkin**
|
||||
(MIT), analyseur Gherkin qui valide les scénarios de `docs/scenarios/`.
|
||||
|
||||
## Remerciements
|
||||
|
||||
|
||||
@@ -11,8 +11,10 @@ BUILD_DIR := build
|
||||
|
||||
# Outils lancés dans Docker (aucune installation sur le PC).
|
||||
SHELLCHECK_IMAGE := koalaman/shellcheck-alpine:v0.10.0
|
||||
# Image construite ici : changer le numéro à chaque modification de docker/gherkin/.
|
||||
GHERKIN_IMAGE := ustagammon/gherkin:2
|
||||
|
||||
export SHELLCHECK_IMAGE
|
||||
export SHELLCHECK_IMAGE GHERKIN_IMAGE
|
||||
|
||||
.PHONY: help setup build test lint deploy clean
|
||||
|
||||
@@ -25,6 +27,8 @@ setup: ## Installe la chaîne d'outils (images Docker) ; sans effet si déjà fa
|
||||
@command -v docker >/dev/null || { echo "Docker est requis : sudo apt install docker.io"; exit 1; }
|
||||
@docker image inspect $(SHELLCHECK_IMAGE) >/dev/null 2>&1 \
|
||||
|| docker pull $(SHELLCHECK_IMAGE)
|
||||
@docker image inspect $(GHERKIN_IMAGE) >/dev/null 2>&1 \
|
||||
|| docker build -q -t $(GHERKIN_IMAGE) docker/gherkin
|
||||
@echo "Chaîne d'outils prête."
|
||||
|
||||
build: ## Compile le moteur (si nécessaire) puis l'application
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
# Analyseur Gherkin officiel de Cucumber, pour valider docs/scenarios/ (ADR 0008).
|
||||
FROM node:22.11.0-alpine3.20
|
||||
|
||||
WORKDIR /opt/gherkin
|
||||
RUN npm install --no-audit --no-fund @cucumber/gherkin@29.0.0 @cucumber/messages@26.0.1
|
||||
COPY validate.mjs .
|
||||
|
||||
ENTRYPOINT ["node", "/opt/gherkin/validate.mjs"]
|
||||
@@ -0,0 +1,46 @@
|
||||
// Valide des fichiers .feature avec l'analyseur Gherkin officiel.
|
||||
// Usage : node validate.mjs fichier.feature…
|
||||
// Sort en erreur si un fichier n'est pas du Gherkin valide, n'est pas en
|
||||
// français (# language: fr), ne contient aucun scénario, ou a une étape égarée
|
||||
// dans une description (signe d'un mot-clé mal orthographié, que Gherkin
|
||||
// accepte alors comme texte libre).
|
||||
|
||||
import { readFileSync } from 'node:fs'
|
||||
import { AstBuilder, GherkinClassicTokenMatcher, Parser } from '@cucumber/gherkin'
|
||||
import { IdGenerator } from '@cucumber/messages'
|
||||
|
||||
const STEP = /^\s*(Étant donné|Etant donné|Quand|Alors|Et|Mais)\b/
|
||||
|
||||
function strayStep(description) {
|
||||
return description.split('\n').find((line) => STEP.test(line))
|
||||
}
|
||||
|
||||
let errors = 0
|
||||
|
||||
for (const file of process.argv.slice(2)) {
|
||||
const parser = new Parser(new AstBuilder(IdGenerator.uuid()), new GherkinClassicTokenMatcher())
|
||||
try {
|
||||
const { feature } = parser.parse(readFileSync(file, 'utf8'))
|
||||
if (!feature) {
|
||||
throw new Error('aucune fonctionnalité')
|
||||
}
|
||||
if (feature.language !== 'fr') {
|
||||
throw new Error(`langue « ${feature.language} » au lieu de « fr »`)
|
||||
}
|
||||
const scenarios = feature.children.filter((child) => child.scenario).map((child) => child.scenario)
|
||||
if (scenarios.length === 0) {
|
||||
throw new Error('aucun scénario')
|
||||
}
|
||||
for (const description of [feature.description, ...scenarios.map((scenario) => scenario.description)]) {
|
||||
const line = strayStep(description)
|
||||
if (line) {
|
||||
throw new Error(`étape hors d'un scénario (mot-clé mal orthographié ?) : ${line.trim()}`)
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(`${file} : ${error.message}`)
|
||||
errors++
|
||||
}
|
||||
}
|
||||
|
||||
process.exit(errors === 0 ? 0 : 1)
|
||||
@@ -40,3 +40,15 @@ dans un ADR, dans la description de la merge request ou dans le journal.
|
||||
- `make test` vérifie la forme des ADR (numérotation, statut, sections, index).
|
||||
- Les ADR 0002 à 0006 reprennent des décisions antérieures à celui-ci, avec
|
||||
leur date d'origine.
|
||||
|
||||
## Amendements
|
||||
|
||||
### 2026-11-02 — Amender plutôt que multiplier les ADR
|
||||
|
||||
Décidé par Pierre, pour ne pas créer un ADR à chaque précision. Un ADR accepté
|
||||
peut recevoir un amendement : une section « Amendements » en fin de fichier,
|
||||
une sous-section datée par amendement, qui dit qui l'a décidé, ce qu'il change
|
||||
et pourquoi. Le texte d'origine n'est pas réécrit ; s'il le faut, une courte
|
||||
mention renvoie à l'amendement. Un nouvel ADR (qui fait passer l'ancien au
|
||||
statut « remplacé par NNNN ») reste nécessaire quand la décision elle-même est
|
||||
abandonnée au profit d'une autre.
|
||||
|
||||
@@ -67,7 +67,8 @@ documentation affichée est donc toujours celle de la version installée.
|
||||
- **Documentation utilisateur rédigée à part des tests** : deux textes qui
|
||||
divergent tôt ou tard.
|
||||
- **Gherkin classique (`.feature`)** : exécutable, mais austère comme page
|
||||
d'aide. Le Markdown avec Gherkin donne les deux.
|
||||
d'aide. Le Markdown avec Gherkin donne les deux. (Choix inversé par
|
||||
l'amendement du 2026-11-02, ci-dessous.)
|
||||
- **Aide intégrée en dur dans l'application** : une seconde source à
|
||||
maintenir.
|
||||
|
||||
@@ -80,3 +81,30 @@ documentation affichée est donc toujours celle de la version installée.
|
||||
de glossaire dans la même merge request.
|
||||
- Toute fonction visible par l'utilisateur demande son scénario dans la même
|
||||
merge request.
|
||||
|
||||
## Amendements
|
||||
|
||||
### 2026-11-02 — Gherkin standard, exécution sur le domaine et le moteur
|
||||
|
||||
Décidé par Pierre. Remplace, dans la décision ci-dessus, le format Markdown
|
||||
avec Gherkin et l'exécution de bout en bout par l'interface.
|
||||
|
||||
- **Format** : Gherkin standard, fichiers `.feature` commençant par
|
||||
`# language: fr`. Le Markdown avec Gherkin est la variante la moins outillée
|
||||
de Cucumber, et sa prise en charge des mots-clés français n'est pas assurée ;
|
||||
le Gherkin standard est compris par tous les outils. Le paragraphe libre sous
|
||||
`Fonctionnalité:` porte l'introduction destinée au joueur ; l'application met
|
||||
le fichier en forme comme page d'aide.
|
||||
- **Validation dès maintenant** : `make test` passe chaque scénario dans
|
||||
l'analyseur officiel de Cucumber (`@cucumber/gherkin`, MIT, image
|
||||
`docker/gherkin/`), et refuse une étape égarée dans une description, signe
|
||||
d'un mot-clé mal orthographié que Gherkin accepterait comme texte libre.
|
||||
- **Exécution** : piloter une application native de bout en bout serait
|
||||
compliqué. Les scénarios sont donc exécutés comme tests d'intégration :
|
||||
leurs étapes appellent directement le domaine, branché sur le vrai moteur.
|
||||
Ils s'écrivent en conséquence avec des intentions (« vous commencez une
|
||||
nouvelle partie ») et non des gestes d'interface (« vous touchez le bouton
|
||||
… ») : le même scénario reste vrai quelle que soit l'interface.
|
||||
- **Perspective** : si les scénarios peuvent un jour être joués dans une
|
||||
instance réelle de l'application, la même exécution produira les captures
|
||||
d'écran de l'aide, toujours à jour avec la version installée.
|
||||
|
||||
+3
-2
@@ -1,8 +1,9 @@
|
||||
# Décisions d'architecture (ADR)
|
||||
|
||||
Un fichier par décision structurante, au format de `modele.md`. Un ADR accepté
|
||||
n'est plus réécrit : une décision qui change donne un nouvel ADR, et l'ancien
|
||||
passe au statut « remplacé par NNNN ». Voir l'ADR 0001.
|
||||
n'est pas réécrit : une précision s'ajoute en amendement daté à la fin du
|
||||
fichier ; une décision abandonnée au profit d'une autre donne un nouvel ADR, et
|
||||
l'ancien passe au statut « remplacé par NNNN ». Voir l'ADR 0001.
|
||||
|
||||
| N° | Décision | Statut |
|
||||
| --- | --- | --- |
|
||||
|
||||
@@ -21,7 +21,7 @@ Acquis : socle du dépôt, organisation (ADR 0001, 0003, 0006), source du moteur
|
||||
| Mesures | Pierre relève les mesures sur le Fairphone 4 | ⏳ | |
|
||||
| Décision | Socle PWA ou Android natif, consigné dans un ADR — validation de Pierre | ⏳ | |
|
||||
| 0c | Android natif (NDK, Gradle en ligne de commande, `make deploy` via adb) | ⏸ si 0b échoue | |
|
||||
| 0d | Plateau minimal jouable sur le socle retenu ; vérifié avec Pierre en suivant `docs/scenarios/jouer-une-partie.feature.md` | ⏳ | |
|
||||
| 0d | Plateau minimal jouable sur le socle retenu ; vérifié avec Pierre en suivant `docs/scenarios/jouer-une-partie.feature` | ⏳ | |
|
||||
|
||||
**Critère de fin** : une partie complète jouée sur le Fairphone 4, moins de 2 s
|
||||
par coup de l'IA en niveau standard, tous les tests au vert.
|
||||
|
||||
@@ -27,10 +27,10 @@ Deux familles de documents, de durée de vie différente (ADR 0001).
|
||||
| Document | Contenu | Mis à jour |
|
||||
| --- | --- | --- |
|
||||
| `docs/cadrage.md` | Vision, périmètre, architecture cible | Quand Pierre change le cadrage |
|
||||
| `docs/adr/` | Un ADR par décision structurante ; index dans `docs/adr/README.md` | À chaque décision ; jamais réécrit une fois accepté |
|
||||
| `docs/adr/` | Un ADR par décision structurante ; index dans `docs/adr/README.md` | À chaque décision ; une fois accepté, amendé (section datée) mais pas réécrit |
|
||||
| `docs/journal.md` | Une entrée datée par session : fait, décidé, suite | En fin de session |
|
||||
| `docs/glossaire/` | Une fiche par terme du jeu, avec sa traduction anglaise utilisée dans le code (ADR 0008) | Avec chaque nouveau terme du domaine |
|
||||
| `docs/scenarios/` | Documentation utilisateur en scénarios, aussi tests de bout en bout (ADR 0008) | Avec chaque fonction visible |
|
||||
| `docs/scenarios/` | Documentation utilisateur en scénarios Gherkin, aussi tests d'intégration (ADR 0008) | Avec chaque fonction visible |
|
||||
| Merge requests (git.sans.pub) | Le détail de chaque changement : pourquoi, comment, vérification | À chaque changement |
|
||||
|
||||
**Temporaires** : ils décrivent le travail à faire et disparaissent une fois
|
||||
|
||||
+27
-15
@@ -2,29 +2,41 @@
|
||||
|
||||
La documentation utilisateur d'Ustagammon : un fichier par tâche réelle d'un
|
||||
joueur, écrit pour lui. Ces fichiers sont la seule source (ADR 0008) :
|
||||
l'application les affiche comme pages d'aide, et ils servent de tests de bout
|
||||
en bout.
|
||||
l'application les met en forme comme pages d'aide, et ils sont exécutés comme
|
||||
tests d'intégration sur le domaine et le moteur réel.
|
||||
|
||||
Tant que l'outil d'exécution n'est pas choisi (avec le socle, fin de
|
||||
l'étape 0), les scénarios se déroulent à la main : ils servent alors de guide
|
||||
de test.
|
||||
Tant que le domaine n'existe pas, les scénarios se déroulent à la main : ils
|
||||
servent alors de guide de test.
|
||||
|
||||
## Format
|
||||
|
||||
Markdown avec Gherkin (`.feature.md`), étapes en français :
|
||||
Gherkin standard (`.feature`), en français, validé par l'analyseur officiel de
|
||||
Cucumber (`make test`) :
|
||||
|
||||
- `# Fonctionnalité : <la tâche>`, puis un court paragraphe qui explique à quoi
|
||||
elle sert, pour le joueur ;
|
||||
- `## Scénario : <un cas précis>` ;
|
||||
- des étapes en liste : `* Étant donné …`, `* Quand …`, `* Et …`, `* Alors …`.
|
||||
```gherkin
|
||||
# language: fr
|
||||
Fonctionnalité: <la tâche>
|
||||
|
||||
Règles d'écriture : la deuxième personne (« vous »), les mots du glossaire
|
||||
(`docs/glossaire/`), des étapes que le joueur peut faire et vérifier lui-même,
|
||||
pas de détail technique. La syntaxe exacte sera validée avec l'outil
|
||||
d'exécution.
|
||||
Un court paragraphe qui explique au joueur à quoi elle sert.
|
||||
|
||||
Scénario: <un cas précis>
|
||||
Étant donné que <la situation de départ>
|
||||
Quand <ce que fait le joueur>
|
||||
Alors <ce qu'il constate>
|
||||
Et <autre constat>
|
||||
```
|
||||
|
||||
Règles d'écriture :
|
||||
|
||||
- la deuxième personne (« vous ») et les mots du glossaire (`docs/glossaire/`) ;
|
||||
- des intentions, pas des gestes d'interface : « vous commencez une nouvelle
|
||||
partie », pas « vous touchez le bouton Nouvelle partie ». Le même scénario
|
||||
reste vrai quelle que soit l'interface, et peut piloter directement le
|
||||
domaine ;
|
||||
- des constats vérifiables par le joueur, sans détail technique.
|
||||
|
||||
## Scénarios
|
||||
|
||||
| Fichier | Tâche | Depuis |
|
||||
| --- | --- | --- |
|
||||
| [jouer-une-partie.feature.md](jouer-une-partie.feature.md) | Jouer une partie contre l'ordinateur | Étape 0d |
|
||||
| [jouer-une-partie.feature](jouer-une-partie.feature) | Jouer une partie contre l'ordinateur | Étape 0d |
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
# language: fr
|
||||
Fonctionnalité: Jouer une partie contre l'ordinateur
|
||||
|
||||
Vous jouez une partie complète contre l'ordinateur, qui s'appuie sur le
|
||||
moteur GNU Backgammon. L'application tire les dés, n'accepte que les coups
|
||||
permis par les règles, et l'ordinateur joue et décide du videau tout seul.
|
||||
|
||||
Scénario: Commencer une partie
|
||||
Quand vous commencez une nouvelle partie
|
||||
Alors les pions sont en position de départ
|
||||
Et le premier jet de dés désigne qui commence
|
||||
|
||||
Scénario: Jouer un coup permis
|
||||
Étant donné que c'est à vous de jouer avec le jet 3-1
|
||||
Quand vous jouez 8/5 6/5
|
||||
Alors votre coup est accepté
|
||||
Et c'est au tour de l'ordinateur
|
||||
|
||||
Scénario: Un coup interdit est refusé
|
||||
Étant donné que c'est à vous de jouer avec le jet 3-1
|
||||
Quand vous essayez de jouer 8/4
|
||||
Alors votre coup est refusé
|
||||
Et la position n'a pas changé
|
||||
|
||||
Scénario: L'ordinateur joue
|
||||
Étant donné que c'est au tour de l'ordinateur
|
||||
Quand ses dés sont tirés
|
||||
Alors il joue le coup recommandé par le moteur en moins de 2 secondes
|
||||
|
||||
Scénario: Prendre le double de l'ordinateur
|
||||
Étant donné que l'ordinateur vous propose de doubler
|
||||
Quand vous prenez
|
||||
Alors la partie continue à valeur doublée
|
||||
Et le videau est de votre côté : vous seul pourrez redoubler
|
||||
|
||||
Scénario: Passer le double de l'ordinateur
|
||||
Étant donné que l'ordinateur vous propose de doubler
|
||||
Quand vous passez
|
||||
Alors la partie s'arrête
|
||||
Et vous perdez la partie à sa valeur d'avant le double
|
||||
|
||||
Scénario: Finir la partie
|
||||
Étant donné qu'un joueur a sorti tous ses pions
|
||||
Alors la partie s'arrête
|
||||
Et le résultat indique le gagnant et les points gagnés
|
||||
@@ -1,48 +0,0 @@
|
||||
# Fonctionnalité : Jouer une partie contre l'ordinateur
|
||||
|
||||
Vous jouez une partie complète contre l'ordinateur, qui s'appuie sur le moteur
|
||||
GNU Backgammon. L'application tire les dés, vous propose uniquement des coups
|
||||
permis par les règles, et l'ordinateur joue et décide du videau tout seul.
|
||||
|
||||
## Scénario : Commencer une partie
|
||||
|
||||
* Étant donné que vous avez ouvert Ustagammon
|
||||
* Quand vous touchez « Nouvelle partie »
|
||||
* Alors le plateau s'affiche avec les pions en position de départ
|
||||
* Et le premier jet de dés désigne qui commence
|
||||
|
||||
## Scénario : Jouer votre coup
|
||||
|
||||
* Étant donné que c'est à vous de jouer et que les dés sont tirés
|
||||
* Quand vous touchez un pion puis la case où vous voulez l'amener
|
||||
* Alors le pion s'y déplace si ce déplacement est permis par les dés
|
||||
* Et un déplacement interdit est refusé sans changer le plateau
|
||||
* Quand vous avez utilisé vos dés
|
||||
* Alors votre coup est validé et c'est au tour de l'ordinateur
|
||||
|
||||
## Scénario : L'ordinateur joue
|
||||
|
||||
* Étant donné que c'est au tour de l'ordinateur
|
||||
* Quand ses dés sont tirés
|
||||
* Alors il joue son coup en moins de 2 secondes
|
||||
* Et son coup s'affiche sur le plateau
|
||||
|
||||
## Scénario : Prendre le double de l'ordinateur
|
||||
|
||||
* Étant donné que l'ordinateur vous propose de doubler
|
||||
* Quand vous touchez « Prendre »
|
||||
* Alors la partie continue à valeur doublée
|
||||
* Et le videau passe de votre côté : vous seul pourrez redoubler
|
||||
|
||||
## Scénario : Passer le double de l'ordinateur
|
||||
|
||||
* Étant donné que l'ordinateur vous propose de doubler
|
||||
* Quand vous touchez « Passer »
|
||||
* Alors la partie s'arrête
|
||||
* Et vous perdez la partie à sa valeur d'avant le double
|
||||
|
||||
## Scénario : Finir la partie
|
||||
|
||||
* Étant donné qu'un joueur a sorti tous ses pions
|
||||
* Alors la partie s'arrête
|
||||
* Et le résultat indique le gagnant et les points gagnés : simple, gammon ou backgammon, multipliés par le videau
|
||||
+14
-10
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# Vérifie la forme des scénarios d'utilisation (docs/scenarios/, ADR 0008) :
|
||||
# un titre « Fonctionnalité », au moins un « Scénario », des étapes qui
|
||||
# commencent par un mot-clé Gherkin français, chaque fichier dans l'index.
|
||||
# Vérifie les scénarios d'utilisation (docs/scenarios/, ADR 0008) :
|
||||
# chaque .feature est du Gherkin valide en français pour l'analyseur officiel
|
||||
# de Cucumber (dans Docker), et figure dans l'index README.md.
|
||||
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/../docs/scenarios"
|
||||
@@ -12,14 +12,18 @@ report() {
|
||||
errors=$((errors + 1))
|
||||
}
|
||||
|
||||
for f in *.feature.md; do
|
||||
head -n1 "$f" | grep -qE '^# Fonctionnalité : .+' \
|
||||
|| report "$f : la première ligne doit être « # Fonctionnalité : … »"
|
||||
grep -qE '^## Scénario : .+' "$f" || report "$f : aucun « ## Scénario : … »"
|
||||
while IFS= read -r step; do
|
||||
report "$f : étape sans mot-clé Gherkin : $step"
|
||||
done < <(grep -E '^\* ' "$f" | grep -vE '^\* (Étant donné|Quand|Alors|Et|Mais) ' || true)
|
||||
features=(*.feature)
|
||||
[ -e "${features[0]}" ] || report "aucun scénario dans docs/scenarios/"
|
||||
|
||||
for f in "${features[@]}"; do
|
||||
[ -e "$f" ] || continue
|
||||
grep -qF "]($f)" README.md || report "$f : absent de l'index README.md"
|
||||
done
|
||||
|
||||
if ! docker image inspect "${GHERKIN_IMAGE:?lancer via make test}" >/dev/null 2>&1; then
|
||||
report "Analyseur Gherkin absent : lancer d'abord make setup"
|
||||
elif ! docker run --rm -v "$PWD:/src:ro" -w /src "$GHERKIN_IMAGE" "${features[@]}"; then
|
||||
report "scénarios invalides (voir ci-dessus)"
|
||||
fi
|
||||
|
||||
[ "$errors" -eq 0 ]
|
||||
|
||||
Reference in New Issue
Block a user