4.4. Mise au point des programmes, gestion des bugs#

Lors de la conception d’un programme, par exemple dans le cadre d’un projet, on rencontre régulièrement des bogues [1] qui perturbent le déroulement d’un programme.

Contenus

Capacités attendues

Commentaires

Mise au point des programmes.

Gestion des bugs.

Dans la pratique de la programmation, savoir répondre aux causes typiques de bugs : problèmes liés au typage, effets de bord non désirés, débordements dans les tableaux, instruction conditionnelle non exhaustive, choix des inégalités, comparaisons et calculs entre flottants, mauvais nommage des variables, etc.

On prolonge le travail entrepris en classe de première sur l’utilisation de la spécification, des assertions, de la documentation des programmes et de la construction de jeux de tests.

Les élèves apprennent progressivement à anticiper leurs erreurs.

4.4.1. Différents types de bogues#

On peut rencontrer plusieurs types de bogues, on va essayer de lister les plus communs ici.

4.4.1.1. Bogues liées au typage#

Considérons une fonction addition, dont la définition est cachée dans un module (on y a pas accès). Suite à une lecture rapide de la documentation, on écrit :

addition("1","2")

La fonction addition s’exécute sans lever d’exception, c’est-à-dire sans problème apparent, mais le résultat de cette fonction est “12”, ce qui n’est pas conforme à ce qu’on attend d’une addition.

Proposer un test pour valider l’usage de cette fonction.

4.4.1.2. Bogues liés à des effets de bords#

Considérons l’extrait de code suivant, «optimisé» pour s’éxécuter plus rapidement.

def mystere():
  L.sort()
  for i in L:
    return i == 1


def autre_fonction():
  assert L == [3,2,1]
L = [3,2,1]
mystere()
autre_fonction()
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
Cell In[4], line 3
      1 L = [3,2,1]
      2 mystere()
----> 3 autre_fonction()

Cell In[3], line 8, in autre_fonction()
      7 def autre_fonction():
----> 8   assert L == [3,2,1]

AssertionError: 

Expliquer ce qui s’est passé et qui fait échouer la fonction autre_fonction.

Proposer un test qui permet de mettre ce comportement en évidence.

4.4.1.3. Bogues liés à un «débordement» de tableau#

On considère le code suivant :

def parcours_liste(L):
  for i in range(1,len(L) + 1):
    return i == L[i]

Expliquer ce qui s’est passé et qui fait échouer la fonction parcours_liste.

Proposer un test qui permet de mettre ce comportement en évidence.

4.4.1.4. Bogues liés à des instructions conditionnelles non exhaustives#

On considère le code suivant :

def menu(entree):
  if entree == 'm':
    pass
  elif entree == 'g':
    pass
  elif entree == 'h':
    pass

On suppose que cette fonction reçoit en entrée une touche tapée par l’utilisateur au clavier.

Expliquer ce qui peut faire échouer la fonction menu.

Proposer un test qui permet de mettre ce comportement en évidence.

4.4.1.5. Bogues liés à une «erreur d’arrondi sur les float»#

On considère le code suivant :

def assert_egal(a, b):
  return a == b

assert_egal(0.2*0.2, 0.04)
False

Expliquer ce qui s’est passé et qui fait échouer la fonction assert_egal.

Proposer un test qui permet de mettre ce comportement en évidence.

4.4.2. Principes basiques de développement#

On va présenter ici une méthode basée sur le TDD.

4.4.2.1. Utilisation de gitlab#

Dans le cadre de la collaboration pour un projet, il est usuel d’utiliser une forge [2] comme Gitlab

Une fois le projet créé, on a accès à l’interface suivante :

Interface principale de Gitlab

Lorsqu’on rencontre un problème lors de la phase de développement ou d’exploitation, on peut signaler un ticket :

Interface de vue des tickets de Gitlab

On peut retrouver les tickets déjà ouverts par d’autres personnes, et si le bogue est nouveau, le signaler sous la forme d’un nouveau ticket :

Interface de saisie d'un ticket de Gitlab

4.4.2.2. Principe basique du TDD#

Dans la phase de conception ou dans la phase d’exploitation, on peut suivre le schéma suivant :

flowchart LR x[1. Découverte d'un bug] --> y[2. Écriture d'un test] y --> z[3. Correction] z --> x

On a donc le schéma suivant :

  1. On découvre un bug (ou on souhaite ajouter une nouvelle fonctionnalité). On écrit la spécification dans le ticket.

  2. On écrit un ou des tests permettant de mettre en évidence le problème (ou la fonctionnalité manquante). À ce stade là, le nouveau jeu de test doit être invalide

  3. On écrit un correctif (ou un apport). À ce stade, le jeu de test doit devenir valide.