<?xml version="1.0" encoding="UTF-8"?>
<quiz>
<question type="category">
  <category>
    <text>$course$/QCM de NSI/Première/Tests et débogage</text>
  </category>
  <info format="html">
    <text><![CDATA[<p>Tester un programme : assertions, jeux d'essais,<br/>
tests unitaires, cas limites. Déboguer : lecture de<br/>
la trace d'erreurs, instructions print de<br/>
débogage, débogueur interactif, isolement de bugs,<br/>
réduction au cas minimal.</p>]]></text>
  </info>
</question>

<question type="multichoice">
  <name>
    <text>Tests et débogage — Q01 : Notion de test</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Qu'appelle-t-on un <strong>test</strong> dans le<br/>
contexte du logiciel ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Une bonne pratique consiste à<br/>
tester systématiquement ses<br/>
fonctions, en particulier dans les<br/>
parties critiques du programme. Un<br/>
projet sans tests est très<br/>
fragile.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Une vérification automatique qu'un programme se comporte comme attendu sur des entrées choisies</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Un test fournit une entrée connue<br/>
et compare la sortie obtenue à la<br/>
sortie attendue. Cela permet de<br/>
détecter aussi bien les<br/>
régressions que les bugs<br/>
nouveaux.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un type particulier de variable</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Un test n'est pas une variable.<br/>
C'est une procédure de<br/>
vérification.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une question à choix multiple posée à l'utilisateur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette interprétation littérale est<br/>
sans rapport avec la notion<br/>
informatique de test logiciel,<br/>
qui vise à vérifier le bon<br/>
fonctionnement d'un programme.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un avertissement émis par le langage Python</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Un avertissement est un message<br/>
envoyé pendant l'exécution, sans<br/>
comparaison à une valeur attendue.<br/>
Ce n'est pas un test.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tests et débogage — Q02 : Instruction assert</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Que fait l'instruction assert<br/>
condition en Python ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Un usage typique :<br/>
assert n &gt; 0, "n doit être<br/>
positif". Le message après la<br/>
virgule apparaît dans l'erreur<br/>
affichée, ce qui aide au<br/>
débogage.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Si la condition est fausse, elle lève une exception AssertionError ; sinon, elle ne fait rien</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>C'est très utile pour vérifier<br/>
des invariants. Lorsqu'une<br/>
assertion échoue, le programme<br/>
s'arrête, ce qui permet de<br/>
détecter les bugs au plus tôt.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elle affiche la condition à l'écran</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>L'instruction assert n'affiche<br/>
rien lorsque la condition est<br/>
vraie. Elle ne lève une erreur<br/>
que dans le cas contraire.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elle convertit la condition en booléen</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La condition est déjà évaluée<br/>
comme un booléen avant l'appel à<br/>
assert. La conversion en tant<br/>
que telle se fait avec<br/>
bool(...).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elle ne fonctionne qu'en mode débogage</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette description est inexacte.<br/>
Les assertions sont actives par<br/>
défaut, et désactivées seulement<br/>
si le programme est lancé avec<br/>
l'option python -O.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tests et débogage — Q03 : Test unitaire</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Qu'est-ce qu'un <strong>test unitaire</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Une organisation classique des<br/>
tests forme une pyramide :<br/>
beaucoup de tests unitaires (très<br/>
rapides), moins de tests<br/>
d'intégration (plus lents mais<br/>
utiles) et très peu de tests de<br/>
bout en bout (lents et fragiles).</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un test sans coût</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette interprétation littérale<br/>
du mot « unitaire » est<br/>
fantaisiste.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un test qui couvre tout le programme</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Un test qui couvre l'ensemble du<br/>
programme s'appelle un test<br/>
d'intégration ou un test<br/>
système, et non un test<br/>
unitaire.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un test qui dure très longtemps</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>C'est plutôt l'inverse. Les tests<br/>
unitaires sont conçus pour être<br/>
rapides, ciblés et automatisés.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Un test qui vérifie le comportement d'une seule fonction (une « unité » de code) sur des entrées spécifiques</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Les tests unitaires sont<br/>
rapides, ciblés et automatisés.<br/>
Ils permettent d'isoler les<br/>
bugs : on identifie précisément<br/>
quelle fonction se comporte<br/>
mal.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tests et débogage — Q04 : Exemple de test</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quelle ligne <strong>teste</strong> que carre(3)<br/>
== 9 ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>L'instruction assert est rapide<br/>
à écrire et lisible. Pour des<br/>
tests plus structurés, avec<br/>
rapports détaillés, on préfère le<br/>
module unittest ou la<br/>
bibliothèque pytest.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>if carre(3) != 9: print("erreur")</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette ligne effectue bien une<br/>
vérification, mais elle<br/>
n'interrompt pas le programme<br/>
en cas d'échec. L'instruction<br/>
assert est plus idiomatique<br/>
dans un contexte de test.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>assert carre(3) == 9</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Si carre(3) ne vaut pas 9,<br/>
l'assertion échoue et le<br/>
programme s'arrête. Sinon, le<br/>
programme continue<br/>
silencieusement.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>carre(3)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette ligne exécute simplement<br/>
la fonction sans rien vérifier.<br/>
Aucune comparaison n'est<br/>
effectuée.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>test carre(3) == 9</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette syntaxe n'existe pas en<br/>
Python. Le mot-clé test<br/>
n'est pas reconnu par le<br/>
langage.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tests et débogage — Q05 : Erreur Python</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quand Python lève une <strong>erreur</strong>, où<br/>
regarder pour comprendre ce qui se<br/>
passe ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Quelques erreurs fréquentes :<br/>
NameError (variable inconnue),<br/>
TypeError (incompatibilité de<br/>
types), IndexError (indice hors<br/>
des bornes), ValueError (valeur<br/>
inappropriée pour une opération).</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le code source du module Python lui-même</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Ce serait à faire en dernier<br/>
recours. La plupart du temps,<br/>
l'erreur vient du code<br/>
utilisateur, pas de<br/>
l'interpréteur.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les paramètres du système d'exploitation</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La trace d'erreur Python est<br/>
locale au programme. Le<br/>
système d'exploitation n'est<br/>
pas concerné.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Sur Internet, en cherchant un message proche</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette démarche peut compléter<br/>
l'analyse, mais ce n'est pas<br/>
la première chose à faire. Il<br/>
faut commencer par la trace<br/>
d'erreur affichée par Python.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>La trace d'erreur affichée par Python, qui indique le fichier, la ligne concernée et le type d'erreur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>On lit la trace d'erreur du bas<br/>
vers le haut. La dernière ligne<br/>
donne en général le type<br/>
d'erreur et le message<br/>
associé.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tests et débogage — Q06 : Instruction print de débogage</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>À quoi sert un appel à print dans<br/>
un objectif de <strong>débogage</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Avantages : la fonction print<br/>
est simple et fonctionne partout.<br/>
Inconvénient : il faut penser à<br/>
retirer ces affichages après le<br/>
débogage. Pour un suivi plus<br/>
sophistiqué, on peut utiliser le<br/>
module logging ou un débogueur<br/>
interactif comme pdb.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>À empêcher d'écrire d'autres lignes de code</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette description ne correspond<br/>
à aucun usage réel de print.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>À encoder des données en hexadécimal</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La fonction print ne réalise<br/>
aucune conversion automatique<br/>
en hexadécimal.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>À afficher la valeur d'une variable à un moment précis du programme, pour suivre son déroulement</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>C'est une technique simple mais<br/>
efficace. Pour suivre la valeur<br/>
de x à l'intérieur d'une<br/>
boucle, on peut écrire<br/>
print(f"x = {x}").</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>À ralentir intentionnellement le programme</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Un excès de print peut<br/>
effectivement ralentir un<br/>
programme, mais ce n'est jamais<br/>
l'objectif recherché.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tests et débogage — Q07 : Notion de bug</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Qu'est-ce qu'un <strong>bug</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Il faut distinguer plusieurs<br/>
notions : un <strong>bug</strong> signifie<br/>
que le code ne fait pas ce qu'il<br/>
doit ; une <strong>erreur d'exécution</strong><br/>
survient quand le programme<br/>
plante ; une <strong>erreur de<br/>
spécification</strong> signifie que la<br/>
définition même du<br/>
comportement attendu est<br/>
incorrecte. Cette dernière est<br/>
la plus difficile à corriger.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Une erreur ou un comportement non conforme aux spécifications du programme</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Le terme est historique : il<br/>
provient d'un véritable insecte<br/>
retrouvé en 1947 dans les<br/>
relais d'une machine analysée<br/>
par Grace Hopper. La trace de<br/>
cet incident est encore<br/>
conservée.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une fonctionnalité que l'utilisateur n'a pas demandée</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette description est une<br/>
plaisanterie courante (« ce<br/>
n'est pas un bug, c'est une<br/>
fonctionnalité »), mais elle<br/>
ne correspond pas à la<br/>
définition technique.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une nouvelle version d'un logiciel</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Une nouvelle version peut<br/>
comporter des bugs, mais elle<br/>
n'est pas elle-même un bug.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un type particulier de mémoire</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Un bug n'a aucun rapport avec<br/>
la mémoire d'un ordinateur.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tests et débogage — Q08 : Jeu d'essais</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Qu'est-ce qu'un <strong>jeu d'essais</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Un bon jeu d'essais détecte les<br/>
régressions. Si l'on modifie le<br/>
code et que tous les tests<br/>
continuent à passer, on peut<br/>
avoir confiance. Si un test<br/>
échoue, on sait précisément quoi<br/>
corriger.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un test choisi au hasard</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Un jeu d'essais est conçu de<br/>
manière réfléchie, et non tiré<br/>
au hasard.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Un ensemble d'entrées prévues, chacune accompagnée de sa sortie attendue, qui couvre les cas typiques et les cas limites de la fonction</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Un bon jeu d'essais couvre les<br/>
cas normaux, les cas limites<br/>
(par exemple liste vide, liste<br/>
d'un seul élément, valeurs<br/>
extrêmes) et les cas d'erreur<br/>
(entrée invalide). Plus la<br/>
couverture est large, plus le<br/>
test est robuste.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un manuel d'utilisation du programme</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La documentation et les jeux<br/>
d'essais sont deux notions<br/>
distinctes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une collection de jeux vidéo</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette interprétation littérale<br/>
du mot « jeu » est sans<br/>
rapport avec son sens<br/>
informatique.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tests et débogage — Q09 : Lire une trace d'erreur</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>`<code><br/>
File "main.py", line 5, in &lt;module&gt;<br/>
    print(liste[5])<br/>
IndexError: list index out of range<br/>
</code>`<br/>
Que dit cette trace d'erreur ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Le réflexe à acquérir : lire le<br/>
<strong>type</strong> de l'erreur (qui donne<br/>
la nature du bug), puis la<br/>
<strong>ligne</strong> indiquée (qui en<br/>
donne l'emplacement). C'est<br/>
systématique.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>À la ligne 5 de main.py, on tente d'accéder à liste[5] alors que cet indice n'existe pas (la liste est trop courte)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Le message<br/>
IndexError: list index out of<br/>
range signifie un accès à un<br/>
indice hors des bornes. La<br/>
cause typique est une mauvaise<br/>
estimation de la taille de la<br/>
liste.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La ligne 5 contient une variable non définie</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette description correspond à<br/>
une NameError, et non à une<br/>
IndexError.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Il s'agit d'une erreur de syntaxe</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Une erreur de syntaxe se<br/>
présente sous la forme d'une<br/>
SyntaxError, et non d'une<br/>
IndexError.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Aucun problème n'est signalé</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La trace contient bien une<br/>
erreur, indiquée par<br/>
IndexError.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tests et débogage — Q10 : Isoler un bug</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour comprendre l'origine d'un bug<br/>
dans un programme, quelle démarche<br/>
est la plus efficace en première<br/>
approche ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>La discipline du cas de test<br/>
minimal est l'une des bases du<br/>
débogage. Elle permet aussi<br/>
d'écrire un test de non-régression<br/>
compact, qui protégera contre la<br/>
réapparition du bug à l'avenir.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Ignorer le bug s'il n'apparaît qu'à l'occasion</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Un bug intermittent, surtout,<br/>
ne s'efface pas en l'ignorant.<br/>
Il finit par réapparaître au<br/>
plus mauvais moment. Au<br/>
contraire, il faut chercher<br/>
activement à le reproduire.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Réduire l'entrée problématique au cas le plus simple qui reproduit encore le bug</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>C'est l'idée du cas de test<br/>
minimal. Si un programme plante<br/>
sur une liste de mille<br/>
éléments, essayer d'abord avec<br/>
dix, puis avec cinq, puis avec<br/>
deux, en gardant à chaque fois<br/>
la propriété qui fait planter.<br/>
On obtient un exemple court qui<br/>
aide à localiser le bug et à<br/>
écrire un test de régression.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Réécrire l'intégralité du programme depuis zéro</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette démarche est risquée et<br/>
peu économique. Elle introduit<br/>
souvent de nouveaux bugs sans<br/>
comprendre l'origine du bug<br/>
initial.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Multiplier la taille de l'entrée jusqu'à trouver une régularité</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>C'est l'inverse de la démarche<br/>
utile. Plus l'entrée est<br/>
grande, plus il est difficile<br/>
d'identifier ce qui déclenche<br/>
précisément le bug.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tests et débogage — Q11 : Module unittest</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quel module de la bibliothèque<br/>
standard de Python permet d'écrire<br/>
des <strong>tests structurés</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Pour exécuter les tests, on<br/>
utilise la commande python -m<br/>
unittest. Pour un débutant, des<br/>
assert directs peuvent<br/>
suffire. Pour un projet<br/>
sérieux, mieux vaut adopter<br/>
unittest ou pytest.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>debug</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Aucun module de ce nom<br/>
n'existe dans la bibliothèque<br/>
standard de Python.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>unittest</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>C'est le module standard pour<br/>
les tests unitaires en<br/>
Python. On définit des<br/>
classes héritant de<br/>
TestCase et l'on écrit des<br/>
méthodes dont le nom commence<br/>
par test_. Une alternative<br/>
très populaire est la<br/>
bibliothèque pytest, plus<br/>
simple d'usage.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>assert_module</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Aucun module de ce nom<br/>
n'existe dans la bibliothèque<br/>
standard.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>tests</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Aucun module de ce nom<br/>
n'existe non plus dans la<br/>
bibliothèque standard.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tests et débogage — Q12 : La bibliothèque pytest</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pourquoi la bibliothèque pytest<br/>
est-elle si populaire ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Un test minimal écrit avec<br/>
pytest :</p>
<p>`<code>python<br/>
def test_carre():<br/>
    assert carre(3) == 9<br/>
</code></p>
<p>Pour lancer les tests, on<br/>
exécute simplement la commande<br/>
pytest, qui découvre<br/>
automatiquement les fonctions<br/>
dont le nom commence par<br/>
test_`.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Pour sa syntaxe simple (un assert valeur == attendu suffit, pas besoin de classes), ses fixtures et son écosystème de greffons</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette bibliothèque simplifie<br/>
considérablement l'écriture<br/>
des tests par rapport au<br/>
module unittest. Elle est<br/>
devenue le standard de fait<br/>
dans le monde Python<br/>
moderne.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce qu'elle est obligatoire dans tout projet Python</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Aucune obligation n'existe.<br/>
La bibliothèque pytest est<br/>
facultative, même si très<br/>
recommandée.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce qu'elle génère automatiquement le code des tests</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La bibliothèque pytest ne<br/>
génère pas automatiquement le<br/>
code des tests : c'est au<br/>
développeur de les écrire.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce qu'elle est plus rapide à l'exécution</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La rapidité d'exécution n'est<br/>
pas son atout principal. Sa<br/>
force vient de la simplicité<br/>
d'écriture des tests.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tests et débogage — Q13 : Identifier un bug</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>`<code>python<br/>
def somme(liste):<br/>
    total = 0<br/>
    for i in range(1, len(liste)):<br/>
        total += liste[i]<br/>
    return total<br/>
</code>`<br/>
Quel <strong>bug</strong> contient cette fonction ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Les bugs de décalage d'indice<br/>
sont très fréquents. Il faut<br/>
toujours tester avec des listes<br/>
simples ([], [1],<br/>
[1, 2]) pour les détecter.<br/>
Un bon test serait par exemple<br/>
assert somme([1, 2, 3]) == 6.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Aucun bug n'est présent</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Un bug existe bien dans cette<br/>
fonction, comme expliqué dans<br/>
la bonne réponse.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La fonction ne renvoie aucune valeur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La fonction se termine bien<br/>
par return total, donc<br/>
elle renvoie une valeur.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La syntaxe est incorrecte</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Le code est syntaxiquement<br/>
valide. Le bug est purement<br/>
logique.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>La boucle commence à l'indice 1 au lieu de 0, donc l'élément liste[0] est ignoré</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>C'est un bug classique de<br/>
<strong>décalage d'indice</strong>. Pour<br/>
la liste [1, 2, 3], la<br/>
fonction renvoie 5 au lieu<br/>
de 6. Un test sur un cas<br/>
simple permettrait de le<br/>
détecter.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tests et débogage — Q14 : Lire la trace d'erreur</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Dans une trace d'erreur à plusieurs<br/>
niveaux, où trouve-t-on en général<br/>
la <strong>cause initiale</strong> du bug ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Pour lire une trace : commencer<br/>
par la fin, qui indique le type<br/>
d'erreur, puis remonter<br/>
jusqu'au code qu'on a soi-même<br/>
écrit. Les premières lignes,<br/>
souvent dans des bibliothèques,<br/>
sont rarement le bon point<br/>
d'entrée.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Au milieu de la trace</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Aucune position particulière<br/>
au milieu n'est privilégiée.<br/>
La cause initiale se lit en<br/>
bas de la trace.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Au hasard dans la trace</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La position du message<br/>
d'erreur n'a rien d'aléatoire :<br/>
il se trouve toujours à la<br/>
fin de la trace.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>En haut de la trace</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>C'est plutôt l'inverse. Le<br/>
message d'erreur le plus<br/>
précis se trouve en bas de<br/>
la trace.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>La dernière ligne (en bas), qui indique le type et le message d'erreur, et la ligne immédiatement au-dessus, qui pointe l'endroit dans votre code</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Python affiche la pile des<br/>
appels de fonctions dans<br/>
l'ordre chronologique, et le<br/>
message d'erreur tout en<br/>
bas. La ligne la plus utile<br/>
est généralement celle qui<br/>
renvoie à votre propre code.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tests et débogage — Q15 : Reproduire un bug</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour résoudre un bug, qu'est-ce qui<br/>
est <strong>essentiel</strong> à faire en<br/>
premier ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>L'adage classique est :<br/>
« si l'on ne peut pas<br/>
reproduire le bug, on ne peut<br/>
pas le corriger ». Une fois la<br/>
reproduction obtenue, on peut<br/>
réduire l'entrée au cas minimal<br/>
qui déclenche encore le bug,<br/>
puis corriger.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Demander à un collègue de regarder le code</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cela peut aider dans un<br/>
second temps, mais ni un<br/>
humain ni un assistant<br/>
automatique ne peuvent<br/>
diagnostiquer un bug sans<br/>
pouvoir le reproduire.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Réécrire le code suspect</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La réécriture n'est pas la<br/>
première étape. Il faut<br/>
d'abord pouvoir observer le<br/>
bug pour pouvoir vérifier<br/>
ensuite la correction.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Réinstaller l'interpréteur Python</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette opération est rarement<br/>
nécessaire. La cause d'un<br/>
bug se trouve presque<br/>
toujours dans le code lui-même.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Le reproduire : trouver une entrée minimale qui déclenche systématiquement le bug</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Un bug intermittent est très<br/>
difficile à corriger. La<br/>
reproduction est la première<br/>
étape, et permet d'écrire un<br/>
<strong>test de régression</strong>.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tests et débogage — Q16 : Débogueur</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Qu'est-ce qu'un <strong>débogueur</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Pour activer pdb, on lance la<br/>
commande python -m pdb<br/>
script.py, ou on insère<br/>
breakpoint() dans le code<br/>
(depuis Python 3.7). Quelques<br/>
commandes utiles : n pour<br/>
passer à la ligne suivante,<br/>
s pour entrer dans une<br/>
fonction, c pour continuer,<br/>
et p variable pour afficher<br/>
la valeur d'une variable.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un compilateur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Un compilateur transforme du<br/>
code source en code<br/>
exécutable. Il n'a aucun<br/>
rapport avec le débogage<br/>
interactif.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Un outil qui permet d'exécuter pas à pas, d'inspecter les variables, de poser des points d'arrêt et de remonter la pile des appels</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Plusieurs outils existent :<br/>
pdb en ligne de commande,<br/>
ou les débogueurs intégrés<br/>
aux environnements de<br/>
développement comme VS Code<br/>
ou PyCharm. Tous sont<br/>
puissants pour comprendre<br/>
des bugs complexes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un antivirus</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Un antivirus protège contre<br/>
les logiciels malveillants ;<br/>
il n'a rien à voir avec le<br/>
débogage de programmes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un fichier de journalisation</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Un débogueur est un outil<br/>
interactif, et non un fichier<br/>
stocké sur le disque.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tests et débogage — Q17 : Couverture de tests</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Que mesure la <strong>couverture de<br/>
tests</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Attention : une couverture de<br/>
100 \% ne garantit pas<br/>
l'absence de bugs. On peut<br/>
passer dans toutes les lignes<br/>
sans pour autant tester tous<br/>
les <strong>comportements</strong>. C'est<br/>
néanmoins une base utile.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>La proportion de lignes (ou de branches) du code qui sont effectivement exécutées par les tests</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>C'est un indicateur de<br/>
qualité des tests. Une<br/>
couverture de 80 \% est<br/>
bien meilleure qu'une<br/>
couverture de 30 \%.<br/>
L'outil coverage.py<br/>
permet de la mesurer en<br/>
Python.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La taille en octets du programme</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La taille du programme n'a<br/>
aucun rapport avec la<br/>
couverture des tests.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le nombre total de tests écrits</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La couverture ne se réduit<br/>
pas à un comptage des tests.<br/>
Elle s'intéresse à la part<br/>
du code effectivement<br/>
parcourue.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La performance d'exécution du programme</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La couverture n'a rien à<br/>
voir avec la performance.<br/>
C'est une mesure de la<br/>
qualité de la suite de<br/>
tests.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tests et débogage — Q18 : Test de régression</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Qu'est-ce qu'un <strong>test de<br/>
régression</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Une discipline classique<br/>
consiste en un cycle « rouge<br/>
puis vert » : on écrit<br/>
d'abord un test qui reproduit<br/>
le bug et qui échoue (état<br/>
« rouge »), puis on corrige<br/>
le code jusqu'à ce que le<br/>
test passe (état « vert »).</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un test qui revient en arrière dans le code</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette interprétation<br/>
littérale du mot<br/>
« régression » ne<br/>
correspond pas au sens<br/>
technique de<br/>
l'expression.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un test qui échoue à chaque exécution</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Un test de régression doit<br/>
au contraire passer après<br/>
la correction. S'il échoue<br/>
systématiquement, c'est que<br/>
la correction n'a pas été<br/>
faite, ou qu'elle a été<br/>
défaite.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Un test ajouté après avoir corrigé un bug, dont le rôle est de vérifier que ce bug ne réapparaisse pas dans le futur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>C'est une pratique<br/>
essentielle. Pour chaque<br/>
bug corrigé, il est<br/>
recommandé d'ajouter un<br/>
test qui aurait permis de<br/>
le détecter. Cela protège<br/>
contre les régressions<br/>
futures.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un test sur l'ancienne version du code</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Un test de régression<br/>
s'exécute sur la version<br/>
actuelle du code, pas sur<br/>
une ancienne. Son rôle est<br/>
de prévenir le retour d'un<br/>
bug ancien.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tests et débogage — Q19 : Module logging</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pourquoi préfère-t-on le module<br/>
logging à la fonction print<br/>
pour le débogage en production ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Exemple d'utilisation typique :</p>
<p>`<code>python<br/>
import logging<br/>
logging.basicConfig(level=logging.DEBUG)<br/>
logging.debug("valeur de x : %s", x)<br/>
</code></p>
<p>Ce module est plus puissant<br/>
que print`, au prix d'un<br/>
léger surcoût syntaxique.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce que la fonction print n'existe pas en Python</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La fonction print existe<br/>
bel et bien et reste utile,<br/>
notamment pour<br/>
l'apprentissage.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Pour pouvoir activer ou désactiver les messages, choisir leur niveau de gravité (debug, info, warning, error), les rediriger vers un fichier, etc.</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Le module logging est<br/>
conçu pour la production.<br/>
Il offre une configuration<br/>
centralisée, plusieurs<br/>
niveaux de gravité, un<br/>
formatage riche et plusieurs<br/>
destinataires possibles<br/>
(console, fichier, réseau).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce que le module logging est obligatoire</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>L'usage du module est<br/>
facultatif, mais il est<br/>
fortement recommandé pour<br/>
les programmes destinés à<br/>
la production.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Pour gagner de l'espace en mémoire</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>L'avantage du module<br/>
logging n'est pas une<br/>
économie de mémoire.<br/>
C'est avant tout une<br/>
question de souplesse et<br/>
de configurabilité.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tests et débogage — Q20 : Écrire les tests avant le code</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quel est l'avantage principal<br/>
d'écrire les tests <strong>avant</strong> le<br/>
code (approche dite de<br/>
développement piloté par les<br/>
tests) ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Le cycle est le suivant : on<br/>
écrit d'abord un test qui<br/>
échoue ; on écrit ensuite le<br/>
code minimal qui le fait<br/>
passer ; on retravaille<br/>
enfin la structure du code,<br/>
en conservant les tests<br/>
verts. Ce cycle se répète<br/>
sur de petites unités, à un<br/>
rythme fréquent.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Elle oblige à clarifier la spécification avant l'implémentation, et garantit que la fonction sera testable et fera bien ce qui est attendu</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>On écrit la spécification<br/>
sous une forme exécutable<br/>
(le test), ce qui contraint<br/>
à réfléchir précisément<br/>
aux comportements attendus<br/>
avant de coder.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le code est plus rapide à écrire dès le départ</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette approche n'est pas<br/>
plus rapide au démarrage,<br/>
et exige même un certain<br/>
temps d'apprentissage. Son<br/>
intérêt se mesure surtout<br/>
à moyen terme, sur la<br/>
qualité et la fiabilité<br/>
du code produit.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elle dispense d'écrire des commentaires</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Aucun rapport. Les<br/>
commentaires gardent leur<br/>
utilité pour expliquer<br/>
les intentions et les<br/>
choix de conception.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elle permet d'éviter complètement les bugs</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette affirmation est trop<br/>
optimiste. Aucune méthode<br/>
ne supprime tous les bugs.<br/>
Les tests réduisent leur<br/>
fréquence et facilitent<br/>
leur détection précoce.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tests et débogage — Q21 : Bug intermittent</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Un bug se produit <strong>parfois</strong>,<br/>
sans que l'on sache prévoir<br/>
quand. Que faire ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Causes typiques<br/>
d'intermittence : exécution<br/>
concurrente (fils<br/>
d'exécution, parallélisme),<br/>
mémoire non initialisée,<br/>
état global partagé, ordre<br/>
des éléments dans un<br/>
dictionnaire (avant Python<br/>
3.7).</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Multiplier les journaux d'exécution, ajouter des assertions, et étudier ce qui change entre les exécutions où le programme fonctionne et celles où il échoue (synchronisation, ordre, données d'entrée)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Les bugs intermittents<br/>
révèlent souvent des<br/>
courses critiques, des<br/>
problèmes de<br/>
synchronisation, ou des<br/>
dépendances cachées entre<br/>
parties du programme.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Réinstaller Python</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette opération est très<br/>
rarement la cause, et ne<br/>
devrait être tentée qu'en<br/>
dernier recours.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Acheter un nouvel ordinateur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette interprétation<br/>
littérale est sans rapport<br/>
avec le débogage.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Ignorer le bug</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>C'est une mauvaise pratique.<br/>
Un bug ignoré finit<br/>
toujours par revenir, et<br/>
souvent au pire moment.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tests et débogage — Q22 : Stratégie globale</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Devant un bug, quelle est la<br/>
<strong>bonne stratégie</strong> générale à<br/>
adopter ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Discipline : ne jamais<br/>
corriger un bug sans avoir<br/>
réussi à le reproduire, et<br/>
ne jamais corriger sans<br/>
ajouter ensuite un test de<br/>
régression. Sinon, le bug<br/>
finira par réapparaître,<br/>
et le temps gagné au<br/>
départ sera perdu plus<br/>
tard.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Demander une mise à jour du langage Python</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Une telle mise à jour est<br/>
extrêmement rarement la<br/>
solution à un bug<br/>
applicatif.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Reproduire le bug, isoler la cause (en réduisant l'entrée au cas minimal), corriger, puis ajouter un test de régression</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>C'est une méthodologie<br/>
éprouvée. Sauter une étape,<br/>
en particulier la dernière,<br/>
garantit que le bug<br/>
finira par réapparaître.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Réécrire intégralement le programme</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette démarche est risquée :<br/>
elle peut introduire de<br/>
nouveaux bugs et masque<br/>
l'origine du problème<br/>
initial.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Désactiver les tests existants</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette démarche est<br/>
contre-productive. Les<br/>
tests sont précisément<br/>
l'outil principal pour<br/>
détecter et corriger les<br/>
bugs.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tests et débogage — Q23 : Test mal écrit</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quel est le problème avec ce<br/>
test ?<br/>
`<code>python<br/>
assert chercher([1, 2, 3], 2)<br/>
</code>`</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Piège des tests laxistes :<br/>
ils passent quand ils ne<br/>
devraient pas, et laissent<br/>
passer des bugs. Il faut<br/>
toujours <strong>vérifier des<br/>
valeurs précises</strong>, et non<br/>
simplement l'absence<br/>
d'erreur.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La syntaxe est invalide</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Le code est syntaxiquement<br/>
valide. Le défaut est<br/>
purement sémantique : le<br/>
test n'est pas assez<br/>
précis.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La fonction chercher n'existe pas</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>On suppose que la fonction<br/>
existe et est définie<br/>
quelque part dans le code.<br/>
Le problème ne tient pas<br/>
à son existence.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Aucun problème particulier</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Ce test contient en réalité<br/>
un défaut subtil mais<br/>
important, comme expliqué<br/>
dans la bonne réponse.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Il vérifie seulement que chercher renvoie une valeur considérée comme vraie au sens booléen, mais pas que l'indice est correct. La fonction pourrait renvoyer 0 (qui est le bon indice mais évalue à False) ou 999 (qui est faux, mais évalue à True)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Ce test est trop laxiste.<br/>
On préfère écrire<br/>
assert chercher([1, 2, 3],<br/>
2) == 1, qui vérifie<br/>
précisément la valeur<br/>
renvoyée.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tests et débogage — Q24 : Tests et débogage</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quelle est la<br/>
<strong>complémentarité</strong> entre tests<br/>
et débogage ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Une démarche idéale combine<br/>
les deux activités : on<br/>
écrit d'abord des tests qui<br/>
trouvent un bug ; on<br/>
débogue ensuite pour<br/>
localiser, comprendre et<br/>
corriger ; on ajoute enfin<br/>
un test de régression pour<br/>
empêcher la résurgence du<br/>
bug.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>L'une remplace l'autre</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Ces activités sont<br/>
complémentaires : ni les<br/>
tests ni le débogage ne<br/>
peuvent se passer l'un de<br/>
l'autre dans un projet<br/>
sérieux.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Les tests trouvent les bugs (sur les cas testés), le débogage localise et corrige un bug déjà repéré</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Ce sont deux phases<br/>
distinctes mais<br/>
complémentaires. Tester,<br/>
c'est investir pour<br/>
détecter ; déboguer, c'est<br/>
investiguer pour corriger.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le débogage permet d'éviter d'écrire des tests</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>C'est l'inverse : un bon<br/>
ensemble de tests permet<br/>
de détecter rapidement un<br/>
bug et de réduire le<br/>
temps passé à le déboguer.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les deux activités sont identiques</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Ces activités diffèrent<br/>
par leur objectif et leur<br/>
déroulement, comme<br/>
expliqué dans la bonne<br/>
réponse.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tests et débogage — Q25 : Synthèse</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Parmi les affirmations suivantes<br/>
sur les tests et le débogage,<br/>
laquelle est <strong>fausse</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Citation d'Edsger Dijkstra :<br/>
« Program testing can be<br/>
used to show the presence of<br/>
bugs, but never to show<br/>
their absence. » Pour<br/>
garantir formellement<br/>
l'absence de bugs, il<br/>
faudrait recourir à une<br/>
preuve mathématique, ce qui<br/>
reste rarement praticable<br/>
sur du code réel.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Réduire l'entrée problématique au cas le plus simple qui reproduit le bug aide à localiser sa cause</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette affirmation est<br/>
correcte. C'est l'une des<br/>
techniques de base pour<br/>
isoler un bug.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La trace d'erreur indique le type d'erreur et la ligne où elle s'est produite</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette affirmation est<br/>
correcte. C'est même son<br/>
rôle principal.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un test unitaire vérifie une seule fonction de manière isolée</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette affirmation est<br/>
correcte. C'est même la<br/>
définition d'un test<br/>
unitaire.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Les tests garantissent l'absence de bugs</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette affirmation est<br/>
fausse (donc c'est la<br/>
bonne réponse). Les<br/>
tests révèlent la<br/>
<strong>présence</strong> de bugs sur<br/>
les cas effectivement<br/>
testés, mais ils ne<br/>
peuvent jamais prouver<br/>
l'<strong>absence</strong> de bugs sur<br/>
des entrées non testées.<br/>
Edsger Dijkstra a résumé<br/>
cela par : « Tester ne<br/>
peut prouver l'absence<br/>
de bugs ».</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tests et débogage — Q26 : Trois familles d'erreurs</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>On distingue habituellement les<br/>
erreurs de <strong>syntaxe</strong>, les<br/>
erreurs <strong>d'exécution</strong> et les<br/>
erreurs <strong>sémantiques</strong> (ou<br/>
logiques). Quelle catégorie est<br/>
la plus difficile à détecter<br/>
automatiquement ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Mémorable : « ce qui ne<br/>
compile pas, ne s'exécute<br/>
pas ; ce qui s'exécute peut<br/>
planter ; ce qui ne plante<br/>
pas peut quand même être<br/>
faux ». Les tests servent<br/>
surtout à détecter la<br/>
troisième catégorie.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les erreurs de syntaxe, car elles cassent toute l'exécution</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ces erreurs sont au<br/>
contraire les <strong>plus<br/>
faciles</strong> à détecter. Python<br/>
refuse de lancer le programme<br/>
et affiche immédiatement<br/>
SyntaxError, avec le<br/>
numéro de ligne. Aucune<br/>
mystère.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les erreurs d'exécution, car le programme s'arrête en cours de route</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ces erreurs sont<br/>
aussi facilement repérables.<br/>
Le programme s'arrête en<br/>
levant une exception, avec<br/>
une trace d'erreur précise<br/>
(IndexError,<br/>
ZeroDivisionError, etc.).<br/>
On voit immédiatement où<br/>
chercher.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Les erreurs sémantiques, car le programme s'exécute sans planter, mais ne fait pas ce qu'il devrait faire</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : c'est le bug<br/>
le plus pernicieux. Aucun<br/>
message d'erreur, juste un<br/>
résultat faux. Seuls des<br/>
tests bien choisis ou une<br/>
relecture attentive<br/>
permettent de le détecter.<br/>
Exemple : une boucle qui<br/>
commence à l'indice 1 au<br/>
lieu de 0.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les trois catégories sont équivalentes</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ces trois<br/>
catégories diffèrent<br/>
radicalement par leur mode<br/>
de détection. La syntaxe est<br/>
détectée par l'analyseur<br/>
syntaxique, l'exécution par<br/>
l'interpréteur, la sémantique<br/>
uniquement par les tests ou<br/>
la relecture humaine.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Tests et débogage — Q27 : Plusieurs cas dans un test</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Comment écrire un test qui<br/>
vérifie le comportement d'une<br/>
fonction carre sur <strong>plusieurs<br/>
entrées</strong> sans dupliquer le code<br/>
?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Schéma général d'un test<br/>
paramétré : une liste de<br/>
couples (entrée, sortie<br/>
attendue), parcourus dans<br/>
une boucle qui vérifie<br/>
chaque cas. La bibliothèque<br/>
pytest formalise cela avec<br/>
le décorateur<br/>
@pytest.mark.parametrize.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>python<br/>
def test_carre():<br/>
    return carre(0) and carre(1) and carre(3)<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce code ne vérifie<br/>
pas que les valeurs<br/>
renvoyées sont<br/>
<strong>correctes</strong>. Il vérifie<br/>
seulement qu'aucune n'est<br/>
fausse au sens booléen.<br/>
Comme carre(0) == 0,<br/>
l'expression renvoie 0<br/>
(faux) sans que cela<br/>
signale un bug.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>python<br/>
def test_carre():<br/>
    assert carre(0) == 0<br/>
    assert carre(1) == 1<br/>
    assert carre(3) == 9<br/>
    assert carre(-2) == 4<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Cette version fonctionne<br/>
aussi, mais l'énoncé<br/>
demandait précisément<br/>
d'éviter la duplication. De<br/>
plus, ici, dès qu'un<br/>
assert échoue, les<br/>
suivants ne sont pas<br/>
exécutés et l'on ignore<br/>
quels autres cas posent<br/>
problème.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>`<code>python<br/>
def test_carre():<br/>
    for x, attendu in [(0, 0), (1, 1), (3, 9), (-2, 4)]:<br/>
        assert carre(x) == attendu, f"échec pour x = {x}"<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : on parcourt<br/>
une liste de couples<br/>
(entrée, sortie attendue),<br/>
on vérifie chaque cas avec<br/>
assert. Le message après<br/>
la virgule indique<br/>
précisément quel cas a<br/>
échoué, ce qui facilite le<br/>
débogage. C'est aussi le<br/>
principe des <strong>tests<br/>
paramétrés</strong> de pytest.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>`<code>python<br/>
def test_carre():<br/>
    assert carre == 9<br/>
</code>`</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : on compare la<br/>
fonction elle-même (un<br/>
objet) à 9, ce qui est<br/>
toujours faux. Il faut<br/>
appeler la fonction avec<br/>
des paramètres et comparer<br/>
son <strong>résultat</strong>.</p>]]></text>
    </feedback>
  </answer>
</question>

</quiz>
