IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Tests et Performance Java Discussion :

Comment tester du code intestable avec JMockit ? [Tutoriel]


Sujet :

Tests et Performance Java

  1. #1
    Membre actif
    Avatar de foucha
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    121
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 121
    Points : 251
    Points
    251
    Par défaut Comment tester du code intestable avec JMockit ?
    Bonjour,

    L'article "Comment tester du code intestable avec JMockit" a été publié :

    http://fchabanois.developpez.com/tutorial/java/jmockit/

    Au programme :

    • I. Qu'est-ce que JMockit ?
    • II. Installation de JMockit
    • III. Lancer les tests
    • IV. JMockit Core et JMockit Annotations
      • IV-A. Redéfinir une méthode
      • IV-B. Redéfinir un constructeur
      • IV-C. Redéfinir un bloc statique
      • IV-E. Créer une implémentation vide d'une interface
    • V. JMockit Expectations
      • V-A. Mocker une méthode "simple"
      • V-B. Mocker une méthode statique
      • V-C. Mocker toutes les méthodes d'une classe
      • V-D. Mocker toutes les méthodes d'une classe sauf certaines
      • V-E. Définir l'expectation d'une méthode privée
      • V-F. Vérifier qu'une méthode est appelée n fois
      • V-G. Vérifier les arguments passés à une méthode
      • V-H. Mocker l'objet de retour d'une méthode
    • VI. Conclusion


    ++
    Foucha.
    ++
    Foucha.

    =========

    "du code propre c'est du code qui fait exactement ce qu'on croit que ça fait"

    Mes Articles DVP

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    476
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 476
    Points : 595
    Points
    595
    Par défaut
    Bonjour,

    Merci pour l'article. Il y a de bonnes idées

    Par contre, je ne suis pas d'accord sur tes conclusions.
    JMockit est loin d'etre unique.
    PowkerMock que j'utilise réguliérement sert le même but.

    En outre, il est trop simple de croire que d'utiliser les artefacts de tests de type JMockit/PowerMock veut dire que notre conception est mauvaise.
    Par exemple, mocker une méthode statique parce que les outils de mock traditionnels (easymock,mockito...) ne savent pas le faire est une bonne pratique. Une mauvaise pratique serait au contraire d'adapter notre code aux limites des outils de mock traditionnels.
    Dans notre cas, on serait contraint de transformer notre méthode statique en méthode d'instance. Or utiliser une méthode statique n'est pas un sacrillége.
    Même si dans certains cas oui !
    Ils flottent tous en bas

  3. #3
    Membre actif
    Avatar de foucha
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    121
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 121
    Points : 251
    Points
    251
    Par défaut
    Salut,

    Ah quelqu'un qui n'est pas d'accord ! Oui la conclusion porte à polémique.

    Par contre je n'ai pas dit que JMockit était unique, j'ai parlé de "solution quasiment unique" car à ma connaissance il n'y a que powermock qui permet aussi ce type de fonctionnalité. Il n'empeche qu'elles sont rares.

    Je ne pense pas non plus que fwk de mock tradi + fwk magique veuille dire mauvais code, vu que fwk magique permet de quasiment tout faire, il permet aussi de faire du bien. Mais il permet aussi de faire du code "crade", sans collaborateurs, avec des instanciations partout par exemple. Alors qu'avec un fwk tradi, t'es sur que ton code reste testable. Se dire qu'un mock manuel doit etre injectable est un bon moyen de garantir cela. Certains ne font plus que cela d'ailleurs.

    En gros je dis qu'il faut être prudent. Si ton équipe considère que les méthodes statiques ne sont pas un sacrilège, alors c'est acceptable d'utiliser le fwk magique meme pour du nouveau code, mais uniquement pour ce cas là des méthodes statiques. Là où ça devient mal, c'est de l'utiliser comme béquille pour compenser du code nouveau qui serait intestable. L'usage du fwk magique est cadré donc pas de souci. Il n'y a pas de souci non plus si l'équipe de dev est super balèze en code testable et qu'elle n'utilise pas les fonctionnalités du fwk magique à tout va, à rajouter du legacy dans le nouveau code. Perso je ne me fais pas forcément confiance et être limité par le fwk me parait plus sur

    Disgression sur "les static ne sont pas un sacrilège" : ça se discute Le langage Java est un langage objet et les méthodes static ont cet aspect "procédural" qui peut etre évité. Elles prendront toujours au moins un paramètre, sur lequel l'opération s'applique. Au lieu de faire une méthode static doOperation(Toto toto), il faudrait plutot permettre toto.doOperation(). Ce n'est pas toujours possible quand le paramètre en question est immutable ou vient du JDK (typiquement les String). Dans ce cas, on peut faire se dire que le static est acceptable ou faire un objet intermédiaire. Voici un très joli article à ce sujet : http://misko.hevery.com/2008/12/15/s...o-testability/

    ++
    Foucha.
    ++
    Foucha.

    =========

    "du code propre c'est du code qui fait exactement ce qu'on croit que ça fait"

    Mes Articles DVP

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    476
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 476
    Points : 595
    Points
    595
    Par défaut
    Salut,

    J'ai lu l'article http://misko.hevery.com/2008/12/15/s...o-testability/, des idées bonnes mais des propos un peu extrémistes.
    Ok mettre du statique partout en POO c'est tres mauvais.
    Mais de la à dire que le statique est le mal et à exclure. Je ne pense pas.

    Ta remarque sur les statiques est bonne. C'est pour ca que j'indiquais que cela dépend des cas.

    A mon sens, tout dépend ce que doOperation(Toto toto) fait pour que je veuille bien faire doOperation() une méthode d'instance de Toto.

    La vraie question pour moi est ici la question de la responsabilité et de la cohésion des méthodes au sein d'une même classe.
    Je vais décrire ici ma façon de procéder.
    Je ne pense pas qu'elle soit la meilleure mais c'est ce que je fais en tout cas

    En général, je me pose 2 questions lorsque j'ajoute une méthode d'instance qui porte à doute :
    - Est ce que cette méthode est en cohérence avec les méthodes déja existantes et surtout avec les responsabilités que doit posséder mon objet ?
    - Est ce que ma classe a besoin d'un état ?

    Par exemple,j'ai la classe "Employé" suivante.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Class Employé
    + arriverAuTravail()
    + quitterLeTravail()
    + travailler()
    + parler(Employe e)
    Tortionnaire, j'ai maintenant le besoin de calculer la différence d'heures travaillées entre deux employés.

    Différentes options s'offrent à moi :

    1. Ajouter une méthode d'instance à ma classe Employe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Class Employé
    .
    .
    .
    + float : calculerDifferenceHeureTravaillees(Employe autreEmploye)
    2.Créer une nouvelle classe instantiable gérant entre autre ce type de calculs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Class CalculateService
    + float : calculerDifferenceHeureTravaillees(Employe from, Employe target)
    3.Créer une classe non instantiable :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Class CalculateUtil
    + float : static calculerDifferenceHeureTravaillees(Employe from, Employe target)
    Mon avis sur les solutions :

    1. Ajouter une méthode d'instance à ma classe Employe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Class Employé
    .
    .
    .
    + float : calculerDifferenceHeureTravaillees(Employe autreEmploye)
    Cette solution ne me plait pas car J'ajouterais à la classe Employé une responsabilité technique particulière qui s'éloigne de la responsabilité intrinsèque d'un employé. Un employé ne calcule pas ce genre d'informations.
    Un employé se rend à son boulot, travaille, parle avec ses collègues, prend en charge des projets, démissionne quand il en a marre mais il ne va pas calculer la différence d'heures travaillées avec ses collègues, ni le nombre d'heures travaillées sur tel ou tel projet.
    En suivant cette solution de façon presque systèmatique, je vais finir avec un objet Employé complexe : beaucoup de méthodes, de propriétés, de dépendance, donc d'effet de bord potentiel : un vrai God Object .
    Et le pire de tout, je vais me retrouver avec un objet dur à tester et à maintenir.

    2.Créer une nouvelle classe instantiable gérant entre autre ce type de calculs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Class CalculateService
    + float : calculerDifferenceHeureTravaillees(Employe from, Employe target)
    Cette seconde solution ne me déplait pas à partir du moment ou j'ai besoin de disposer d'un état dans ma classe. En outre, elle sépare les responsabilités et réduit donc la complexité, contrairement à la 1ère solution.

    3.Créer une classe non instantiable :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Class CalculateUtil
    + float : static calculerDifferenceHeureTravaillees(Employe from, Employe target)
    Cette solution ne me déplait pas à partir du moment ou je n'ai PAS besoin de disposer d'un état dans ma classe. En outre, comme la précédente, elle sépare les responsabilités et réduit donc la complexité, contrairement à la 1ère solution. Mais en plus, elle nous exonère de la création d'instance.


    A mon sens, refuser d'utiliser les static systématiquement lorsque c'est possible, c'est ajouter de la complexité à un design potentiellement simple et efficace.
    Pour conclure, je dirais que pour moi, les statics c'est comme la boisson, il ne faut pas en abuser

    En tous les cas, sujet intéressant
    Ils flottent tous en bas

  5. #5
    Membre actif
    Avatar de foucha
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    121
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 121
    Points : 251
    Points
    251
    Par défaut
    Spontanément, en premier lieu, j'aurais créer une classe (ta solution 2 donc) genre EmployeStatistics (CalculateService étant un peu vague).

    Ce qui aurait été moins bien, c'est de créer une méthode static supplémentaire dans Employe (ce que j'aurais tout à fait pu faire dans le passé). Le fait de se dire, attention au static "m'oblige" à me dire "attention aux responsabilités => je crée un autre objet".

    Je comprends qu'on ait envie d'économiser une instanciation et ton exemple se défent bien. Le risque c'est qu'il n'y a pas de limites, Utils peut devenir un véritable fourre tout de toute manipulation concernant des employes.

    Du coup, j'aurais envie de créer une classe spéciale qui fait des comparaisons entre deux employes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class EmployesComparator {
       EmployesComparator(Employe emp1, Employe emp2){
       }
       long dureeTravail(){
       }
    }
    Si tu utilises plusieurs calculs entre deux employés, on peut trouver plus lisibles de faire ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    EmployesComparator employesComparator = new EmployesComparator(emp1, emp2);
    employesComparator.dureeTravail();
    employesComparator.age()
    qu'avoir des noms de méthodes qui doivent etre plus explicites et des utils :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    EmployesUtils.calculterDureeTravail(emp1, emp2);
    EmployesUtils.calculerDifferenceAge(emp1, emp2);
    ...ou pas !

    Ce que j'aime bien en cherchant à éviter les static, c'est que ma conception en est meilleure je trouve. Dans la pratique, j'y ai quand meme pas mal recours au static, surtout pour les types de la JVM. Mais je me pose la question à chaque fois.


    ++
    Foucha.
    ++
    Foucha.

    =========

    "du code propre c'est du code qui fait exactement ce qu'on croit que ça fait"

    Mes Articles DVP

Discussions similaires

  1. Comment vérifier un code PHP avec beaucoup de conditions ?
    Par Gunner4902 dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 2
    Dernier message: 03/07/2008, 14h53
  2. comment tester le code donné dans l'aide de vb2005
    Par programaniac dans le forum Windows Forms
    Réponses: 7
    Dernier message: 04/03/2008, 18h04
  3. Réponses: 4
    Dernier message: 21/09/2005, 22h59
  4. Réponses: 7
    Dernier message: 12/09/2005, 11h05
  5. Comment fermer une Fenetre Modal avec Code ?
    Par Soulama dans le forum Langage
    Réponses: 19
    Dernier message: 13/07/2005, 11h17

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo