<?xml version="1.0" encoding="UTF-8"?>

<upm-export>
	<title>Enseignement de l&#039;informatique et du numérique au lycée Boissy d&#039;Anglas</title>
	<link>https://icn-isn-boissy.yj.fr/wp</link>
	<description></description>
	<pubDate>Wed May 6 12:01:16 2026 / +0000  GMT</pubDate>
	<generator>Universal Post Manager 1.1.2 [ www.ProfProjects.com ] </generator>
	<language></language>
	
			<item>
			<title>Doctest : une façon originale et pratique de tester…</title>
			<link>https://icn-isn-boissy.yj.fr/wp/?p=2102</link>
			<pubDate>Wed May 6 12:01:16 2026 / +0000  GMT</pubDate>
			<guid isPermaLink="false">https://icn-isn-boissy.yj.fr/wp/?p=2102</guid>
			<content-encoded><![CDATA[<!-- wp:paragraph -->
<p>Objectifs</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>utiliser un outil de test : <em><strong>doctest</strong></em></li><li>établir une méthodologie pour les TP</li></ul>
<!-- /wp:list -->

<!-- wp:heading -->
<h2>Motivation</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Vous savez documenter les fonctions à l'aide d'une «chaîne de documentation» (ou «docstring»), c'est-à-dire une chaîne de caractères placée immédiatement après l'en-tête de la fonction. Voici un tel exemple de documentation</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>def fact(n):
    """
        paramètre n : (int) un entier
        valeur renvoyée : (int) la factorielle de n.

    CU : n >= 0

    Exemples :

    >>> fact(3)
    6
    >>> fact(5)
    120
    """
    res = 1
    for i in range(2, n + 1):
       res = res * i
    return res</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>Cette documentation peut être exploitée avec la fonction <em><strong>help</strong></em> :</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>>>> help(fact)
Help on function fact in module __main__:

fact(n)
        paramètre n : (int) un entier
        valeur renvoyée : (int) la factorielle de n.

    CU : n >= 0

    Exemples :

    >>> fact(3)
    6
    >>> fact(5)
    120</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>À faire</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Utilisez Pyzo pour</p>
<!-- /wp:paragraph -->

<!-- wp:list {"ordered":true} -->
<ol><li>recopier la fonction<em><strong> fact </strong></em>avec sa docstring dans un fichier que vous nommerez <code>exples_doctest.py</code>,</li><li>et utiliser la fonction <strong><em>help </em></strong>au niveau de l'interpréteur.</li></ol>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>Réaliser une telle chaîne de documentation permet</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>à l'utilisateur de la fonction de savoir
<ul><li>à quoi peut servir la fonction ;</li><li>comment il peut l'utiliser ;</li><li>et quelles conditions il doit respecter pour l'utiliser (CU).</li></ul>
</li><li>et au programmeur de la fonction de préciser
<ul><li>le nombre et la nature de ses paramètres ;</li><li>la relation entre la valeur renvoyée et celle du ou des paramètres ;</li><li>ses idées avec quelques exemples.</li></ul>
(Tout cela bien entendu à condition que cette documentation soit rédigée
avant la réalisation du programme et non le contraire.)
</li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>Mais vous allez découvrir que cela permet davantage encore !</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>Utiliser le module  <em>doctest</em></h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Les exemples donnés dans une chaîne de documentation peuvent être testés à l'aide d'un module de Python nommé <em><strong>doctest</strong></em>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>À faire</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Depuis l'interpréteur (shell), dans lequel la fonction <strong><em>fact</em></strong> ci-dessus est supposée chargée, tapez les deux lignes</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>>>> import doctest</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>pour importer le module, et</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>>>> doctest.testmod()</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>Vous devez obtenir</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">&gt;&gt;&gt; doctest.testmod()
TestResults(failed=0, attempted=2)
</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>La fonction<em><strong> testmod </strong></em>du module <em><strong>doctest</strong></em> est allée chercher dans les docstring des fonctions du module actuellement chargé, c'est-à-dire <code>exples_doctest</code>, tous les exemples (reconnaissables à la présence des triples chevrons &gt;&gt;&gt;), et a vérifié que la fonction documentée satisfait bien ces exemples. Dans le cas présent, une seule fonction dont la documentation contient deux exemples (<code>attempted=2</code>) a été testée, et il n'y a eu aucun échec (<code>failed=0</code>).</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3>Et si un exemple et la fonction ne sont pas d'accord ?</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>À faire</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Modifiez le deuxième exemple, en mettant <strong><em> 121</em></strong> à la place de <strong><em>120</em></strong> dans le second exemple. Chargez le fichier dans l'interpréteur (touche F5) et retapez les deux lignes</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>>>> import doctest
>>> doctest.testmod()</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>Vous devez obtenir</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">&gt;&gt;&gt; doctest.testmod()
**********************************************************************
File "/home/eric/AP1/exples_doctest.py", line 24, in __main__.fact
Failed example:
    fact(5)
Expected:
    121
Got:
    120
**********************************************************************
1 items had failures:
   1 of   2 in __main__.fact
***Test Failed*** 1 failures.
</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>Qu'est ce que tout cela révèle ?</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>Tout d'abord que les tests ont échoué et qu'il y a eu 1 échec (cf dernière ligne) et que cet échec est dû à la fonction <strong><em>fact</em></strong> (cf avant dernière ligne).</li><li>Ensuite que le test incriminé est celui concernant <strong><em>fact(5)</em></strong> pour lequel le test a obtenu (<strong><em>Got</em></strong>) 120 en exécutant la fonction <strong><em>fact,</em></strong> alors qu'il attendait (<strong><em>Expected)</em></strong> 121 selon l'exemple donné par la documentation.</li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>Lorsqu'il y a de tels échecs, cela invite le programmeur à vérifier 
son programme,  … ou bien les exemples de sa documentation, comme c'est 
le cas ici.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3>Rendre automatique les tests</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Il est très facile de rendre automatique les tests et ainsi de ne plus avoir à faire appel explicitement (et manuellement) à la fonction <strong><em>te</em></strong><em><strong>stmod</strong></em>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Il suffit pour cela d'inclure en fin de fichier les trois lignes :</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">if __name__ == '__main__':
    import doctest
    doctest.testmod()
</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>À faire</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Ajoutez ces trois lignes à la fin du fichier <code>exple_doctest.py</code>
et exécutez-le ! (F5)
Faites le dans le cas d'un test erroné, et dans le cas sans erreur.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Que remarquez-vous dans le cas sans erreur ?</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3>Rendre les doctests bavards même en cas de succès</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Un paramètre optionnel de la fonction <strong><em>te</em></strong><em><strong>stmod</strong></em> permet d'obtenir plus d'informations sur les tests effectués mêmes en cas de succès.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Il suffit pour cela de rajouter le paramètre ̀`verbose=True`` :</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">doctest.testmod(verbose = True)
</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>À faire</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Faites-le !
Et observez ce que vous obtenez</p>
<!-- /wp:paragraph -->

<!-- wp:list {"ordered":true} -->
<ol><li>avec des exemples erronés</li><li>sans exemple erroné.</li></ol>
<!-- /wp:list -->

<!-- wp:heading -->
<h2>Les sorties complexes</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Tester les exemples des docstring avec le module <em><strong>doctest</strong></em> peut être source de déboires et de pièges. Vous allez découvrir certains d'entre eux et les remèdes qu'on peut y apporter.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3>Avec les listes</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Supposez que vous vouliez donner un exemple qui produit la liste
des factorielles des entiers de 0 à 5.
Vous avez donc complété votre documentation en ajoutant</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">"""
paramètre n : (int) un entier
valeur renvoyée : (int) la factorielle de n.


CU : n &gt;= 0

Exemples :

&gt;&gt;&gt; fact(3)
6
&gt;&gt;&gt; fact(5)
120

La liste des factorielles des entiers de
0 à 5
&gt;&gt;&gt; [fact(n) for n in range(6)]
[1,1,2,6,24,120]
"""
</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>Avertissement</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>La ligne blanche entre le deuxième exemple et la phrase qui
suit est absolument nécessaire. En son absence, la phrase sera comprise
comme faisant partie de la sortie produite par le deuxième exemple, et
le test échouera donc.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Il est clair que ce nouvel exemple est tout à fait correct.
Pourtant, si vous procédez au test vous constaterez que sur les trois exemples testés, l'un a abouti à un échec : le troisième.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>À faire</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Faites-le !</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Quel est le problème ? Cela vient du fait que la fonction<em><strong> testmode </strong></em>effectue une comparaison litérale entre la réponse fournie par la documentation (<em><strong>Expected</strong></em> ) et celle fournie par l'interpréteur (<em><strong>Got</strong></em>).</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>À faire</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Examinez attentivement ces deux points (<em><strong>Expected</strong></em> et <em><strong>Got)</strong></em> dans la réponse du test que vous venez d'effectuer.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Avez-vous compris ? Le problème, ce sont les espaces que l'interpréteur
place après chaque virgule dans l'énumération des éléments de la liste.
Dans la documentation, ils n'y sont pas.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Comment corriger ce point ?
C'est simple, il faut mettre des espaces entre les éléments d'une liste.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Mais ce n'est pas si simple. On peut facilement mettre plusieurs espaces,
comme ci-dessous :</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">"""
paramètre n : (int) un entier
valeur renvoyée : (int) la factorielle de n.

CU : n &gt;= 0

Exemples :

&gt;&gt;&gt; fact(3)
6
&gt;&gt;&gt; fact(5)
120

La liste des factorielles des entiers de
0 à 5
&gt;&gt;&gt; [fact(n) for n in range(6)]
[1,  1, 2,   6,  24,   120]
"""
</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>À faire</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Faites-le ! Testez !</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>L'excès d'espaces provoque des erreurs. Si on ajoute, sous forme d'un commentaire la directive  <em><strong>#doctest : </strong></em></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p><strong><em>+ NORMALIZE WHITESPACE</em></strong> , alors le test réussit, à condition néanmoins d'avoir mis au moins une espace après chaque virgule.</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">"""
paramètre n : (int) un entier
valeur renvoyée : (int) la factorielle de n.

CU : n &gt;= 0

Exemples :

&gt;&gt;&gt; fact (3)
6
&gt;&gt;&gt; fact (5)
120

La liste des factorielles des entiers de
0 à 5
&gt;&gt;&gt; [fact (n) for n in range (6)]
... # doctest: +NORMALIZE_WHITESPACE
[1,  1, 2,   6,  24,   120]
"""
</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>À faire</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Vérifiez-le !</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Avertissement</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>les trois petits points sous les trois chevrons sont indispensables.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Avec la directice supplémentaire <em><strong>+ELLIPSIS</strong></em> , on peut même se dispenser d'énumérer explicitement tous les éléments de la liste :</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">"""
paramètre n : (int) un entier
valeur renvoyée : (int) la factorielle de n.

CU : n &gt;= 0

Exemples :

&gt;&gt;&gt; fact(3)
6
&gt;&gt;&gt; fact(5)
120

La liste des factorielles des entiers de
0 à 5
&gt;&gt;&gt; [fact(n) for n in range(6)]
... # doctest: +NORMALIZE_WHITESPACE, +ELLIPSIS
[1,  ...,   24,   120]
"""
</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>À faire</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Vérifiez-le !</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3>Attention aux ensembles et dictionnaires</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Contrairement aux listes ou tuples, les ensembles et les dictionnaires ne sont pas des
structures de données séquentielles. Il est impossible de prévoir dans quel
ordre un interpréteur Python écrira les éléments de ces structures.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Par exemple, on peut très bien avoir</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">&gt;&gt;&gt; {'a', 'b'}
{'a', 'b'}
</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>comme on peut avoir</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">&gt;&gt;&gt; {'a', 'b'}
{'b', 'a'}
</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>Il est donc difficile d'illustrer une valeur d'un de ces deux types  dans un
exemple d'une docstring. Il est préférable de tester l'égalité de deux
valeurs <a href="http://www.fil.univ-lille1.fr/~L1S2API/CoursTP/tp_doctest.html#eq">[1]</a>  :</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">&gt;&gt;&gt; {'a', 'b'} == {'b', 'a'}
</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>Voici donc un exemple de ce qu'il est envisageable de placer dans une
docstring</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">Un dictionnaire de certaines valeurs de fact :
&gt;&gt;&gt; set (n for n in range(5)) == {0, 1, 2, 3, 4}
True
</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>À faire</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Vérifiez ce point !</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3>Avec des sorties aléatoires</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Comment tester des fonctions qui produisent des valeurs aléatoires ?</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Dans l'absolu, il est impossible de placer un exemple dans la docstring
donnant le résultat d'un appel à de telles fonctions  puisque les valeurs
qu'elles renvoient sont  imprévisibles.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Par exemple si on veut tester qu'une fonction simulant un dé à six faces
ne produit que des nombres compris entre 1 et 6, comment faire ?</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>On peut si on le souhaite vérifier que cette fonction ne renvoie que des nombres
compris entre 1 et 6.</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">from random import randrange

def de():
    """
        paramètre : aucun
    valeur renvoyée : (int) un nombre choisi au hasard compris entre
    1 et 6.

    CU : aucune

    Exemple :

    &gt;&gt;&gt; 1 &lt;= de() &lt;= 6
    True
    """
    return randrange(1,7)
</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>À faire</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Concevez un test qui vérifie 100 fois qu'aucun nombre produit par la fonction <strong><em>de </em></strong>n'est en dehors de l'intervalle [1,6]</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Mais un tel test <strong>ne prouve pas</strong> que jamais la fonction ne produira un nombre en dehors de
cet intervalle.</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>Méthodologie</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Note</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Pour chacun des fichiers de programmes Python que vous écrirez durant
 les séances de TP, ainsi que dans la réalisation du projet de fin de 
semestre, vous devrez</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>documenter toutes les fonctions avec une docstring donnant des exemples pertinents d'utilisation de ces fonctions
</li><li>ajouter les trois lignes de code suivantes en fin de fichier :
if __name__ == "__main__":
    import doctest
    doctest.testmod()


</li></ul>
<!-- /wp:list -->

<!-- wp:heading -->
<h2>Pour en savoir plus</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Voir la <a href="https://docs.python.org/3.4/library/doctest.html">documentation de Python</a>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Notes</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>merci à l'université de Lilles pour son cours <a href="http://www.fil.univ-lille1.fr/~L1S2API/CoursTP/index.html">Algorithmes et Programmation 1.</a></p>
<!-- /wp:paragraph -->

<!-- wp:table -->
<figure class="wp-block-table"><table><tbody><tr><td><a href="http://www.fil.univ-lille1.fr/~L1S2API/CoursTP/tp_doctest.html#id1">[1]</a></td><td>À condition qu'on puisse tester l'égalité des éléments de ces structures.</td></tr></tbody></table></figure>
<!-- /wp:table -->]]></content-encoded>
			<excerpt-encoded><![CDATA[]]></excerpt-encoded>
			<wp-post_id>2102</wp-post_id>
			<wp-post_date>2019-10-09 12:06:24</wp-post_date>
			<wp-post_date_gmt>2019-10-09 10:06:24</wp-post_date_gmt>
				</item>
</upm-export>
