Leçon 8 — Projet final : assistant de réunion

Tester dans les deux modes

5 min de lecture

Tester dans les deux modes

Deux niveaux de tests

flowchart LR
  subgraph S["Sans clé (pytest)"]
    F["FakeClient"] --> L["logique : coût, réessais, JSON, Markdown, chat, mode"]
  end
  subgraph R["Avec le vrai modèle"]
    A["Mode clé d'API"] --> E["tokens, resume, --stream, chat"]
    V["Mode Vertex AI"] --> E
  end
  S --> R
Tests pytestTest de bout en bout
Clé ou projet nécessairenonoui
Duréemoins d'une secondede quelques secondes à une minute
Coûtnulquelques fractions de centime
Ce qu'il prouvele code fait ce qu'on croitl'ensemble marche avec le vrai service et donne des résultats sensés

Le faux client

FakeClient imite les quatre points d'entrée utilisés (models.generate_content, models.generate_content_stream, models.count_tokens, chats.create). Il renvoie des réponses préparées, ou lève une erreur pour simuler un incident :

files/test_reunion.py
class FakeClient:
    def __init__(self, *reponses):
        self.reponses = list(reponses)
        self.appels = []
        self.models = self
        self.chats = self

    def _suivante(self, **kw):
        self.appels.append(kw)
        r = self.reponses.pop(0)
        if isinstance(r, Exception):
            raise r
        return r

Chaque test prépare un scénario et vérifie le résultat et les appels effectués (par exemple, que la config contient bien le schéma JSON). Code complet : test_reunion.py.

terminal
pip install -r requirements.txt
pytest -q

Le test de bout en bout

terminal : mode clé d
python reunion.py tokens reunion_exemple.txt
python reunion.py resume reunion_exemple.txt
python reunion.py resume reunion_exemple.txt --stream
printf "Qui prépare le message aux clients ?\nEt quand est-il validé ?\n\n" | python reunion.py chat reunion_exemple.txt
terminal : mode Vertex AI
gcloud auth application-default login          # une seule fois
export GOOGLE_GENAI_USE_VERTEXAI=TRUE GOOGLE_CLOUD_PROJECT=mon-projet-gcp
export MODEL=gemini-2.5-flash                  # voir la leçon Vertex AI
# puis les mêmes quatre commandes

Que prouve test_compte_rendu_structure, qui utilise FakeClient ?

Le mode Vertex AI nécessite-t-il de supprimer quelque chose après le test ?

Résultat obtenu

Tests sans clé, 2026-10-15 :

pytest -v (fin)
test_reunion.py::test_mode[TRUE-Vertex AI] PASSED                     [ 85%]
test_reunion.py::test_mode[false-cl\xe9 d'API] PASSED                    [ 92%]
test_reunion.py::test_mode[-cl\xe9 d'API] PASSED                         [100%]
============================== 14 passed in 0.29s ==============================

Bout en bout en mode clé d'API (gemini-3.5-flash) :

sortie
[mode : clé d'API | modèle : gemini-3.5-flash]
302 tokens en entrée, soit environ 0.000091 $ avant la réponse
[coût estimé : 0.003344 $]
1. Le lancement de la v2 de l'application est officiellement décalé au 4 novembre.
2. Karim analyse cette semaine le problème d'export PDF sur les gros fichiers.
...
> Et quand est-il validé ?
Le message sera validé lundi (par Inès et Léa).

Bout en bout en mode Vertex AI (projet de test, gemini-2.5-flash, région global puis europe-west1) :

sortie
[mode : Vertex AI | modèle : gemini-2.5-flash]
301 tokens en entrée, soit environ 0.000090 $ avant la réponse
[coût estimé : 0.002226 $]
| Examiner le problème d'export PDF sur les gros fichiers | Karim | cette semaine |
| Envoyer les captures d'écran de la v2 à Thomas pour la page d'accueil | Karim | vendredi |
| Préparer le message pour informer les clients du nouveau calendrier | Léa | lundi |
...
=== europe-west1
| Terminer les tests de bout en bout du module de paiement | Karim | non précisé |
| Préparer le message pour prévenir les clients du nouveau calendrier | Léa | non précisé |

Les quatre commandes fonctionnent dans les deux modes, sans changer une ligne de code. Les comptes rendus diffèrent d'un modèle et d'un appel à l'autre (ici, une action « tests de paiement » apparaît en europe-west1) : les deux sont défendables, c'est pourquoi on relit avant de diffuser. Rien n'a été créé dans le projet Google Cloud, il n'y a donc rien à nettoyer.

Exercice final

Ajoutez une commande actions qui n'affiche que le tableau des actions, et le test sans clé correspondant.

Voir la solution
files/reunion.py (modifications)
    p.add_argument("commande", choices=["resume", "tokens", "chat", "actions"])
    ...
    elif args.commande == "actions":
        cr, _ = compte_rendu(client, transcription)
        print(en_markdown(cr).split("## Actions\n", 1)[1])
files/test_reunion.py (ajout)
def test_commande_actions(monkeypatch, tmp_path, capsys):
    f = tmp_path / "r.txt"
    f.write_text("Inès : on décale.", encoding="utf-8")
    monkeypatch.setattr(reunion, "make_client",
                        lambda: FakeClient(NS(text=json.dumps(CR), usage_metadata=USAGE)))
    reunion.main(["actions", str(f)])
    out = capsys.readouterr().out
    assert "| Prévenir le support | Inès | vendredi |" in out and "Résumé" not in out

monkeypatch.setattr(reunion, "make_client", ...) remplace la création du vrai client : main() tourne entièrement, sans clé. C'est le même principe que pour toutes les autres fonctions, appliqué à tout le programme.

Je sais faire

  • Écrire un faux client et tester un programme qui appelle Gemini sans clé
  • Lancer un test de bout en bout en mode clé d'API puis en mode Vertex AI
  • Rendre une conversation scriptable avec un tube
  • Expliquer pourquoi aucune ressource cloud n'est à nettoyer après ces appels