Précédent   Forum du club des développeurs et IT Pro > Java > EDI et OUTILS pour Java > Tests et Performance
Tests et Performance Vos questions sur les APIs et Outils de tests unitaires, d'intégration, de performance, profiling, etc.
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Actualité déjà publiée
 
Outils de la discussion
Publicité
'
Vieux 20/01/2010, 15h13   #1
foucha
Membre confirmé
 
Avatar de foucha
 
Inscription : janvier 2009
Messages : 120
Détails du profil
Informations personnelles :
Localisation : France

Informations forums :
Inscription : janvier 2009
Messages : 120
Points : 225
Points : 225
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
foucha est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 06/02/2010, 21h30   #2
thebloodyman
Membre expérimenté
 
David
Inscription : décembre 2003
Messages : 475
Détails du profil
Informations personnelles :
Nom : David

Informations forums :
Inscription : décembre 2003
Messages : 475
Points : 525
Points : 525
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
thebloodyman est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2010, 10h37   #3
foucha
Membre confirmé
 
Avatar de foucha
 
Inscription : janvier 2009
Messages : 120
Détails du profil
Informations personnelles :
Localisation : France

Informations forums :
Inscription : janvier 2009
Messages : 120
Points : 225
Points : 225
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
foucha est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2010, 17h21   #4
thebloodyman
Membre expérimenté
 
David
Inscription : décembre 2003
Messages : 475
Détails du profil
Informations personnelles :
Nom : David

Informations forums :
Inscription : décembre 2003
Messages : 475
Points : 525
Points : 525
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 :
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 :
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 :
1
2
3
 
Class CalculateService
+ float : calculerDifferenceHeureTravaillees(Employe from, Employe target)
3.Créer une classe non instantiable :
Code :
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 :
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 :
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 :
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
thebloodyman est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2010, 18h38   #5
foucha
Membre confirmé
 
Avatar de foucha
 
Inscription : janvier 2009
Messages : 120
Détails du profil
Informations personnelles :
Localisation : France

Informations forums :
Inscription : janvier 2009
Messages : 120
Points : 225
Points : 225
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 :
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 :
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 :
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
foucha est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Actualité déjà publiée
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 11h49.


 
 
 
 
Partenaires

Hébergement Web