Contactez-nous

Utiliser des assertions (assert) pour valider les préconditions

Découvrez l'instruction 'assert' en Python, un outil puissant pour valider les préconditions, les postconditions et les invariants dans votre code. Détectez les erreurs de logique au plus tôt et facilitez le débogage.

Qu'est-ce qu'une assertion ? Vérifier une condition

En programmation, une assertion est une instruction qui vérifie qu'une condition est vraie à un point précis du code. Si la condition est fausse, une erreur est signalée (en Python, une exception `AssertionError` est levée).

Les assertions sont utilisées pour détecter les erreurs de logique *pendant le développement*. Elles permettent de s'assurer que les hypothèses que vous faites sur l'état de votre programme sont correctes.

Les assertions ne sont *pas* destinées à gérer les erreurs d'exécution normales (comme les erreurs de saisie utilisateur, les fichiers manquants, etc.). Pour cela, utilisez des blocs `try...except`.

Les assertions sont des outils de *débogage* et de *test*. Elles ne doivent pas être utilisées pour valider des données d'entrée dans un programme en production (voir plus loin).

Syntaxe de l'instruction assert : assert condition, message

L'instruction `assert` a la syntaxe suivante :

assert condition, message  # Le message est optionnel
  • `assert` : Le mot-clé qui introduit l'assertion.
  • `condition` : Une expression booléenne qui est évaluée. Si la condition est `True`, l'assertion ne fait rien. Si la condition est `False`, une `AssertionError` est levée.
  • `message` : (Optionnel) Une chaîne de caractères qui sera affichée si l'assertion échoue (si la condition est `False`). Ce message permet d'expliquer pourquoi l'assertion a échoué.

Exemples :

x = 5
assert x > 0  # Pas d'erreur, car x est positif

# assert x > 10  # Lèverait une AssertionError, car x n'est pas supérieur à 10

y = -2
assert y >= 0, "y doit être positif ou nul"  # Lève une AssertionError avec le message spécifié

Si l'assertion échoue (la condition est `False`), le programme s'arrête avec une `AssertionError` (sauf si elle est capturée par un bloc `try...except`, ce qui est généralement déconseillé pour les assertions).

Le message d'erreur, s'il est fourni, est inclus dans l'exception `AssertionError`.

Utilisations des assertions : préconditions, postconditions, invariants

Les assertions sont utilisées pour valider différentes hypothèses dans le code :

  • Préconditions : Conditions qui doivent être vraies *avant* l'exécution d'une fonction ou d'un bloc de code. Par exemple, vous pouvez vérifier que les arguments d'une fonction ont des types et des valeurs valides.
  • Postconditions : Conditions qui doivent être vraies *après* l'exécution d'une fonction ou d'un bloc de code. Par exemple, vous pouvez vérifier que la valeur de retour d'une fonction est correcte.
  • Invariants : Conditions qui doivent être vraies *tout au long* de l'exécution d'une boucle ou d'une structure de données. Par exemple, vous pouvez vérifier que la taille d'une liste reste dans une certaine plage.

Exemple (précondition) :

def diviser(a, b):
    assert b != 0, "Le diviseur ne peut pas être zéro"  # Précondition
    return a / b

Exemple (postcondition) :

def calculer_carre(x):
    resultat = x * x
    assert resultat >= 0, "Le carré doit être positif ou nul"  # Postcondition
    return resultat

Exemple (invariant de boucle) :

def tri_insertion(liste):
  for i in range(1, len(liste)):
    cle = liste[i]
    j = i - 1
    while j>= 0 and liste[j] > cle:
      liste[j+1] = liste[j]
      j -= 1
      assert j >= -1 and j < i #Invariant de boucle.
    liste[j+1] = cle

Les assertions permettent de détecter les erreurs de logique le plus tôt possible, ce qui facilite le débogage.

Assertions et tests : un complément, pas un remplacement

Les assertions sont utiles pour le débogage et pour vérifier la cohérence interne du code, mais elles ne remplacent pas les tests (en particulier les tests unitaires).

Les assertions sont généralement utilisées pour vérifier des conditions qui *devraient toujours être vraies* si le code est correct. Elles sont une forme d'auto-vérification du code.

Les tests, en revanche, sont utilisés pour vérifier que le code se comporte comme prévu dans différents cas d'utilisation, y compris les cas limites et les cas d'erreur *attendus*.

Les assertions et les tests sont complémentaires : les assertions aident à détecter les erreurs de logique *internes* au code, tandis que les tests vérifient le comportement *externe* du code.

Il est recommandé d'utiliser à la fois des assertions et des tests pour garantir la qualité du code.

Désactiver les assertions : l'option -O

Il est possible de désactiver les assertions en exécutant Python avec l'option `-O` (optimisation) :

python -O mon_script.py

Lorsque les assertions sont désactivées, les instructions `assert` sont ignorées. Cela peut améliorer légèrement les performances, mais cela supprime également les vérifications de cohérence.

Il est généralement *déconseillé* de désactiver les assertions dans le code de production, sauf si vous êtes absolument certain que le code est correct et que les gains de performance sont significatifs.

Les assertions sont un outil de développement et de débogage, et elles doivent généralement rester activées, même en production, car elles permettent de détecter des erreurs qui pourraient autrement passer inaperçues.

Il ne faut *jamais* utiliser les assertions pour valider des données utilisateur, car l'utilisateur pourrait désactiver les assertions et ainsi contourner les validations.

Si vous voulez valider des données utilisateur ou gérer des erreurs d'exécution attendues, utilisez des blocs `try...except`.