Tester ses fonctions avec doctest


Chapitre 5,1


Le travail qui suit s’appuie sur la définition de la fonction kelvin_vers_celsius suivante :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def kelvin_vers_celsius(t: float) -> float:
    """ 
    Convertit la température donnée en kelvin en une température θ en degrés celsius.
    Relation : θ = t - 273.15.
    
    >>> kelvin_vers_celsius(0) -273.15
    >>> kelvin_vers_celsius(273.15) 0.0
    """
    offset = -273.15
    return t + offset

Première utilisation du module doctest

À quoi sert le module doctest ?

À faire

  1. Taper le code complet de la définition de la fonction kelvin_vers_celsius dans un fichier.

  2. Écrire, sur la première ligne du fichier, l’instruction :

1
import doctest

Enregistrer le fichier contenant le code précédent.

  1. Charger le fichier dans l’interpréteur. La fonction peut être appelée, rien de particulier n’apparaît pour l’instant.
1
2
>>> kelvin_vers_celsius(373.15)
100.0
  1. Entrer et exécuter l’instruction suivante :
1
2
>>> doctest.testmod()
TestResults(failed=0, attempted=2)

La fonction testmod du module doctest semble avoir effectué deux tests (attempted=2) sans avoir rencontré le moindre problème (failed=0).
Mais quels tests a-t-elle effectué ?

  1. Entrer et exécuter l’instruction suivante :
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
>>> doctest.testmod(verbose = True)
   Trying: 
     kelvin_vers_celsius(0) 
   Expecting: 
      -273.15 
   ok 
   Trying: 
      kelvin_vers_celsius(273.15) 
   Expecting: 
      0.0 
   ok 

La fonction testmod du module doctest a :

  • lu la documentation de la fonction kelvin_vers_celsius à la recherche de lignes débutant par >>> ;
  • exécuté les instructions de ces lignes ;
  • vérifié que le résultat retourné correspond bien à ce qui est écrit dans cette documentation.
  1. Modifier maintenant, dans la définition de la fonction kelvin_vers_celsius, la valeur 0.0 par 1.0. Charger à nouveau le fichier dans l’interpréteur et relancer la commande du point 5. ci-dessus.
    Que retourne la fonction testmod maintenant ? Ce message décrit-il précisément le problème ?
La fonction testmod du module doctest analyse la valeur retournée par une fonction à partir d’exemples données dans sa documentation.

Comment rendre l’analyse de la valeur retournée par une fonction automatique ?

  1. Effacer l’instruction import doctest de la ligne 1 du code.

  2. Inclure, à la fin du fichier (après la définition de toutes les fonctions), le bloc d’instructions suivant :

1
2
3
4
if __name__ == "__main__":

    import doctest 
    doctest.testmod()
  1. Lancer à nouveau le programme.
    La fonction testmod est lancée automatiquement et retourne la même erreur qu’au point 6 de la section 2.1 ci-dessus.

  2. Modifier maintenant, dans la documentation de la fonction kelvin_vers_celsius, la valeur 1.0 par 0.0.
    A-t-on la moindre indication que la fonction testmod a été lancée ?

Que faire lorsqu’on souhaite prendre en compte la mauvaise utilisation d’une fonction ?

  1. Remplacer la définition de la fonction kelvin_vers_celsius par celle-ci :
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
def kelvin_vers_celsius(t: float) -> float:

    """ Convertit la température donnée en kelvin en une
    température θ en degrés celsius. 
    Relation : θ = t - 273.15. 
    
    ERREUR si t est négative.
    
    >>> kelvin_vers_celsius(0) 
    -273.15
    >>> kelvin_vers_celsius(273.15) 
    0.0 
    """ 
    if t < 0: 
        raise ValueError("Température en kelvin doit être positive !")

    offset = -273.15 
    return t + offset

Quelle est la différence dans le comportement de la fonction ce code introduit-il ?

  1. Pour l’instant la documentation de la fonction ne comporte aucun exemple illustrant ce à quoi il faut s’attendre si on appelle la fonction avec un nombre négatif.

    1. Charger le fichier dans l’interpréteur.

    2. Écrire et exécuter l’instruction

    1
    
    >>> kelvin_vers_celsius(-5)
    

    On obtient

    1
    2
    3
    
    Traceback (most recent call last):
    ...
    ValueError: Température en kelvin doit être positive !
    
    1. Ce sont ces lignes qu’il faut ajouter à la documentation de la fonction
    1
    2
    3
    4
    5
    
    >>> kelvin_vers_celsius(-5)
    
    Traceback (most recent call last): 
    ...
    ValueError: Température en kelvin doit être positive !
    

    Compléter la documentation de la fonction et la tester.

À retenir

Pour chacune des fonctions, il faut

  1. Incorporer à sa documentation des exemples pertinents d’utilisation de ces fonctions ;

  2. Ajouter le bloc d’instruction suivant à la fin du fichier

1
2
3
if __name__ == "__main__":
    import doctest
    doctest.testmod()

Exercices

Exercice 1

Définir le prédicat est_egal dont une partie de la spécification est :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def est_egal(a: float, b: float) -> bool:
    """
    Teste l'égalité de 2 floats a et b : abs(a - b) <= epsilon avec
    epsilon = 1e-7
    
    >>> est_egal(0, 0.0) 
    xxx 
    >>> est_egal(1/49*49, 1) 
    xxx 
    """

Remplacer les xxx de façon à ce que la fonction testmod accepte votre définition.

Exercice 2

Définir la fonction inverse dont une partie de la spécification est :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
def inverse(x: float) -> float:
    """ Retourne l'inverse du nombre x.
    ERREUR si x est nul.

    >>> inverse(0) 
    Traceback (most recent call last):
    ZeroDivisionError: Division par 0 !!!
    >>> inverse(5) 
    xxx
    """

Remplacer les xxx de façon à ce que la fonction testmod accepte votre définition.


Suggestions de lecture :