Aller au contenu
Réussir mon BTS SIO

Tape une notion, une commande ou le nom d'une épreuve.

Par exemple

Chapitre 1519 minIntermédiaire

Les tests à l'examen : E7 et E6 SLAM, exercices corrigés

Par Josselyn C., prof de BTS SIO. Mis à jour le .

À la fin de ce chapitre, tu sauras

  • lire et expliquer un test JUnit sur papier ;
  • écrire les tests d'une règle avec ses valeurs limites ;
  • éviter les pièges classiques des questions sur les tests ;
  • préparer les tests de ton évolution pour l'E6.

5 exercices corrigés

Au BTS SIO SLAM, les tests tombent à l'écrit E7 « Cybersécurité des services informatiques », où le sujet donne une classe de test à expliquer ou demande d'en écrire une, et à l'E6, où la commission attend des tests qui tournent et un test de non-régression pour l'évolution réalisée. Ce chapitre donne la méthode pour répondre sur papier, la syntaxe JUnit des sujets, les pièges classiques, puis des exercices corrigés au format de l'examen.

Où les tests apparaissent dans les épreuves

ÉpreuveCe qu'on te demande sur les testsOù t'entraîner
E7 SLAM (écrit de 4 h, U7)Expliquer les cas testés par une classe de test ; écrire un ou plusieurs tests d'une méthode ; trouver le cas manquant ; relier un test à une exigence de sécuritéCe chapitre, le chapitre Journalisation et tests de sécurité du cours E7
E6 SLAM (pratique et oral)Des tests automatisés qui tournent dans ton projet ; un test pour l'évolution demandée ; la non-régression ; parfois un rapport de testLes chapitres 7 et 8 du cours E6 SLAM
E5 (oral, bloc 1, les deux options)Des tests d'intégration et d'acceptation rédigés et effectués, et un rapport de test, pour un service mis à dispositionLe chapitre 14

Les sujets d'écrit des sessions 2022 à 2024, quand l'épreuve de cybersécurité s'appelait E6 (U6), restent d'excellents entraînements : les questions de tests y ont la même forme. En 2025, par exemple, le sujet donnait trois tests d'une méthode possedeDroit qui vérifie si un utilisateur a le droit de faire une opération sur une table : il fallait expliquer qu'ils couvraient une table absente des droits (refus), une table et une opération autorisées (accord), et une table connue avec une opération non autorisée (refus).

Lire un test JUnit sur papier

Les sujets d'E7 sont souvent écrits en Java, avec JUnit, parfois en PHP avec PHPUnit ou en C#. Tu n'as pas besoin de connaître Java en détail : les tests se lisent comme ceux de ce cours.

java
import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

class CompteUtilisateurTest {
    private CompteUtilisateur compte;

    @BeforeEach
    void setUp() {
        compte = new CompteUtilisateur();
    }

    @Test
    void test1() {
        for (int i = 0; i < 4; i++) {
            compte.enregistrerEchec();
        }
        assertFalse(compte.estVerrouille());
    }
}
Élément Java (JUnit 5)Équivalent dans ce coursSens
@Testtest(…) en Vitest, [Fact] en xUnit, #[Test] en PHPUnitCette méthode est un test
@BeforeEach (JUnit 4 : @Before) sur setUp()beforeEach, le constructeur xUnit, setUp() de PHPUnitExécutée avant chaque test : chaque test part d'un objet neuf
assertEquals(attendu, obtenu)expect(obtenu).toBe(attendu), Assert.Equal(attendu, obtenu)L'attendu d'abord
assertTrue(condition), assertFalse(condition)toBe(true), Assert.TrueLa condition doit être vraie, ou fausse
assertNull(x), assertNotNull(x)toBeNull()La valeur doit être nulle, ou non
assertThrows(Exception.class, () -> …)toThrow, Assert.ThrowsL'appel doit lever cette exception

La méthode pour une question de test

Pour expliquer des tests existants, réponds pour chaque test à trois questions, en une ou deux lignes :

  1. Quelle situation est préparée ? (dans setUp et au début du test)
  2. Quelle action est faite ? (l'appel de la méthode testée)
  3. Quel résultat est attendu, et ce qu'il prouve par rapport à la règle ?

Un tableau rend la réponse claire et rapide à corriger :

TestSituationActionAttenduCe qu'il prouve
test1Compte neuf4 échecs de connexionNon verrouilléLe verrouillage n'intervient pas avant le 5e échec

Pour écrire des tests, procède en quatre temps :

  1. Lis la règle dans le dossier documentaire et souligne les nombres, les « au plus », les « à partir de », les rôles.
  2. Liste les cas : le cas nominal, chaque cas refusé, et les valeurs limites de part et d'autre de chaque frontière (chapitre 3).
  3. Écris les tests dans le langage et le style du sujet : reprends les noms de classes et de méthodes des documents, un comportement par test, l'attendu calculé à la main.
  4. Justifie en une phrase par test ce qu'il vérifie.

Les pièges classiques à l'écrit

PiègeCe qui se passeLa parade
Ne tester que le cas qui marcheUn contrôle d'accès « testé » sans cas refusé ne prouve rienToujours au moins un cas refusé par règle
Oublier la valeur limite« 5 échecs » testé avec 10 échecs : la frontière n'est pas vérifiéeTester 4 et 5, pas 2 et 10
Inverser assertEqualsLe message d'échec annoncerait l'inverse ; le correcteur le remarqueassertEquals(attendu, obtenu)
Inventer des méthodesLe test appelle compte.reinitialiser(), qui n'existe pas dans les documentsUtiliser uniquement les classes et méthodes fournies
Plusieurs comportements dans un testUn seul test pour « verrouille et déverrouille et compte »Un test par comportement, avec un nom ou un commentaire clair
Un attendu recopié du codeSi le code est faux, le test confirme l'erreurCalculer l'attendu à partir de la règle du sujet
Oublier la préparationLe test utilise compte sans qu'il soit crééRappeler ce que fait setUp, ou créer l'objet dans le test

À l'E6 : ce que la commission regarde

À l'E6, la question n'est pas de réciter, mais de montrer. La commission vérifie :

  • que ton projet a des tests automatisés qui tournent, avec la commande dans le README (npm test, dotnet test, vendor/bin/phpunit) ;
  • que l'évolution demandée arrive avec ses tests : le cas nominal et au moins deux cas d'erreur (un test pour prouver un calcul et un contrôle d'accès) ;
  • qu'une correction arrive avec le test qui reproduit le bug, et que toute la suite reste verte (chapitre 11) ;
  • que tu sais expliquer un test, dire ce qu'il prouve et ce qui n'est pas testé ;
  • si l'expression des besoins le demande, que tu présentes un rapport de test (chapitre 14).

Exercices type examen

Exercice 1 sur 5 Expliquer les cas testés (type E7) Réussi À revoir

Une application de gestion verrouille un compte après 5 échecs de connexion consécutifs. Une connexion réussie remet le compteur d'échecs à zéro, sauf si le compte est déjà verrouillé : seul un administrateur peut alors le déverrouiller.

java
public class CompteUtilisateur {
    public static final int ECHECS_MAX = 5;

    private int nbEchecs = 0;
    private boolean verrouille = false;

    public void enregistrerEchec() {
        nbEchecs++;
        if (nbEchecs >= ECHECS_MAX) {
            verrouille = true;
        }
    }

    public void enregistrerSucces() {
        if (!verrouille) {
            nbEchecs = 0;
        }
    }

    public boolean estVerrouille() {
        return verrouille;
    }

    public int getNbEchecs() {
        return nbEchecs;
    }
}

La classe de test contient setUp et test1 (ci-dessus), et :

java
    @Test
    void test2() {
        for (int i = 0; i < 5; i++) {
            compte.enregistrerEchec();
        }
        assertTrue(compte.estVerrouille());
    }

    @Test
    void test3() {
        compte.enregistrerEchec();
        compte.enregistrerEchec();
        compte.enregistrerSucces();
        assertEquals(0, compte.getNbEchecs());
    }
  1. Explique les cas testés par test1, test2 et test3.
  2. Quelle règle de la spécification n'est pas testée ? Écris le test manquant en JUnit.
Voir la réponseMasquer la réponse de l'exercice 1

1.

TestSituation et actionAttenduCe qu'il prouve
test1Compte neuf, 4 échecsNon verrouilléLe compte n'est pas verrouillé avant le 5e échec (limite inférieure)
test2Compte neuf, 5 échecsVerrouilléLe verrouillage intervient au 5e échec exactement (limite)
test3Compte neuf, 2 échecs puis un succèsCompteur à 0Une connexion réussie remet le compteur à zéro tant que le compte n'est pas verrouillé

test1 et test2 encadrent la valeur limite : 4 échecs, pas de verrouillage ; 5 échecs, verrouillage.

  1. La règle « un succès ne déverrouille pas un compte verrouillé » n'est pas testée. C'est pourtant la plus importante pour la sécurité : sans elle, un attaquant qui finirait par trouver le mot de passe débloquerait le compte.
java
    @Test
    void test4() {
        for (int i = 0; i < 5; i++) {
            compte.enregistrerEchec();
        }
        compte.enregistrerSucces();
        assertTrue(compte.estVerrouille());
        assertEquals(5, compte.getNbEchecs());
    }

Le test vérifie que le compte reste verrouillé et que le compteur n'a pas été remis à zéro. Les boucles for sont courantes dans les sujets pour répéter une action ; dans un projet, on préférerait une petite méthode utilitaire echouer(n) pour garder le test lisible.

Tu avais trouvé ?

Exercice 2 sur 5 Écrire les tests d'une règle (type E7) Réussi À revoir

La politique de mots de passe de l'entreprise impose au moins 12 caractères, dont au moins un chiffre et au moins une lettre majuscule. La méthode statique PolitiqueMotDePasse.estRobuste(String mdp) renvoie true si le mot de passe respecte la politique, false sinon (y compris pour null).

Écris en JUnit une classe de test qui couvre la politique avec le minimum de tests pertinents, et justifie chaque test.

Voir la réponseMasquer la réponse de l'exercice 2
java
import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;

class PolitiqueMotDePasseTest {

    @Test
    void accepteDouzeCaracteresAvecChiffreEtMajuscule() {
        assertTrue(PolitiqueMotDePasse.estRobuste("Sorbier2027a"));
    }

    @Test
    void refuseOnzeCaracteres() {
        assertFalse(PolitiqueMotDePasse.estRobuste("Sorbier2027"));
    }

    @Test
    void refuseSansChiffre() {
        assertFalse(PolitiqueMotDePasse.estRobuste("SorbierLogistique"));
    }

    @Test
    void refuseSansMajuscule() {
        assertFalse(PolitiqueMotDePasse.estRobuste("sorbier2027abc"));
    }

    @Test
    void refuseNull() {
        assertFalse(PolitiqueMotDePasse.estRobuste(null));
    }
}
  • Le premier test est le cas nominal à la limite : exactement 12 caractères, avec un chiffre et une majuscule. Il prouve que 12 suffit.
  • Le deuxième est la limite de l'autre côté : 11 caractères, tout le reste valide. Il prouve que la longueur est vérifiée, et au bon seuil.
  • Les troisième et quatrième testent chaque condition seule : chaque mot de passe est assez long et ne manque que d'une chose. Un mot de passe trop court et sans chiffre ne dirait pas laquelle des deux règles a provoqué le refus.
  • Le dernier vérifie le cas null, prévu par la spécification.

Tu avais trouvé ?

Exercice 3 sur 5 Le code ou le test ? (type E6) Réussi À revoir

Pendant l'E6, ton test échoue :

text
FAIL  src/export.test.js > refuse l'export à un salarié
AssertionError: expected 401 to be 403

Le test envoie la requête avec le jeton d'un salarié, et l'API répond 401. La commission te demande si le problème vient du code ou du test. Comment le déterminer, et que réponds-tu dans chacun des deux cas ?

Voir la réponseMasquer la réponse de l'exercice 3

401 signifie « non authentifié » : l'API n'a pas reconnu l'appelant. 403 signifie « authentifié mais pas autorisé ». Le salarié devrait être reconnu, puis refusé : l'attendu 403 est le bon, d'après les conventions HTTP.

Pour trancher, on regarde pourquoi l'authentification échoue :

  • si le test fabrique mal le jeton (secret de test absent, en-tête mal écrit comme Bearer oublié), c'est le test qui est faux : « Le jeton de test n'était pas valide ; je le corrige, le test passe à 403, ce qui prouve que la route refuse bien les salariés » ;
  • si le jeton est valide mais que la route vérifie le rôle avant l'authentification, ou renvoie 401 pour un mauvais rôle, c'est le code : « La route renvoie 401 au lieu de 403 pour un rôle insuffisant ; je corrige le code de statut dans le middleware, et je relance toute la suite pour vérifier la non-régression ».

Dans les deux cas, on ne modifie pas l'attendu pour « faire passer » le test : on cherche qui a raison à partir de la règle (ici, la sémantique des codes HTTP), puis on corrige ce qui est faux.

Tu avais trouvé ?

Exercice 4 sur 5 Vocabulaire (questions de cours) Réussi À revoir

Réponds en une ou deux phrases.

  1. Quelle est la différence entre un test unitaire et un test d'intégration ?
  2. Qu'est-ce qu'un test de non-régression ?
  3. Qu'est-ce qu'un mock ?
  4. Pourquoi une couverture de code de 100 % ne garantit-elle pas l'absence de bug ?
  5. À quoi sert un cahier de recette ?
Voir la réponseMasquer la réponse de l'exercice 4
  1. Un test unitaire vérifie une unité de code (une méthode, une classe) isolée de ses dépendances, en quelques millisecondes ; un test d'intégration vérifie que plusieurs composants fonctionnent ensemble (une route, ses middlewares et la base, par exemple).
  2. C'est le fait de rejouer, après chaque modification, les tests qui passaient avant, pour vérifier que la modification n'a rien cassé. Après chaque bug corrigé, on ajoute le test qui l'aurait détecté.
  3. Une doublure de test qui remplace une dépendance et vérifie que le code testé l'appelle comme prévu (par exemple, qu'un courriel est envoyé à la bonne adresse), sans effet réel.
  4. La couverture mesure les lignes exécutées par les tests, pas les résultats vérifiés : un test sans assertion ou sans valeur limite couvre le code sans détecter ses erreurs, et une règle absente du code n'apparaît dans aucune mesure.
  5. Il liste les cas de test qui vérifient chaque exigence (préconditions, étapes, résultat attendu) ; la MOA le déroule pendant la recette pour décider si elle accepte la livraison.

Tu avais trouvé ?

Exercice 5 sur 5 Préparer les tests d'une évolution (type E6) Réussi À revoir

Expression des besoins : « Ajoutez à Prêt'Matos la possibilité, pour la logistique, de marquer un matériel "en réparation". Un matériel en réparation ne peut plus être réservé. Les réservations déjà faites sur ce matériel sont conservées, mais la logistique en voit la liste pour prévenir les salariés. »

Pendant la phase de préparation, liste les tests que tu écriras (niveau, situation, résultat attendu), en commençant par les plus importants.

Voir la réponseMasquer la réponse de l'exercice 5
OrdreNiveauSituationRésultat attendu
1UnitaireDemande de réservation d'un matériel en réparationRefusée, motif « matériel en réparation »
2UnitaireDemande sur un autre matériel, disponibleAcceptée (la règle ne touche que le matériel concerné)
3IntégrationLa logistique marque PC-07 en réparation200 ; PC-07 apparaît « en réparation »
4Intégration (sécurité)Un salarié tente de marquer un matériel en réparation403 ; état inchangé
5IntégrationPOST /api/reservations sur un matériel en réparationRefus (409, conflit avec l'état du matériel) ; aucune réservation ajoutée
6IntégrationPC-07 a deux réservations futures, puis passe en réparationLes deux réservations existent toujours ; la liste des réservations concernées les renvoie à la logistique
7Non-régressionToute la suite existanteVerte

Les tests 1 et 2 fixent la règle ; 4 est le test de droits, indispensable ; 6 vérifie l'exigence la plus facile à oublier, la conservation des réservations existantes. Si le temps manque, on garde 1, 4, 5 et 7, et on annonce les autres comme « à écrire » dans le rapport.

Tu avais trouvé ?

Chapitre terminé !

Fais les 5 exercices avant de passer à la suite : c'est en t'entraînant que tout se fixe.

chapitres
–
de série
–
du cours
–
Cours suivant : Maintenance applicativeRevoir le sommaire du cours