#1. Application du cours sur des cas simples
#1.1. Exceptions
Faites un nouveau projet Exceptions
#1.1.1. Exercice 1 : Division par zéro
Recopiez le programme suivant
class DivisionByZero{
public static void main(String[] args){
int i = 10/args.length;
System.out.println("i = " + i);
}
}
- Que fait ce programme ?
- Testez sans arguments et repérez le type d'exception généré
- Corrigez le programme pour
- capturer cette exception
- afficher un message d'erreur explicite
- modifier la valeur de i en cas d'exception
- Testez avec des arguments corrects et incorrects (dans Eclipse : “Run configuration” -> onglet “arguments”)
#1.1.2. Exercice 2 : Problème de format et Dépassement de tableau
La methode parseInt
de la classe Integer
convertit une String
en entier et est spécifiée ainsi :
public static int parseInt(String s) throws NumberFormatException
- Dans un nouveau
main
, utilisez cette fonction pour faire la somme des 5 premiers entiers donnés en argument de la ligne de commande - Testez avec des arguments corrects puis incorrects
- Corrigez le main pour tenir compte des exceptions possibles (le programme ignorera les arguments qui posent problème et passera aux suivants)
#1.2. Tests unitaires avec JUnit 4
#1.2.1. Fonctionnement de JUnit
Principe
JUnit est un framework open source pour le développement et l‘exécution de tests unitaires automatisables d'application Java. Le principal intérêt est de s'assurer que le code répond toujours aux spécifications prévues même après d’éventuelles modifications (“non régression”).
En général, pour chaque classe MaClasse
d'une application va correspondre une classe de test MaClasseTest
et pour chaque méthode maMethode()
de MaClasse
qu‘on souhaitera tester on écrira une ou plusieurs méthodes de test. Cela permet d’éviter de créer un main()
par classe et de le lancer manuellement.
Création des tests
Le code des classes et méthodes de test est semblable à celui des classes et méthodes classiques. Une méthode de test exécute classiquement les tâches suivantes :
- création d'une instance de la classe et de tout autre objet nécessaire aux tests
- appel de la méthode à tester avec les paramètres du cas de tests
- comparaison du résultat attendu avec le résultat obtenu, par des opérations d‘assertion : en cas d’échec, une exception est levée automatiquement.
Quelques exemples d'assertions sont :
static void assertEquals(int attendu, int observe)
: prend en argument deux valeurs entières, celle attendue et celle observée, et vérifie que les deux valeurs sont égales.static void assertEquals(float attendu, float observe, float precision)
: prend en argument deux valeurs réelles, celle attendue et celle observée, et vérifie que les deux valeurs sont égales plus ou moins une troisième valeur de précision.static void assertTrue(boolean condition)
: vérifie que la valeur booléenne passée en argument est àtrue
.static void assertNotNull(Object object)
: vérifie que la référence passée en argument n'est pasnull
.
Lorsqu'un test échoue, un rapport est envoyé (sous la forme d'une exception) qui aidera à découvrir et corriger le(s) bug(s) d'implémentation
Pour connaître tous les tests disponibles, se reporter à la javadoc de la classe Assert
: http://junit.sourceforge.net/javadoc.
La classe de test peut également contenir des méthodes particulières (cf. junit.framework.TestCase
), par ex. :
protected void setUp( ) throws Exception
: executée avant chaque méthode de testprotected void tearDown( ) throws Exception
: executée après chaque méthode de test
Rq : Eclipse permet de créer le squelette des classes de test : clic droit sur la classe à tester -> New -> JUnit Test Case
Lancement des tests
Dans Eclipse, il faut que la bibliothèque JUnit soit ajoutée au projet :
- clic droit -> Properties
- Java Build Path -> onglet Libraries -> Add Library…
- JUnit -> Next -> JUnit 4 -> Finish
Pour lancer le test à partir d'Eclipse :
- clic droit sur la classe de test
- Run As -> JUnit Test
Un nouvel onglet JUnit s'ouvre alors, contenant le rapport d'erreur. 3 cas sont possibles pour chaque méthode de test :
- test correct
- failure : le résultat obtenu n'est pas celui attendu
- error : le test n'a pas pu aboutir
#1.2.2. Exercice
Soit la classe IntegerOp
destinée à contenir et faire des opérations sur un nombre entier.
public class IntegerOp {
private int e;
private int two = 3;
public IntegerOp(int n){
e = n;
}
public void twice(){
e *= (2 + 2 - 2 + 1);
}
public void half(){
e /= two;
}
public int getE(){
return e;
}
}
On souhaite vérifier que le constructeur et les méthodes fonctionnent comme on le souhaite.
- Recopiez le code de la classe
IntegerOp
- Créez une classe
IntegerOpTest
via le menu Eclipse (new -> “JUnit Test Case” -> choix des méthodes à tester)- lancez le test
- Complétez une méthode
public void testIntegerOp() throws Exception
qui- crée un
IntegerOp
de valeur 2 - vérifie qu'il n'est pas
null
- vérifie que la valeur stockée est 2
- crée un
- Complétez une méthode
testTwice()
similaire qui- crée un
IntegerOp
de valeur 1 - lui applique
twice()
- vérifie le résultat avec une des méthodes de JUnit proposées ci-dessus
- crée un
- Complétez une méthode
testTwice_0()
qui fait le même test avec un entier qui vaut 0 - Complétez une méthode
testHalf()
avec un entier qui vaut 3 - Lancez les tests au fur et à mesure et corrigez le programme si besoin
#2. Application à l'inventaire (cf. TP1)
Reprenez le projet Inventory
#2.1. Tests unitaires Devices
- Créez une classe de test sur la classe Device
- Créez des méthodes qui vérifient que les constructeurs des devices fonctionnent correctement
- Créez des méthodes qui vérifient que les prix d'achat ne sont pas négatifs
- Testez votre méthode equals
- Testez
- Faites les corrections nécessaires dans votre programme
#2.2. Exceptions
- Modifiez la classe PeopleDemo pour entrer une personne au clavier, avec gestion des exceptions (voir méthodes ci-dessous)
- On pourra ajouter une date de naissance dans la classe People (cf. LocalDate)
- Modifiez pour permettre l'entrée de plusieurs personnes à la suite
#3. Documentation pour le TP
#3.1. Lecture des entrées clavier dans la console
#3.1.1. Méthode 1 : BufferedReader
Principe : System.in
est de type InputStream
, il faut le convertir via BufferedReader
et InputStreamReader
)
InputStream in = System.in;
InputStreamReader isr = new InputStreamReader(in, Charset.forName("UTF-8"));
BufferedReader reader = new BufferedReader(isr);
String line = reader.readLine(); // exception à gérer ici
System.out.println(line);
reader.close();
Rq : il n'est pas nécessaire de passer par des variables intermédiaires
#3.1.2. Méthode 2 : Scanner
Principe : un objet construit à partir de System.in
qui possède des méthodes de récupération spécifiques par type de données
Scanner sc=new Scanner(System.in);
System.out.println("Enter your nb");
int nb = sc.nextInt();
System.out.println("Enter your name");
String name = sc.next();
System.out.println("Enter your fee");
double fee = sc.nextDouble();
System.out.println("Nb:"+nb+" name:"+name+" fee:"+fee);
sc.close();