18 - Spécification et tests

Dans ce chapitre, nous allons découvrir comment documenter correctement nos fonctions Python grâce aux prototypes, aux docstrings et aux tests. Les exercices correspondants se trouvent dans la fiche 15 - Spécification et tests .

Le prototype d’une fonction

Définition. Le prototype d’une fonction est la première ligne de sa définition. Il précise le nom de la fonction, les paramètres avec leurs types, et le type de retour.

Exemple. def aire_rectangle(longueur: float, largeur: float) -> float:

Cette fonction prend deux paramètres de type float et renvoie un float.

La docstring

Définition. Une docstring est une chaîne de documentation placée après le prototype. Elle documente ce que fait la fonction, ses paramètres et sa valeur de retour.

Voici la fonction aire_rectangle complétée avec une docstring.

def aire_rectangle(longueur: float, largeur: float) -> float:
    """Calcule l'aire d'un rectangle.
    Paramètres :
        longueur (float) : la longueur du rectangle.
        largeur (float) : la largeur du rectangle.
    Renvoie :
        float : l'aire du rectangle (longueur * largeur).
    """
    return longueur * largeur

Structure d’une docstring. Une docstring complète contient :

  1. une description brève ;
  2. les paramètres avec leurs types (section Paramètres :) ;
  3. la valeur de retour (section Renvoie :) ;
  4. des exemples (doctests, section Exemples :) ;
  5. les préconditions si nécessaire (section Préconditions :).

Les préconditions

Définition. Une précondition est une condition que doivent vérifier les paramètres pour que la fonction s’exécute correctement.

Exemples. Pour une fonction calculer_racine_carree(x: float) -> float, une précondition est que x doit être positif ou nul. Pour une fonction diviser(a: float, b: float) -> float, une précondition est que b doit être différent de 0.

Méthode : vérifier avec assert. On utilise l’instruction assert pour vérifier les préconditions :

assert condition, "message d'erreur"
def calculer_racine_carree(x: float) -> float:
    """Calcule la racine carrée d'un nombre."""
    assert x >= 0, "La racine carrée n'est définie que pour les nombres positifs."
    return x ** 0.5

Si on appelle calculer_racine_carree(-4), le programme s’arrête et affiche :

AssertionError: La racine carrée n'est définie que pour les nombres positifs.

Les doctests

Définition. Un doctest est un exemple d’utilisation inclus dans la docstring. Il commence par >>> suivi de l’instruction et du résultat attendu.

def aire_rectangle(longueur: float, largeur: float) -> float:
    """Calcule l'aire d'un rectangle.
    Paramètres :
        longueur (float) : la longueur du rectangle.
        largeur (float) : la largeur du rectangle.
    Renvoie :
        float : l'aire du rectangle.
    Exemples :
        >>> aire_rectangle(10.0, 5.0)
        50.0
        >>> aire_rectangle(7.0, 3.0)
        21.0
        >>> aire_rectangle(0.0, 10.0)
        0.0
    """
    assert longueur >= 0 and largeur >= 0, "Les dimensions doivent être positives."
    return longueur * largeur

Méthode : exécuter les doctests. Pour exécuter les doctests, on ajoute ce bloc à la fin du fichier Python :

if __name__ == "__main__":
    import doctest
    doctest.testmod(verbose=True)

Utilisation de bibliothèques

Définition. Une bibliothèque (ou module) est un fichier Python contenant des fonctions réutilisables comme math, random, etc.

Si vous avez besoin de calculer une racine carrée ou de générer un nombre aléatoire, vous n’avez pas besoin de réécrire ces fonctions. Vous utiliserez respectivement les bibliothèques math et random.

Méthode : importer une bibliothèque. Syntaxes possibles :

  • import math (importe tout le module) ;
  • from math import sqrt (importe seulement la fonction sqrt) ;
  • import math as m (importe le module en lui donnant un surnom).
# Utilisation 1 : import math
import math
print(math.sqrt(16)) # Affiche 4.0
print(math.pi)       # Affiche 3.14159...

# Utilisation 2 : from math import sqrt, pi
from math import sqrt, pi
print(sqrt(25)) # Affiche 5.0
print(pi)       # Affiche 3.14159...

# Utilisation 3 : import math as m
import math as m
print(m.sqrt(36)) # Affiche 6.0

Synthèse

Une fonction Python de qualité professionnelle contient :

  1. un prototype clair avec annotations de types ;
  2. une docstring complète (description, paramètres, renvoie, exemples) ;
  3. une vérification des préconditions avec assert ;
  4. des doctests variés (cas normaux, cas limites).