C16.5 : Jeu de tests d'une fonction

De quoi parle-t-on ?

Exemple

Supposons qu'on dispose d'une fonction prod(a:int, b:int) -> int qui prend deux entiers en paramètres et renvoie le produit de ces deux entiers.

Question : Quelles valeurs de a et de b serait-il judicieux de tester pour s'assurer que la fonction prod a été bien programmée ?

A connaitre

Vocabulaire

L'ensemble des valeurs que l'on utilise pour tester une fonction s'appelle un "jeu de tests".

Les qualités d'un bon jeu de tests

On bon jeu de tests doit couvrir au mieux toutes les situations possibles d'exécution de la fonction.

On pensera en particulier aux situations suivantes :

  • - pour les entiers : le zero, les entiers positifs et négatifs...
  • - pour les listes : la liste vide, des listes de tailles différentes...
  • - ...

Application

On considère une fonction qui prend une liste d'entiers en paramètres et renvoie le nombre de 0 que contient la liste.

Proposer un jeu de tests pour cette fonction.

Afficher la correction

Cas où la fonction renvoie 0. On n'oublie pas la liste vide.

  • []
  • [1]
  • [1, 8]

Cas où la fonction renvoie 1. Il est utile de tester le cas où le 0 est en début, au milieu et en fin de liste (pour tester les extrémités des boucles).

  • [0]
  • [0, 1]
  • [1, 0]
  • [1, 0, 8]

Cas où la fonction renvoie 2.

  • [0, 0]
  • [0, 0, 1]
  • [0, 1, 0]
  • [1, 0, 0]
  • [1, 0, 0, 1]

Utilisation de doctests

Exemple

A faire :

1) Tester le code ci-dessous et analyser l'affichage de la ligne de commande :

def prod(a:int, b:int) -> int:
    """
    Renvoie le produit de deux nombres
    Paramètres :
        a : (int) un entier
        b : (int) un entier
    Valeur renvoyée :
        (int) le produit de a et b.

    Exemples :
        >>> prod(3,2)
        6
        >>> prod(-2,5)
        -10
    """
    return a * b

# Programme principal
import doctest
doctest.testmod(verbose = True)

2) Compléter le jeu de tests.

Applications

Application 1

Proposer une fonction prod(a:int, b:int) -> int (avec un jeu de test pertinent) qui prend deux nombres entiers en paramètres et renvoie le produit de ces deux nombres. Le code proposé ne devra pas utiliser l'opérateur *.

Afficher la correction
def prod(a:int, b:int) -> int:
    """
    Renvoie le produit de deux nombres
    Paramètres :
        a : (int) un entier
        b : (int) un entier
    Valeur renvoyée :
        (int) le produit de a et b.

    Exemples :
        >>> prod(3,2)
        6
        >>> prod(-3,2)
        -6
        >>> prod(3,-2)
        -6
        >>> prod(-3,-2)
        6
        >>> prod(3,0)
        0
        >>> prod(0,2)
        0
        >>> prod(0,0)
        0
    """
    p = 0
    if a >= 0:
        for _ in range(a):
            p = p + b
        return p
    else:
        for _ in range(-a):
            p = p + b
        return -p

# Programme principal
import doctest
doctest.testmod(verbose = True)

Application 2

On souhaite disposer d'une fonction mini3(a, b, c) qui prend trois nombres en paramètre et renvoie le plus petit des trois.

1) Proposer un jeu de tests pertinent pour cette fonction.

2) Écrire le code d'une telle fonction, avec une docstring et des doctests. Le code proposé ne devra utiliser ni la fonction min, ni la méthode sort.

Afficher la correction
def mini3(a, b, c):
    """
    Renvoi le plus grand de a, b et c
    Paramètres :
        a : (int) ou (float)
        b : (int) ou (float)
        c : (int) ou (float)
    Valeur renvoyée :
        (int) ou (float) le plus grand de a, b ou c.

    Exemples :
        >>> mini3(1, 2, 3)
        1
        >>> mini3(1, 3, 1)
        1
        >>> mini3(3, 1, 2)
        1
        >>> mini3(2, 1, 3)
        1
        >>> mini3(3, 2, 1)
        1
        >>> mini3(2, 3, 1)
        1
    """
    if a <= b and a <= c:
        return a
    elif b <= c:
        return b
    else:
        return c

# Programme principal
import doctest
doctest.testmod(verbose = True)

Application 3

Écrire le code d'une fonction (avec une docstring et des doctests) qui prend une liste d'entiers en paramètre et renvoie la somme des nombres de cette liste. La liste passée en paramètre pourra être vide, dans ce cas la fonction renverra 0.

Afficher la correction
def som_list(l):
    """
    Renvoi la somme des valeurs d'une liste d'entiers, 0 si la liste est vide.
    Paramètres :
        l : (list) liste d'entiers
    Valeur renvoyée :
        (int) la somme des valeurs de l.

    Exemples :
        >>> som_list([])
        0
        >>> som_list([8])
        8
        >>> som_list([-2, 5])
        3
    """
    # Teste si la liste est vide
    if l == []:
        return 0
    # Calecule la somme des valeurs
    s = 0
    for val in l:
        s = s + val
    return s

# Programme principal
import doctest
doctest.testmod(verbose = True)

Utilisation des assertions

Application n° 1 (sur papier)

def prod(a, b):
    return a*b

def fct():
    assert prod(3,5) == 15
    assert prod(-3,5) == -15
    assert prod(3,-5) == -15
    assert prod(-3,-5) == 15
    print('Les tests sont validés')

# Programme principal
teste_prod()

1. Expliquer les lignes 5 à 8.

2. Expliquer le rôle de la fonction fct lui donner un nom parlant.

3. Compléter le jeu de tests pour qu'il soit plus complet.

Afficher la correction

1. Les lignes 5 à 8 permettent de tester la fonction prod

2. La fonction fct permet de tester la fonction prod. on pourrait l'appeler texte_prod.

3. On pourra ajouter les deux tests suivants :

assert prod(0, 5) == 0
assert prod(-3, 0) == 0

Application n° 2

Écrire une fonction positifs qui prend une liste d'entiers en paramètre et renvoie une liste contenant les mêmes éléments, dans le même ordre, en ne gardant que les entiers strictement positifs. La liste passée en paramètre pourra être vide.

Écrire une fonction qui permet de tester la fonction positifs avec un jeu de tests sous forme d'assertions de façon à tester cette fonction.

Afficher la correction
def positifs(l):
    """
    Renvoie une liste en ne gardant que les entiers positifs.
    Paramètres :
        l : (list) liste d'entiers
    Valeur renvoyée :
        (list).
    """
    l2 = []
    for val in l:
        if val > 0:
            l2.append(val)
    return l2

def teste_positifs():
    assert positifs([]) == []
    assert positifs([8]) == [8]
    assert positifs([-5]) == []
    assert positifs([0]) == []
    assert positifs([8, 5]) == [8, 5]
    assert positifs([-3, 5]) == [5]
    assert positifs([-4, -5]) == []
    print('Les tests sont validés')

# Programme principal
teste_positifs()