JavascriptTDD

mardi 30 octobre 2007

Ajouter des fonctionnalités Ajax se fait de plus en plus sur des applications web existantes. Pour garantir la qualité du code Javascript créé, il est nécessaire d’appliquer les principes du TDD sur le code javascript de la même façon que sur le code Java,Perl,Python.

Cet article présente rapidement comment faire du TDD en javascript. Il s’attache à présenter les frameworks de test Javascript JSUnit et JSMock.

JSUnit

JSUnit est un framework de tests unitaires Javascript côté client, c’est un portage de JUnit en Javascript. Les mêmes fonctions existent: assertEquals, assertTrue, fail,…

Exemple Hello world

  • Télécharger JSUnit
  • Déziper dans le répertoire jsunit
  • Créer une page test.html
<html>
	<head>
		<script src=“jsunit/app/jsUnitCore.js”></script>
		<script>
			function testOK() {
			}
		</script>
	</head>
	<body>
	</body>
</html>
  • Ouvrir le fichier jsunit/testRunner.html et ajouter le fichier test.html
  • Cliquer sur le bouton Run
  • Vérifier la présence de la barre verte
  • Modifier le fichier test.html:
<html>
	<head>
		<script src=“jsunit/app/jsUnitCore.js”></script>
		<script>
			function testHelloWorld() {
				assertEquals(“hello world!”,helloworld );
			}
		</script>
	</head>
	<body>
	</body>
</html>
  • Lancer le script et vérifier la présence de la barre rouge
  • Modifier le fichier test.html:
<html>
	<head>
		<script src=“jsunit/app/jsUnitCore.js”></script>
		<script>
			function testHelloWorld() {
				assertEquals(“hello world!”,helloworld );
			}
			function helloworld  {
				return ’hello world!’;
			}
		</script>
	</head>
	<body>
	</body>
</html> 
  • Lancer le script et vérifier la présence de la barre verte

Intégration de JSUnit dans l’environnement Eclipse

Il existe un plugin Eclipse permettant de lancer des tests jsUnit dans l’environnement Eclipse comme le plugin JSUnit:

  • Télécharger le plugin http://downloads.sourceforge.net/jsunit/eclipse_plugin1.0alpha3.zip?modtime=1143183913&big_mirror=0
  • Déziper le contenu dans le répertoire d’eclipse
  • Afficher la vue JSUnit à partir du menu …
  • Paramétrer le plugin JSUnit à partir de Options > Preferences > JSUnit:
    • Entrer le chemin d’installation de jsUnit (le répertoire déziper, par exemple c:/junit)
    • Entrer le chemin des navigateurs à tester, par exemple c:/Program Files/Internet Explorer/iexplore.exe pour Internet Explorer
  • Intégrer le fichier test.html dans un projet Eclipse
  • Sélectionner ce fichier et faire Run as > JSUnit

JSMock

JSMock est un framework de tests javascript comme JMock pour Java. Il permet de tester les interactions avec des objets javascript. Dans le cas présent, nous allons modifier le fichier test.html pour mocker le comportement d’un objet Hello comportant la méthode helloworld

  • Télécharger JSMock
  • Modifier le fichier test.html
<html>
	<head>
		<script src=“jsunit/app/jsUnitCore.js”></script>
		<script src=“jsmock.js”></script>
		<script>
			function testHelloWorld() {
				var mockControl = new MockControl();
				helloMock = mockControl.createMock(Hello);
				helloMock.expects().helloworld().andReturn(’hello world!’);				
				assertEquals(“hello world!”,hello(helloMock));
			}
		</script>
	</head>
	<body>
	</body>
</html>
  • Vérifier la barre rouge
  • Modifier le fichier test.html
<html>
	<head>
		<script src=“jsunit/app/jsUnitCore.js”></script>
		<script src=“jsmock.js”></script>
		<script>
			function Hello  {
				this.helloworld  {
					return ’hello world!’;
				}
			}
			function sayHello(objHello) {
				return objHello.helloworld ;	
			}
			function testHelloWorld  {
				var mockControl = new MockControl ;
				helloMock = mockControl.createMock(Hello);
				helloMock.expects .helloworld .andReturn(’hello world!’);				
				assertEquals(“hello world!”,sayHello(helloMock));
				mockControl.verify ;
			}
		</script>
	</head>
	<body>
	</body>
</html>

Ressources

SpringJSON

mardi 23 octobre 2007

Une application Web 2.0 nécessite souvent d’appeler des services de données situés au niveau du serveur. Par défaut, on va utiliser DWR qui permet d’appeler des beans Spring facilement. Néanmoins je vois un inconvénient, l’échange n’est pas standard avec DWR, de plus il faut avoir un conteneur de servlets qui tourne, il est donc difficile de faire des tests unitaires avec JSUnit et JSMock, voici pourquoi j’avais besoin de trouver une autre solution. Un des formats utilisé pour des échanges service de données AJAX est JSON qui est un format plus simple que du XML. Dans une application J2EE utilisant Spring, Il parait donc intéressant de pouvoir afficher les résultats d’un controlleur sur une vue de type JSON ou d’exporter un bean en service JSON. Les deux approches ont déjà été réalisées (c.f. Ressources), celle qui m’a paru la plus simple est la vue JSON.

Création du service JSON Helloworld

  • Créer un projet Java
  • Ajouter un répertoire WEB-INF
  • Ajouter un fichier web.xml dans WEB-INF:
<?xml version=“1.0” encoding=“UTF-8”?>
<web-app version=“2.4” xmlns=“http://java.sun.com/xml/ns/j2ee”
	xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
	xsi:schemaLocation=“http://java.sun.com/xml/ns/j2ee 
	http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd”>
	<servlet>
		<servlet-name>hello</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>hello</servlet-name>
		<url-pattern>/hello/*</url-pattern>
	</servlet-mapping>
</web-app>
  • Ajouter un fichier hello-servlet.xml dans WEB-INF:
<?xml version=“1.0” encoding=“UTF-8”?>
<!DOCTYPE beans PUBLIC “-//SPRING//DTD BEAN//EN” “http://www.springframework.org/dtd/spring-beans.dtd”>
<beans>
	<bean class=“org.springframework.web.servlet.handler.SimpleUrlHandlerMapping”>
		<property name=“mappings”>
			<props>
				<prop key=“/helloworld.json”>helloWorld</prop>
			</props>
		</property>
	</bean>
	<bean id=“helloWorld” class=“fr.jfhelie.springjson.bean.HelloWorld” />
</beans>
  • Créer la vue JSON qui utilise JSON-lib:
package fr.jfhelie.springjson.bean;
import java.io.PrintWriter;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONObject;
import org.springframework.web.servlet.View;
public class JSONView implements View {
	public void render(Map map, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		JSONObject jsonObject = JSONObject.fromObject(map);
		PrintWriter writer = response.getWriter();
		writer.write(jsonObject.toString());
	}
	public String getContentType() {
		return “application/json”;
	}
}
  • Créer le controller Spring:
package fr.jfhelie.springjson.bean;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
public class HelloWorld implements Controller {
	public ModelAndView handleRequest(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		response.setContentType(“text/html”);
		Map model = new HashMap();
		model.put(“test”, “hello”);
		return new ModelAndView(new JSONView(), model);
	}
}

Appel du service JSON Helloworld

J’utilise jquery comme framework Javascript (syntaxe plus simple que Prototype), voici un exemple d’appel du client:

<html>
<head>
<script src=“jquery.js”></script>
<script>
$(document).ready(function() {
	$.getJSON(“hello/helloworld.json”,function(json){
		alert(json.test);
	});
});
</script>
</head>
<body>
</body>
</html>

Simple, n’est ce pas ?

Ressources

Axis2Outils

lundi 22 octobre 2007

Cet article présente les outils Axis 2 disponibles permettant d’administrer les web services, de débugger les requêtes/réponses SOAP transmises. Cet article s’attachera à décrire essentiellement:

  • la console d’administration Axis 2
  • le contrôleur TCP (TCPMon)

Cet article fait suite à l’article précédent: Introduction à Axis2

Console d’administration Axis 2

Installation

  • Télécharger le fichier .war de la console d’administration Axis 2
  • Installer ce fichier dans un container de servlet type Tomcat ou Jetty
  • Démarrer l’application
  • Ouvrir un navigateur Web sur http://localhost:8080/axis2/ sur Tomcat par exemple
  • Cliquer sur le lien Services pour visualiser les services disponibles

Gérer les web services

Ajouter un service

  • Cliquer sur Administration
  • Se connecter, par défaut admin/admin
  • Cliquer sur Upload Service
  • Aller chercher le web service en local et cliquer sur le bouton Upload
Activer un service
  • Cliquer sur Activate Service
  • Sélectionner un service, cocher la case à cocher Activate Service et cliquer sur le bouton Activate
Activer un service
  • Cliquer sur Desactivate Service
  • Sélectionner un service, cocher la case à cocher Desactivate Service et cliquer sur le bouton Desactivate

TCP Monitor

TCP Monitor permet de visualiser les requêtes et réponses SOAP qui transitent entre un client de web service et le web service lui même.

  • Télécharger TCPMon
  • Déziper le fichier sous le répertoire de votre choix
  • Aller dans le répertoire build du répertoire d’installation
  • Lancer le script tcpmon.bat (il est nécessaire d’avoir une JRE installée)
  • Dans l’onglet Admin, ajouter un Listener sur le port 8090 par exemple et faites pointer sur le serveur Axis 2
  • Modifier le client web service pour qu’il passe par le listener TCP sur le port 8090
  • Visualiser les messages qui transit Port 8090
  • Cocher la case à cocher XML format pour avoir un XML indenté

LdapWeb

mercredi 17 octobre 2007

Cet article décrit comment installer LdapWeb. Ceci peut être utile dans le cas de tests de recette effectués avec Selenium.

Installation de WAMP

WAMP (Windows Apache MySQL Php) est un packaging d’Apache, MySQL, Php qui permet de simplifier l’installation sous Windows.

Configuration du support LDAP pour PHP sur Windows :

  • Dans c:/wamp/Apache2/bin/php.ini, décommentez la ligne : extension=php_ldap.dll
  • Copiez C:/wamp/php/ext/php_ldap.dll dans c:/windows/system32
  • Redémarrez le serveur Apache

Installation de LdapWeb

ApacheProxyHTML

dimanche 14 octobre 2007

Lorsqu’on utilise le mod proxy sur Apache avec la directive ProxyPassReverse les liens internes ne sont pas corrigés. Par exemple je souhaite mettre un Continuum en 8080 derrière un proxy HTTPS, j’obtenai des liens du type

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN”  “http://www.w3.org/TR/html4/loose.dtd”>
<html>
  <head>
    <title>Configure Continuum</title>
    <link rel=“stylesheet” type=“text/css” href=“http://localhost:8080/continuum/css/tigris.css” media=“screen” />
…
</html>

Pour corriger les liens internes, il faut utiliser le module mod-proxy-html.

Installation du module mod-proxy-html

  • Pour l’installer sur Ubuntu, installer le package suivant:
sudo apt-get install libapache2-mod-proxy-html 
  • Redémarrer Apache
sudo /etc/init.d/apache2 force-reload
 

Configuration du mod-proxy-html

  • Ajouter dans votre fichier:
ProxyPass /continuum/ http://localhost:8080/continuum/
ProxyPassReverse /continuum/ http://localhost:8080/continuum/
SetOutputFilter proxy-html
ProxyHTMLURLMap http://localhost:8080/continuum /continuum
  • Redémarrer Apache:
 sudo /etc/init.d/apache2 restart
  • Résultat:
<html><head><title>Configure Continuum</title><link rel=“stylesheet” type=“text/css” href=“/continuum/css/tigris.css” media=“screen”><link rel=“stylesheet” type=“text/css” href=“/continuum/css/print.css” media=“print”><script src=“/continuum/scripts/tigris.js” type=“text/javascript”>
…
</html>

Ressources

ESB

jeudi 11 octobre 2007

Le séminaire Les ESB dans la SOA de Xebia permet d’avoir une bonne approche sur les ESB et leurs liens avec une architecture SOA. Je savais ce qu’était un ESB avant d’y participer mais les séminaires sont souvent des stimulateurs d’idées.

Il existe un lien entre SOA et ESB mais on ne peut pas dire que l’on ne puisse pas faire d’architecture SOA sans ESB. Une architecture SOA est une architecture de services métiers et d’infrastructure pour l’ensemble du SI. Evoluer vers une architecture SOA est avant tout une aventure humaine où les différentes institutions du SI prennent conscience du besoin de décrire son métier sous forme de processus directement visibles sous la forme de services, ESB ou pas ça n’a rien à voir avec une architecture SOA. On peut faire une architecture SOA sans ESB, avec une couche de services EJB comme ça a pu être fait chez un de nos clients du secteur distribution.

Je n’enlève pas l’intérêt des ESB pour autant, ils permettent réellement de fournir l’infrastructure de médiation, de transformation et de routage nécessaire pour mieux maitriser son SI. Les ESB ne remplace pas les EAI, il n’y a pas de notion métier dans un ESB (ou très peu) contrairement aux EAI, d’une certaine façon un EAI = ESB + BPM, une fois qu’on a les services, on décrit les processus d’appels entre les services, en gros on fait les Business Process

les fonctionnalités attendus d’un ESB

Un ESB apparait réellement comme un réducteur de coût qui permet de:

  • Exposer des services de type legacy (Mainframe, progiciels …)
  • Mutualiser les accès à cetaines applications
  • Minimiser les coûts des connecteurs legacy
  • Implémenter des services d’infrastructure transverses:
    • Sécurité
    • Interopérabilité
    • Performance, cache
    • Monitoring
    • Haute disponibilité
    • Enrichissement de messages
    • Support de plusieurs protocoles et types d’appels

En bref, c’est une multiprise, un proxy, une passerelle de services.

Une Approche

Il semble évident que l’on devient pas SOA du jour au lendemain. Par contre il arrive que pour des raisons de coût et de réorganisation, on soit obliger d’échanger des données rapidement avec d’autres domaines fonctionnels, voir des partenaires ou organismes externes au SI.

Avant de proposer une approche “top down” où l’on modélise tous les processus métiers, il est judicieux de commencer à décider quel service l’on souhaite exposer à un consommateur externe et l’on utilise un ESB pour exposer ce service. Utiliser un ESB open source dans un premier temps est une approche pragmatique car non couteuse mais surtout évite de rentrer dans une “usine à gaz logicielle” lourde à mettre en oeuvre et à maitriser. Ensuite il faut pouvoir bien savoir ce que l’on souhaite utiliser dans l’ESB, les traces des messages, quels connecteurs, la sécurité, les performances, la montée de versions. Utiliser au début un produit open source permet d’arriver rapidement à une solution et permet par la suite de bien identifier les besoins transverses pour les services et partir sur une solution plus intégrée propriétaire.

Un exemple d’évolution vers un ESB:

J’ai une application “vieille technologie” qui génére des fichiers UFAS de données, j’ai besoin d’utiliser ses données dans d’autres applications interne à mon SI. On peut imaginer d’utiliser un ETL pour synchroniser ces données avec une base de données. Si j’ai des règles métiers qui ne sont pas gérées par ma base de données, j’expose un service métier au dessus de la base de données et j’expose en interne ce service métier en Web service ou EJB. Ensuite mon service nécessite d’être appelé par des applications externes à mon SI ou de domaines différents. Mes besoins deviennent plus important, j’ai besoin de tracer les appels qui sont effectués, de gérer la sécurité de manière transverse, de fournir une infrastructure fiable et performante, c’est là que l’ESB entre en jeu. Et puis encore un pas en plus j’ai besoin de créer une fédération, alors là j’ajoute un médiateur à mon ESB qui permet de générer et de transformer des assertions SAML.

Les produits

  • Les deux produits phares ESB commerciaux sont:
    • WebSphere ESB: il semble qu’il y ait quelques bugs sans parler des wizards intégrés dans RAD… mon dieu …
    • Aqualogic Service Bus: connait pas
  • Open source:
    • Mule: en recul
    • ServiceMix: le plus avancé, permet l’utilisation de connecteurs JCA ou JBI
    • Apache Synapse: utilisé que pour les web services de type Axis 2, c’est mon préféré car très léger, bien documenté

DojoPremiersRetours

mercredi 3 octobre 2007

Toutes les semaines, nous faisons des Dojos Java pour appliquer le TDD, les premiers retours des participants du Dojo sont intéressants:

  • il est nécessaire d’avoir besoin d’un minimum de conception pour commencer une application
  • le TDD donne de la certitude: ca marche
  • le code en TDD respecte mieux les spécifications (bien évidement il faut imaginer du TDD dans un cycle en Y;))
  • permet de montrer les manques fonctionnels
  • faire des tests ça coûte cher
  • comment sait on qu’on a fait assez de tests ?
  • Quelles sont les limites du refactoring ? Jusqu’à quand doit on factoriser ?

Les résultats sont intéressants:

  • pour un énoncé identique, les codes développés par les paires sont très différents
  • l’écriture des tests vient assez rapidement
  • ceux qui écrivent le mieux leur tests sont ceux qui travaillent sur papier d’abord
  • l’utilisation de l’API Java est très variable d’un code à un autre
  • les méthodes sont assez longues, peu de refactoring
  • le code est assez statique
  • les développeurs se bloquent à trouver des solutions élégantes du premier coup avant de faire quelque chose qui fonctionne
  • le fonctionnement en paire permet un bon apprentissage par contre nuit à la productivité pour le moment, cela demande à celui qui code de commenter oralement ce qu’il fait.

Finallement assez peu de productivité, un exercice simple en 1h30.

Ce qui me fait penser qu’un développeur TDD confirmé doit être au moins 10 à 100 fois plus productif.

A suivre …