Jean-Yves, Bricolage et Bidouilles

Aller au contenu | Aller au menu | Aller à la recherche

mercredi 5 décembre 2007

Wicket premiers pas

Cela fait déjà un petit moment que je tourne autour de wicket et j'ai fini par me lancer à l'occasion d'un petit projet web utilisant spring. Comme d'habitude un petit tour chez Matt qui est une source inépuisable d'exemples, chez qui je télécharge appfuse-light en version "wicket".

On peut aussi s'inspirer du wicket phone book bien que le code soit un peu plus fouillis que celui de Matt.

C'est un peu déroutant au début, mais par contre très facile à tester (voir le wiki de wicket).

Conclusion, pas de conclusion car j'ai du abandonner pour reprendre Spring MVC, le projet devant utiliser JDK 1.4 ... A plus tard wicket

vendredi 10 août 2007

Maven assembly

Ce qui est un peu énervant avec Maven c'est la fiabilité des plugins, tant que l'on ne fait pas mvn -U tout va bien, mais dés que l'on met à jour les plugin c'est le début des ennuis.

Ca m'est arrivé ce matin avec l'assembly plugin qui s'est mis à bricoler sur un projet qui date de plusieurs semaines ....

La solution revenir en arrière sur la version :

<artifactId>maven-assembly-plugin</artifactId>
              <version>2.1</version>

Quelle idée aussi de mettre des version beta dans le repository officiel !

jeudi 14 décembre 2006

Test unitaires et Socket

La litérature déborde d'informations sur la façon de faire des test unitaires sur des classes simples et autonomes.

Lorsque l'on creuse un peu plus on arrive vite à avoir besoin d'utiliser des objets factices ou encore 'Mock Object', ce que encore une fois l'on fait facilement grâce à des librairies comme JMock, que je ne saurais trop conseiller d'ailleurs car son utilisation, une fois passé l'écueil de la documentation un peu sommaire, est assez facile.

Après avoir passé quelques heures à tester et à implémenter des classes simples, on se retrouve à implémenter les couches basses de l'application qui font appel à des librairies non conçues pour les tests unitaires (n'utilisant pas d'interfaces).

Comment procéder lorsque l'on doit tester d'une manière unitaire le code suivant ?

(Ce n'est pas forcément l'implémentation optimum d'un client TCP, mais disons que cet exemple est la pour illustrer la méthode de test :)).

   public boolean sendMessage(byte message, int length) {
       Socket socket = null;
       try {
           socket = new socket(inetAddress,portnumber);
           OutputStream outPut =socket.getOutputStream();
           outPut.write(message, 0, length);
           outPut.close();
       } catch (IOException e) {
           return false;
       }
       return true;
   }

La classe Socket et OutputStream, ne sont pas des implémentations d'interface, et il est donc impossible d'utiliser JMock pour vérifier que leur appel est bien effectué, ou de simuler le comportement de problème réseau qui peuvent lever des IOException. Pourtant il serait bien pratique de le faire et éviterai d'avoir à tester manuellement les cas de connexion et déconnexion réseau en devant enlever ou remettre le câble réseau de la machine.

Première solution, on laisse tel quel et on testera à la main.

Deuxième solution, qui une fois que l'on a trouvé la façon de faire ne parait pas si difficile, ecrire soit même des object factices qui seront renvoyé par une 'SocketFactory' que l'on pourra elle même utiliser d'une manière factice grâce à JMock. Ces objets héritent des objets que l'on ne peut pas tester et l'on peut facilement surcharger les méthodes que l'on veut pouvoir simuler.

  • Ecrire la classe factory qui renverra l'implémentation de la socket
   public class SocketFactoryImpl implements SocketFactory {
   
       public Socket createSocket(InetAddress address, int port)
                           throws IOException {
   
       return new Socket(address,port);
       }
   
   }
  • Utiliser cette factory pour renvoyer la Socket à la classe utilisatrice.
   protected boolean sendMessage(byte message, int length) {
       Socket socket = null;
       try {
           socket = socketFactory.createSocket(inetAddress, portNumber);
           OutputStream outPut =socket.getOutputStream();
           outPut.write(message, 0, length);
           outPut.close();
       } catch (IOException e) {
           return false;
       }
       return true;
   }
  • Ecrire dans le test unitaire des classes factices Socket et OutputStream
   private class MockOutputStream extends OutputStream {
       
       public  boolean writeCalled = false;
       public  boolean closeCalled = false;
       public boolean sendException = false;
       
       public void write(byte b, int off, int len) throws IOException {
           if (sendException) throw new IOException("MockOutputStream exception");
           writeCalled = true;
       }
       
       public void close() throws IOException {
           closeCalled = true;
       }
       /* (non-Javadoc)
        * @see java.io.OutputStream#write(int)
        */
       @Override
       public void write(int b) throws IOException {
           
       }
       
   }
   private class MockSocket extends Socket {
       
       public boolean sendException = false;
       public boolean closeCalled = false;
       private OutputStream outputStream;
       
       public void setOutputStream(OutputStream outputStream) {
           this.outputStream = outputStream;
       }
       public OutputStream getOutputStream() throws IOException {
           if (sendException) throw new IOException("mock exception");
           return outputStream;
       }
       
       public synchronized void close() throws IOException {
           if (sendException) throw new IOException("mock exception");
           closeCalled = true;
       }
       
   }

Une fois ces deux classes écrite il est facile de les utiliser pour simuler un comportement réseau hératique.

Exemple :

   public void testSendMessage() {
       MockOutputStream mockOutputStream = new MockOutputStream();
       MockSocket mockSocket = new MockSocket();
       mockSocket.setOutputStream(mockOutputStream);
       socketFactory.expects(once()).method("createSocket").will(returnValue(mockSocket));
       
       assertTrue ("message not sent",tcpLink.sendDataMessage(new byte32, 32));
       
       assertTrue("output stream write not called",mockOutputStream.writeCalled);
       assertTrue("output stream close not called",mockOutputStream.closeCalled);
       assertTrue("socket close not called",mockSocket.closeCalled);
   }
   
   public void testSendMessageSocketException() {
   
       MockOutputStream mockOutputStream = new MockOutputStream();
       MockSocket mockSocket = new MockSocket();
       mockSocket.setOutputStream(mockOutputStream);
       mockSocket.sendException = true;
       socketFactory.expects(once()).method("createSocket").will(returnValue(mockSocket));
       
       assertFalse ("message should be not sent",tcpLink.sendDataMessage(new byte32,32));
       
   }

Cette solution est bien entendu applicable lorsque l'on a peu de cas possibles ou de méthodes à tester, dans le cas contraire le nombre de combinaisons possibles deviendrait assez élevé et la complexité de l'implémentation des objets factices rendrait les tests difficile à écrire et donc non exempts de défaut.

Il y a d'autres pistes à creuser, comme l'utilisation d'une classe de délégation ou l'utilisation d'une classe dérivée implémentant une interface similaire à la classe à simuler. Peut être à un prochain billet pour décrire ces deux méthodes.

lundi 11 décembre 2006

Xplanner et Mylar

Première étape d'intégration d'Xplanner et de Mylar en utilisant le connecteur web generique

dimanche 10 décembre 2006

Matt l'écrivain

Matt Raible s'est laché ce week-end, beaucoup d'articles avec un contenu très dense.

  • TSE Keynote: The Bigger Picture with Adrian Colyer, Un tour d'horizon des sous projets de Spring : SFW, SWF, SWS, S-OSGi. Les services d'entreprise clustering, persistence, messaging et scheduling. Les tendances du moment: SAO, Web 2.0/RIA, RAD stacks. Je rajouterai à tout çà le projet de validation.
  • Spring-OSGI with Adrian Colyer

Beaucoup de choses à lire et à faire ....http://www.thespringexperience.com/

lundi 4 décembre 2006

RMI maven et tomcat

Il y a peu de temps je mettais en oeuvre une librairie utilisant RMI. Tout avait l'air de fonctionner impeccable lors du lancement de l'applicaton dans Eclipse à l'aide du plugin jetty.

Lors du déploiment dans tomcat, quelle ne fut pas ma surprise de voir l'application se planter en affichant des RMI Exceptions du plus bel effet.

Un coup de google et je tombe sur plusieurs articles / billets / archives email ou il est conseillé d'installer tomcat dans un répertoire sans espace, ce qui n'est bien entendu pas le cas par défaut sous Windows. Aussitôt lu aussitôt fait cela régle effectivement le problème.

Dans le même temps je suis en train de mettre en oeuvre des tests automatiques d'integration sous maven et quelle ne fut pas surprise de rencontrer le même problème. Ces tests tournant sans problème sous eclipse je pensais que mon paramètrage du fichier pom.xml était en cause ....

Mais non, même problème, même solution, il suffit de redéfinir dans le fichier settings.xml de maven un repository local situé dans un répertoire sans espace

Moralité, je me suis toujours méfié des caractères exotiques dans les noms de fichiers, et bien j'avais raison.

Calendrier

« décembre 2007
lunmarmerjeuvensamdim
12
3456789
10111213141516
17181920212223
24252627282930
31