PACT GL 3/3

PACT Encadrement Informatique

Déroulement de la séance

  • Introduction à la notion de “test” (obligatoire pour tous les modules)
    • Atelier: préparation des tests
    • Quelques bonnes pratiques de structuration du code pour le test
      • Interfaces graphiques
      • Clients/serveurs
      • Capteurs
  • Retour sur le débuggage d’un programme
    • Le débuggage simple par “logging”
    • Le débuggage avec un environnement de développement

Pourquoi tester ?

  • pour être sûr que le programme marche
    • parce qu’un programme ne marche jamais du premier coup
    • il y a toujours un cas auquel vous n’avez pas pensé
    • il arrive des cas que vous pensez impossible
    • vous ne pouvez pas penser à tout, personne ne peut
  • pour que le programme continue à marcher quand vous le modifiez
    • à chaque changement, il faut retester
    • à chaque changement, une régression est possible
  • intention du test niveau projet
    • faciliter la tâche des intégrateurs
    • permettre de démontrer le fonctionnement de bout en bout du projet
    • évaluer les performances de bout en bout du projet
    • permettre aux experts, encadrants GL et jurys d’évaluer le degré de réflexion sur votre module
  • bonnes pratiques:
    • avoir des exemples d’entrées/sorties de chaque module
    • s’assurer qu’il se branche bien avec un autre module développé par un autre élève

Qu’est-ce qu’il faut tester ?

  • Chaque module
    • testé par les responsables du module
  • Les combinaisons de modules
    • testées par les responsables “Tests et Intégration”)
  • Quel pré-requis minimaux pour tester?
    • quelles données sont nécessaires pour faire le test?
    • quelles fonctionnalités peuvent être testées très tôt?
  • Nécessité des tests et conception d’un plan de test dès le début d’un projet

Types de tests

  • Tests de composants (ou tests unitaires)
    • Tests de l’implémentation de chaque composante du projet par les développeurs ou équipes de testeurs du projet.
    • est-ce que le module accepte les entrées normales ?
    • est-ce que le module refuse sans crasher des entrées anormales ?
    • est-ce que le module se comporte bien quand il plante ?
    • est-ce que le module produit des sorties au bon format ?
    • est-ce que le module produit la bonne sortie pour une entrée donnée ?
  • Tests d’intégration
    • Tests de la conception du logiciel par l’équipe d’intégration
    • Tests progressifs de l’assemblage de composants (tests des interfaces entre composant)
    • si les modules A et B sont chacun testés OK, est-ce que les tests de A+B fonctionnent ?
  • Validation
    • Tests des fonctionnalités de l’ensemble du logiciel (y compris documentation, évolutivité …)
    • Validation = réponse à un cas pertinent
  • Tests de résistance à l’effet démo = on met n’importe quoi en entrée et ça fait une erreur claire sans crash
  • Il y a beaucoup de types de test…

Quand tester

  • Avant de livrer un module aux responsables “Test et intégration”: OBLIGATOIRE
  • Avant de livrer le prototype allégé et le prototype final: OBLIGATOIRE
  • Le plus souvent possible
    • Possibilité d’automatiser le test: ex: chaque commit git déclenche le test

Méthodes de test

  • Tests de fonctionnement
    • Boîte blanche
      • tester en connaissant le code des modules
      • tester pour le plus de cas possibles en fonction des “if” dans le code,
      • il est parfois possible de tester tous les chemins
      • qui: les concepteurs d’un module
    • Boîte noire
      • tester sans connaître le code interne, juste avec les spécifications d’un module
      • le test complet n’est jamais possible, il faut estimer un taux de couverture du test
      • vérifier que les couples (valeur d’entrée, valeur de sortie) sont bons
      • exemple: un test par fonction possible, un test par paramètre possible, tests avec des valeurs aléatoires,…,
      • qui: les intégrateurs pour un assemblage de modules

Autres méthodes de test

  • Tests de performance
    • mesurer et enregistrer (log) le temps passé dans chaque module et le temps total
    • qui: les developpeurs d’un module
  • Tests d’acceptabilité
    • mettre des utilisateurs réels (externes au projet) devant le résultat du projet
    • le programme peut très bien donner la bonne réponse mais ne pas passer le test quand même
      • interface d’entrée incompréhensible ou incomplête
      • temps de réaction trop long
      • message de sortie incompréhensible ou incomplet ou noyé dans les infos de debug
    • qui: les intégrateurs

Intégration

  • Qu’est-ce que l’intégration ?
    • la mise en commun de code développé par les différents groupes
  • Quand faire l’intégration ?
    • Le plus souvent possible, intégration continue
    • à faire progressivement, lors de la mise à disposition des versions de module
    • Au moins avant chaque PAN (à partir du PAN2) pour fournir des résultats
      • PAN3: démontrer et évaluer le prototype allégé
      • PAN4: démontrer et évaluer le prototype final
  • Comment faire l’intégration ?
    • en faisant fonctionner ensemble le code de plusieurs modules
    • en concevant et en exécutant des tests d’intégration
      • programmes qui permettent de tester le fonctionnement conjoint de plusieurs modules

Processus de test (…)

  • Planifier les tests: faire le plan, vision globale des tests
  • Spécifier les tests (vision en détail de chaque test)
    • nature des tests et parties sur lesquelles ils porteront
    • description (texte) des entrées
    • description (texte) des tests à faire sur les sorties
  • Concevoir les tests
    • décrire le scénario de test, si le test comporte plusieurs étapes
    • écrire le programme de validation des données en sortie, par exemple comparer avec une image de référence et donner le nombre max admissible de pixels différents
    • créer les jeux de données pour les tests (entrées, sorties)
  • Toutes ces informations font partie du plan de test qui doit être rendu pour le PAN2
  • Certaines de ces étapes peuvent être très simples, selon les cas

Processus de test (suite)

  • Créer les classes de test
    • Note: un programme de test est une classe avec une méthode main, vous pouvez en avoir autant que vous voulez.
    • écrire le code qui positionne les entrées et appelle la fonction
    • écrire le code qui teste les sorties
    • Note: ce code fait partie des rendus et doit être dans le dépôt git, même s’il ne sert pas directement dans le projet final
  • Définir les conditions d’arrêt d’une campagne de tests
  • Garder une trace des tests appliqués dans votre rapport
    • Quel test
    • Appliqué quand
    • Sur quelle version du projet
    • Avec quel résultat et quelle conséquence

Bonnes pratiques de structuration

  • Quand il y a une interface graphique:
    • sur PC, le système doit pouvoir fonctionner (au moins dans une version simple) en ligne de commande: vous donnez les instructions d’execution par des options en ligne de commande plutôt qu’en utilisant l’interface graphique.
    • sur Android, si une partie du code est écrite d’abord sur PC, alors une version PC de test de l’application devrait exister.
      Cela a pour but de bien séparer le code Android-specifique du reste.
      Attention à la gestion du dépôt git pour partager le code.
  • De manière générale, cela a pour but de bien séparer l’interface graphique du reste du code (MVC) pour faciliter le test.

Bonnes pratiques de structuration

  • Quand il y a un serveur:
    • Le serveur doit pouvoir fonctionner à partir d’un fichier pour simuler des requêtes entrantes.
    • Ce fichier peut être généré par le serveur quand un client lui envoie des messages de façon à pouvoir reproduire le test sans le client.
    • Cela sépare également bien le code “réseau” du code “back-end”. De ce fait, le logging devient presque obligatoire.

Ce qu’il faut rajouter à un serveur pour le tester est donc:

  • une option d’écrire dans un fichier tous les messages reçus du client et tous les messages renvoyés par le serveur au client: ceci est un fichier de log qui permet déjà de détecter par lecture certaines erreurs
  • une option de relire un fichier de log pour faire comme si le serveur était connecté à un client, et le serveur peut vérifier lui-même que la nouvelle réponse est bien la même que celle qu’il a envoyée lors de la création du fichier log

Bonnes pratiques de structuration

  • Quand il y a un capteur:
    • Le capteur doit pouvoir être remplacé par un fichier simulant les données, pour tester sans la présence d’un capteur.
    • De même, que pour le serveur, cela signifie qu’on est capable de créer des fichiers en loggant les données reçues par un vrai capteur.

Et donc pour tester un capteur, il faut ajouter:

  • une option qui écrit dans un fichier de capture tout ce qui est envoyé par le capteur
  • une option qui, en l’absence d’un capteur, relit un fichier de capture pour simuler la présence d’un capteur, et qui peut être utilisé pour tester un autre module avec toujours les mêmes entrées.

Atelier

Plan de test de votre projet

  • Test par module
    • Liste de tous les cas à tester
    • Quelles données en entrée
    • Environnement du test: quel contexte
    • Evaluation du test: quelle sortie attendue
  • Test d’intégration …
  • Test de validation

Logging

  • Pour comprendre ce que fait son programme
  • Exposer des détails d’exécution sous forme de message texte sur une console
  • Changer la quantité de messages sans recompiler
  • Avoir les mêmes messages en création et en production
  • Utiliser un unique framework

In the beginning…

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println(“Hello world!”);
    }
}
                    
  • Problèmes avec System.out.println
    • quand il y en a beaucoup, comment retrouver d’où vient tel message
    • pas d’information de temps
    • il faut recompiler pour changer la quantité de messages
    • quand on enlève les messages, on n’a plus exactement le même programme, et le comportement peut changer

Logging: ce qu’il ne faut pas faire

  • System.out.println / System.err.println
  • mettre des mots de passe dans un log
  • envoyer des informations vers STDERR
  • plusieurs applications qui écrivent des logs dans un même fichier
  • ignorer des messages d’erreur qui sont dans vos logs
  • messages non pertinents voire confusants

Hello java.util.logging

import java.util.logging.*;

public class HelloJDKLogging {
    private static Logger logger =
            Logger.getLogger("com.foo.HelloJDKLogging");

    public static void main(String argv[]) {
        logger.setLevel(Level.ALL);
        logger.fine("Program started");
        logger.info("This app uses java.util.logging");
        logger.warning("Oops, I did it again");
    }
}                    

Output from HelloJDKLogging

Jul 23, 2002 12:12:43 PM HelloJDKLogging main
INFO: This app uses java.util.logging
Jul 23, 2002 12:12:43 PM HelloJDKLogging main
WARNING: Oops, I did it again
                    

Logging concepts

  • levels
  • destination for log messages (handler)
  • message log format (formatter)

java.util.Logging.Level

  • Basic level and ordering:
    • FINEST < FINER < FINE < CONFIG < INFO < WARNING < SEVERE
  • Other levels:
    • ALL
    • OFF

java.util.logging Handlers

  • les handlers sont des managers d’un type de sortie
  • StreamHandler : pour une sortie vers un flux
  • ConsoleHandler : pour une sortie vers la console
  • FileHandler : pour une sortie dans un fichier de journal
  • SocketHandler : pour une sortie vers une Socket (debug distant)
  • MemoryHandler : pour une sortie en mémoire (si pas de système de fichier)

java.util.logging Formatters

  • gère le format des messages
  • par exemple, le format par défaut est sur deux lignes, on peut écrire un formatteur simple qui écrit moins de choses et sur une seule ligne
  • SimpleFormatter : le formatteur par défaut
  • XMLFormatter : un formatteur qui crée du XML, à utiliser probablement dans un fichier

Fichier de configuration

handlers=java.util.logging.FileHandler, java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.level=FINEST
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.FileHandler.level=FINEST
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
                    

A l’exécution

java -Djava.util.logging.config.file=logging.properties …

Android et LogCat

  • Log.v() Log.d() Log.i() Log.w() Log.e()
  • degré d’importance décroissant: ERROR, WARN, INFO, DEBUG, VERBOSE
  • 2 arguments: un tag et un message
  • le tag sert à filtrer dans la console Android qui reçoit BEAUCOUP de messages

Debug

Comment débugger dans Eclipse

Eclipse Debugging

  • Point d’arrêts (Breakpoints)
    • Simple
    • Conditionel
      • Si une variable vaut une valeur donnée
      • Si on est passé N fois à cet endroit
  • Execution pas-à-pas (step-by-step)
    • Step into
    • Step over
    • Step return
    • Step Filters
    • Watches
    • Run to line
    • Suspend/Resume/Terminate

Points d’arrêts

  • Quand l’exécution rencontre un point d’arrêt, le programme s’arrête et donne la main à l’IDE (Eclipse, AndroidStudio, Visual Studio, …)
  • Pour mettre un point d’arrêt, il suffit de cliquer dans la marge gauche

Step Into

  • Execute une seule ligne (la ligne courante)
  • Si c’est une methode, alors il rentre dans la methode
  • Se mettre en “perspective debug”
  • Utiliser la toolbar ou F5

Step Over

  • Execute une seule ligne (la ligne courante)
  • Si c’est une methode, alors il execute l’appel complet à la methode
  • Se mettre en “perspective debug”
  • Utiliser la toolbar ou F6

Step Return

  • Execute tout jusqu’à la fin de la methode courante
  • Revient au point où la methode a ete appelée
  • Se mettre en “perspective debug”
  • Utiliser la toolbar ou F7

Watches

  • Vous permet de voir et de changer la valeur d’une variable pendant l’execution
  • Toutes les variables dans la portée courante sont “watched”
  • Voir la fenêtre “Variables”
  • On peut modifier la valeur des variables

Run to line

  • Revient à mettre un point d’arret temporaire à la ligne en question

DEMO

DEMO 2

DEMO 3

DEMO 4

DEMO 5

DEMO 6

DEMO 7

DEMO 8

DEMO 9

DEMO 10

DEMO 11

DEMO 12

DEMO 13

DEMO 14

DEMO 15

DEMO 16