From 14851fbf4f824ac279ce76723b3afe9578857fb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laure=CE=B7t?= Date: Fri, 3 Dec 2021 15:47:29 +0100 Subject: [PATCH] =?UTF-8?q?fin=20de=20s=C3=A9ance?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + .vscode/settings.json | 11 +++ Apres.java | 10 +++ Assert.java | 19 +++++ Avant.java | 7 ++ CasLimitesTest.java | 35 +++++++++ DeviseInvalideException.java | 13 ++++ Echec.java | 12 +++ ErreurTest.java | 17 ++++ FausseException.java | 3 + LanceurIndependant.java | 147 +++++++++++++++++++++++++++++++++++ Monnaie.java | 59 ++++++++++++++ MonnaieTest.java | 39 ++++++++++ MonnaieTest2.java | 12 +++ UnTest.java | 9 +++ 15 files changed, 394 insertions(+) create mode 100644 .gitignore create mode 100644 .vscode/settings.json create mode 100644 Apres.java create mode 100644 Assert.java create mode 100644 Avant.java create mode 100644 CasLimitesTest.java create mode 100644 DeviseInvalideException.java create mode 100644 Echec.java create mode 100644 ErreurTest.java create mode 100644 FausseException.java create mode 100644 LanceurIndependant.java create mode 100644 Monnaie.java create mode 100644 MonnaieTest.java create mode 100644 MonnaieTest2.java create mode 100644 UnTest.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6b468b6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.class diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..b1bba8a --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "files.exclude": { + "**/.git": true, + "**/.svn": true, + "**/.hg": true, + "**/CVS": true, + "**/.DS_Store": true, + "**/Thumbs.db": true, + "**/*.class": true + } +} \ No newline at end of file diff --git a/Apres.java b/Apres.java new file mode 100644 index 0000000..fe83ada --- /dev/null +++ b/Apres.java @@ -0,0 +1,10 @@ +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Apres { + +} diff --git a/Assert.java b/Assert.java new file mode 100644 index 0000000..8e843ba --- /dev/null +++ b/Assert.java @@ -0,0 +1,19 @@ +/** La classe Assert définit des méthodes de vérification. Pour l'instant, la + * seule méthode de vérification est assertTrue mais d'autres pourraient être + * définies (voir JUnit). + * + * @author Xavier Crégut + * @version $Revision: 1.1 $ + */ +abstract public class Assert { + + /** Vérifier que la condition est vraie. + * @param condition la condition à vérifier + */ + static public void assertTrue(boolean condition) { + if (! condition) { + throw new Echec(); + } + } + +} diff --git a/Avant.java b/Avant.java new file mode 100644 index 0000000..2af3ec2 --- /dev/null +++ b/Avant.java @@ -0,0 +1,7 @@ +import java.lang.annotation.*; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Avant { + +} diff --git a/CasLimitesTest.java b/CasLimitesTest.java new file mode 100644 index 0000000..12b3aae --- /dev/null +++ b/CasLimitesTest.java @@ -0,0 +1,35 @@ +/** Tester quelques cas limites. + * @author Xavier Crégut + * @version $Revision$ + */ +public class CasLimitesTest { + + public void testOK() { + // OK. + } + + private void testMethodePrivee() { + throw new RuntimeException("Une méthode privée n'est pas un test !"); + } + + protected void testMethodeProtegee() { + throw new RuntimeException("Une méthode protected n'est pas un test !"); + } + + void testMethodePaquetage() { + throw new RuntimeException("Une méthode de droit d'accès paquetage n'est pas un test !"); + } + + public static void testMethodeDeClasse() { + throw new RuntimeException("Une méthode de classe n'est pas un test !"); + } + + public void testAvecParametre(int a) { + throw new RuntimeException("Une méthode avec des paramètres n'est pas un test !"); + } + + public void testAvecParametre2(int a) { + throw new RuntimeException("Une méthode avec des paramètres n'est pas un test !"); + } + +} diff --git a/DeviseInvalideException.java b/DeviseInvalideException.java new file mode 100644 index 0000000..d950afd --- /dev/null +++ b/DeviseInvalideException.java @@ -0,0 +1,13 @@ +/** L'exception DeviseInvalideException indique des devises incompatibles sur + * des opérations entre monnaies. + * + * @author Xavier Crégut + * @version $Revision: 1.1 $ + */ +public class DeviseInvalideException extends Exception { + + public DeviseInvalideException(String message) { + super(message); + } + +} diff --git a/Echec.java b/Echec.java new file mode 100644 index 0000000..c8dcb55 --- /dev/null +++ b/Echec.java @@ -0,0 +1,12 @@ +/** L'exception Echec permet de signaler l'erreur fonctionnelle d'un test. + * @author Xavier Crégut + * @version $Revision: 1.1 $ + */ +public class Echec extends Error { + public Echec() { + super("condition non vérifiée"); + } + public Echec(String message) { + super(message); + } +} diff --git a/ErreurTest.java b/ErreurTest.java new file mode 100644 index 0000000..df26ea7 --- /dev/null +++ b/ErreurTest.java @@ -0,0 +1,17 @@ +/** ErreurTest est un programme de test qui définit trois méthodes de test + * dont une provoque une erreur. + */ +public class ErreurTest { + + public void tester1() { + } + + public void tester2() { + Assert.assertTrue(false); + } + + public void tester3() { + Assert.assertTrue(true); + } + +} diff --git a/FausseException.java b/FausseException.java new file mode 100644 index 0000000..7d99fc9 --- /dev/null +++ b/FausseException.java @@ -0,0 +1,3 @@ +public class FausseException extends Exception { + +} diff --git a/LanceurIndependant.java b/LanceurIndependant.java new file mode 100644 index 0000000..0cc31d4 --- /dev/null +++ b/LanceurIndependant.java @@ -0,0 +1,147 @@ +import java.lang.reflect.*; +import java.util.*; +import java.lang.annotation.*; + +/** + * L'objectif est de faire un lanceur simple sans utiliser toutes les clases de + * notre architecture JUnit. Il permet juste de valider la compréhension de + * l'introspection en Java. + */ +public class LanceurIndependant { + private int nbTestsLances; + private int nbErreurs; + private int nbEchecs; + private List erreurs = new ArrayList<>(); + + public LanceurIndependant(String... nomsClasses) { + System.out.println(); + + // Lancer les tests pour chaque classe + for (String nom : nomsClasses) { + try { + System.out.println(nom + " : "); + this.testerUneClasse(nom); + System.out.println(); + } catch (ClassNotFoundException e) { + System.out.println("Classe inconnue !"); + } catch (Exception e) { + System.out.println("Problème : " + e); + e.printStackTrace(); + } + } + + // Afficher les erreurs + for (Throwable e : erreurs) { + System.out.println(); + e.printStackTrace(); + } + + // Afficher un bilan + System.out.printf("%d tests lancés dont %d échecs et %d erreurs.", nbTestsLances, nbEchecs, nbErreurs); + } + + public int getNbTests() { + return this.nbTestsLances; + } + + public int getNbErreurs() { + return this.nbErreurs; + } + + public int getNbEchecs() { + return this.nbEchecs; + } + + private void testerUneClasse(String nomClasse) + throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, + IllegalArgumentException, InvocationTargetException, SecurityException { + // Récupérer la classe + Class classe = Class.forName(nomClasse); + + // Récupérer les méthodes "preparer" et "nettoyer" + Method preparer = null; + Method nettoyer = null; + + for (Method method : classe.getMethods()) { + if (method.isAnnotationPresent(Avant.class)) { + preparer = method; + break; + } + } + + for (Method method : classe.getMethods()) { + if (method.isAnnotationPresent(Apres.class)) { + nettoyer = method; + break; + } + } + + // Instancier l'objet qui sera le récepteur des tests + // Object objet = classe.newInstance(); + Object objet = classe.getDeclaredConstructor().newInstance(); + + // Exécuter les méthods de test + Method[] methods = classe.getMethods(); + for (Method method : methods) { + if (method.isAnnotationPresent(UnTest.class)) { + if (method.getAnnotation(UnTest.class).enabled()) { + + this.nbTestsLances++; + + if (preparer != null) { + preparer.invoke(objet); + } + + Class exep = method.getAnnotation(UnTest.class).expected(); + + try { + if (exep != FausseException.class) { + System.out.println("exep != FausseException.class"); + try { + method.invoke(objet); + System.out.println(method.getName() + " : echec"); + this.nbEchecs++; + } catch (InvocationTargetException e) { + Class exep2 = method.getAnnotation(UnTest.class).expected(); + if (e.getCause().getClass().isAssignableFrom(exep)) { + System.out.println(method.getName() + " : success"); + } else { + System.out.println(method.getName() + " : erreur"); + this.erreurs.add(e); + this.nbErreurs++; + } + } + } else { + try { + method.invoke(objet); + System.out.println(method.getName() + " : success"); + } catch (InvocationTargetException e) { + if (e.getCause() instanceof Echec) { + System.out.println(method.getName() + " : echec"); + this.erreurs.add(e); + this.nbEchecs++; + } else { + System.out.println(method.getName() + " : erreur"); + this.erreurs.add(e); + this.nbErreurs++; + } + } + } + } catch (java.lang.IllegalArgumentException e) { + System.out.println(method.getName() + " : erreur, pas de test avec arguments"); + this.nbErreurs++; + System.out.println("d"); + } + + if (nettoyer != null) { + nettoyer.invoke(objet); + } + } + } + } + } + + public static void main(String... args) { + new LanceurIndependant(args); + } +} diff --git a/Monnaie.java b/Monnaie.java new file mode 100644 index 0000000..b763cb9 --- /dev/null +++ b/Monnaie.java @@ -0,0 +1,59 @@ +/** La classe Monnaie est caractérisée par une valeur et une devise. Deux + * monnaies peuvent être ajoutées ou retranchées. + * + * @author Xavier Crégut + * @version $Revision: 1.1 $ + */ +public class Monnaie { + private int valeur; + private String devise; + + /** Initialiser une monnaie à partir de sa valeur de et sa devise. + * @param valeur valeur de la monnaie + * @param devise devise de la monnaie + */ + public Monnaie(int valeur, String devise) { + this.valeur = valeur; + this.devise = devise; + } + + /** Obtenir la valeur de cette monnaie. + * @param la valeur de cette monnaie + */ + public int getValeur() { + return this.valeur; + } + + /** Obtenir la devise de cette monnaie. + * @param la devise de cette monnaie + */ + public String getDevise() { + return this.devise; + } + + /** Ajouter une autre monnaie à cette devise. + * @param autre l'autre devise + * @depend - - DeviseInvalideException + */ + public void ajouter(Monnaie autre) throws DeviseInvalideException { + verifierMemesDevises(autre); + this.valeur += autre.valeur; + } + + /** Retrancher une autre monnaie à cette devise. + * @param autre l'autre devise + * @depend - - DeviseInvalideException + */ + public void retrancher(Monnaie autre) throws DeviseInvalideException { + verifierMemesDevises(autre); + this.valeur -= autre.valeur; + } + + private void verifierMemesDevises(Monnaie autre) throws DeviseInvalideException { + if (! this.devise.equals(autre.devise)) { + throw new DeviseInvalideException("Devises incompatibles : " + + this.devise + " et " + autre.devise); + } + } + +} diff --git a/MonnaieTest.java b/MonnaieTest.java new file mode 100644 index 0000000..89b20bc --- /dev/null +++ b/MonnaieTest.java @@ -0,0 +1,39 @@ +/** Classe regroupant les tests unitaires de la classe Monnaie. */ +public class MonnaieTest { + + protected Monnaie m1; + protected Monnaie m2; + protected Monnaie m3; + + @Avant + public void debut() { + this.m1 = new Monnaie(5, "euro"); + this.m2 = new Monnaie(7, "euro"); + } + + @UnTest(enabled = false) + public void ajouter() throws DeviseInvalideException { + m1.ajouter(m2); + Assert.assertTrue(m1.getValeur() == 12); + } + + @UnTest + public void retrancher() throws DeviseInvalideException { + m1.retrancher(m2); + Assert.assertTrue(m1.getValeur() == -2); + } + + @UnTest(expected = NullPointerException.class) + public void retrancher2() throws DeviseInvalideException { + m1.retrancher(m2); + m3.ajouter(m1); + Assert.assertTrue(m1.getValeur() == 1234567890); + } + + @Apres + public void rwwwwit() { + this.m1 = null; + this.m2 = null; + } + +} diff --git a/MonnaieTest2.java b/MonnaieTest2.java new file mode 100644 index 0000000..b834fb8 --- /dev/null +++ b/MonnaieTest2.java @@ -0,0 +1,12 @@ +/** MonnaieTest2 : Vérifier que les méthodes de test de la superclasse sont bien + * prises en compte ! + * @author Xavier Crégut + * @version $Revision$ + */ +public class MonnaieTest2 extends MonnaieTest { + + public void testSupplementaire() { + // OK. + } + +} diff --git a/UnTest.java b/UnTest.java new file mode 100644 index 0000000..3d42260 --- /dev/null +++ b/UnTest.java @@ -0,0 +1,9 @@ +import java.lang.annotation.*; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface UnTest { + boolean enabled() default true; + + Class expected() default FausseException.class; +}