<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>romain.getBlog( ); &#187; Romain</title>
	<atom:link href="http://linsolas.free.fr/wordpress/index.php/author/admin/feed/" rel="self" type="application/rss+xml" />
	<link>http://linsolas.free.fr/wordpress</link>
	<description></description>
	<lastBuildDate>Wed, 23 Jan 2013 21:29:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.5</generator>
		<item>
		<title>Redirection&#8230;</title>
		<link>http://linsolas.free.fr/wordpress/index.php/2012/11/redirection/</link>
		<comments>http://linsolas.free.fr/wordpress/index.php/2012/11/redirection/#comments</comments>
		<pubDate>Sun, 18 Nov 2012 13:11:34 +0000</pubDate>
		<dc:creator>Romain</dc:creator>
				<category><![CDATA[article]]></category>

		<guid isPermaLink="false">http://linsolas.free.fr/wordpress/?p=288</guid>
		<description><![CDATA[Ce blog ne sera sans doute plus maintenu, compte tenu des difficultés à le faire vivre sur les pages perso de Free. Ma nouvelle version du blog est donc hébergée par GitHub Pages, propulsé par Octopress ! Ca se passe ici -> http://linsolas.github.com/]]></description>
			<content:encoded><![CDATA[<p>Ce blog ne sera sans doute plus maintenu, compte tenu des difficultés à le faire vivre sur les pages perso de Free.<br />
Ma nouvelle version du blog est donc hébergée par GitHub Pages, propulsé par <a href="http://www.octopress.org" onclick="pageTracker._trackPageview('/outgoing/www.octopress.org?referer=');">Octopress</a> !</p>
<p>Ca se passe ici -> <a href="http://linsolas.github.com/" onclick="pageTracker._trackPageview('/outgoing/linsolas.github.com/?referer=');">http://linsolas.github.com/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://linsolas.free.fr/wordpress/index.php/2012/11/redirection/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TestNG, votre avis m&#8217;intéresse</title>
		<link>http://linsolas.free.fr/wordpress/index.php/2012/05/testng-votre-avis-minteresse/</link>
		<comments>http://linsolas.free.fr/wordpress/index.php/2012/05/testng-votre-avis-minteresse/#comments</comments>
		<pubDate>Fri, 04 May 2012 11:48:39 +0000</pubDate>
		<dc:creator>Romain</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[tests]]></category>
		<category><![CDATA[tools]]></category>

		<guid isPermaLink="false">http://linsolas.free.fr/wordpress/?p=282</guid>
		<description><![CDATA[Lors du Devoxx France, j&#8217;avais présenté un Quickie (session courte de 15 minutes) sur TestNG, parce que vos tests le valent bien. Les slides sont d&#8217;ailleurs visibles ici.   Le but de cette présentation est de montrer les atouts de la librairie de tests Java TestNG, en particulier face à l&#8217;omniprésent JUnit.   Il faut [...]]]></description>
			<content:encoded><![CDATA[<p>Lors du Devoxx France, j&#8217;avais présenté un Quickie (session courte de 15 minutes) sur <a href="http://devoxx.fr/display/FR12/TestNG%2C+parce+que+vos+tests+le+valent+bien" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/TestNG_2C+parce+que+vos+tests+le+valent+bien?referer=');">TestNG, parce que vos tests le valent bien</a>. Les slides sont d&#8217;ailleurs visibles <a href="http://www.slideshare.net/linsolas/devoxx-test-ng" onclick="pageTracker._trackPageview('/outgoing/www.slideshare.net/linsolas/devoxx-test-ng?referer=');">ici</a>.<br />
 <br />
Le but de cette présentation est de montrer les atouts de la librairie de tests Java <a href="http://testng.org/doc/index.html" onclick="pageTracker._trackPageview('/outgoing/testng.org/doc/index.html?referer=');">TestNG</a>, en particulier face à l&#8217;omniprésent <a href="https://github.com/KentBeck/junit" onclick="pageTracker._trackPageview('/outgoing/github.com/KentBeck/junit?referer=');">JUnit</a>.<br />
 <br />
Il faut l&#8217;avouer, aujourd&#8217;hui JUnit a réussi à combler certaines de ses lacunes par rapport à TestNG. Je pense par exemple au groupage / catégorisation des tests (JUnit 4.8 a introduit un <code>@Category</code> bancal, mais grandement aidé par Maven Surefire depuis sa version 2.11), aux tests paramétrés (annotation <code>@Parameters</code> de JUnit), etc.<br />
Toutefois, je reste convaincu de l&#8217;intérêt de TestNG sur JUnit. Mais j&#8217;aimerais connaitre ton opinion&#8230;<br />
 <br />
Bref, toi, lectrice, lecteur de mon blog, si tu fais partie d&#8217;une catégorie suivante :<br />
 </p>
<ul>
   
<li>Tu utilises déjà TestNG</li>
<p>   
<li>Tu as utilisé TestNG par le passé</li>
<p>   
<li>Tu aimerais bien utiliser TestNG</li>
<p>   
<li>Tu t&#8217;intéresses à TestNG</li>
</ul>
<p> <br />
alors ton avis m&#8217;intéresse ! Dis-moi quels sont les intérêts que tu lui trouves ? Pourquoi le préfères-tu à JUnit, ou au contraire pourquoi préfères-tu JUnit ? Que lui manque-t&#8217;il ? Bref, dis moi tout !<br />
 <br />
Merci.</p>
]]></content:encoded>
			<wfw:commentRss>http://linsolas.free.fr/wordpress/index.php/2012/05/testng-votre-avis-minteresse/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Chouchoutez votre JavaScript dans un projet web</title>
		<link>http://linsolas.free.fr/wordpress/index.php/2012/05/chouchoutez-votre-javascript-dans-un-projet-web/</link>
		<comments>http://linsolas.free.fr/wordpress/index.php/2012/05/chouchoutez-votre-javascript-dans-un-projet-web/#comments</comments>
		<pubDate>Thu, 03 May 2012 22:06:30 +0000</pubDate>
		<dc:creator>Romain</dc:creator>
				<category><![CDATA[continuous integration]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[sonar]]></category>
		<category><![CDATA[tests]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://linsolas.free.fr/wordpress/?p=277</guid>
		<description><![CDATA[Voilà, c&#8217;est fait ! Vous êtes venus à Devoxx France, vous avez assisté à ma présentation (ou alors vous avez juste lu mon post sur le sujet), et donc vous voulez désormais chouchouter votre code JavaScript. Pour démarrer sur le sujet, vous avez suivi les étapes écrites sur mon post, comme je l&#8217;ai fait lors [...]]]></description>
			<content:encoded><![CDATA[<p>Voilà, c&#8217;est fait ! Vous êtes venus à Devoxx France, vous avez assisté à ma présentation (ou alors vous avez juste lu mon <a href="http://linsolas.free.fr/wordpress/index.php/2012/04/chouchoutez-votre-code-javascript">post sur le sujet</a>), et donc vous voulez désormais <strong>chouchouter votre code JavaScript</strong>.</p>
<p>Pour démarrer sur le sujet, vous avez suivi les étapes écrites sur mon post, comme je l&#8217;ai fait lors de ma présentation. C&#8217;est bien joli tout ça, mais dans la vraie vie réelle, vous n&#8217;avez pas un module Maven dédié au code JavaScript. Votre code JavaScript est (bêtement) dans votre application web ! Du coup, vous vous posez des questions sur la façon de procéder, en particulier concernant les analyses Sonar&#8230;</p>
<p>Allez zou, suivez le guide !</p>
<p><span id="more-277"></span></p>
<h2>Zou, créons un projet</h2>
<p>Lors de ma présentation, j&#8217;ai utilisé l&#8217;archetype Maven <code>de.akquinet.javascript.archetypes:javascript-quickstart</code>, qui crée un squelette d&#8217;application contenant juste du JavaScript.<br />
Cette fois-ci, on va partir d&#8217;un projet web classique dans lequel on incluera notre code JavaScript. Donc quelque chose de plus proche que ce que vous avez sur votre projet !</p>
<p>Je pars donc avec l&#8217;archetype <code>org.codehaus.mojo.archetypes:webapp-javaee6</code> pour avoir un squelette d&#8217;application web. Il s&#8217;agit là de votre propre projet web&#8230; De mon côté, j&#8217;y ajoute une petite classe Java, ainsi qu&#8217;une class de test JUnit pour le fun.</p>
<p>Désormais, on peut lancer une première analyse Sonar, avec la commande <code>mvn clean install sonar:sonar</code>.</p>
<div id="attachment_272" class="wp-caption center" style="width: 750px"><a href="http://linsolas.free.fr/wordpress/wp-content/uploads/chouchoutage-1.png"><img src="http://linsolas.free.fr/wordpress/wp-content/uploads/chouchoutage-1.png" alt="" title="chouchoutage-1" width="740" height="455" class="size-full wp-image-272" /></a><p class="wp-caption-text">Jusqu'ici, tout va bien !</p></div>
<p>Maintenant, je rajoute mon code JavaScript (les fichiers <code>underscore.js</code> et <code>undescore-test.js</code>). Je les positionne respectivement dans les répertoires <code>src/main/javascript</code> et <code>src/test/javascript</code>. Il est possible d&#8217;adapter ces répertoires, bien entendu !<br />
On ajoute le fichier de configuration de <code>jsTestDriver.conf</code> qui va nous permettre de lancer nos tests JavaScript de Jasmine. On ajoute aussi dans un coin (le répertoire <code>lib/</code> disons) :</p>
<ul>
<li>le fichier <code>jasmine.js</code> ;</li>
<li>le fichier <code>jasmineAdapter.js</code> (pour lancer les tests JavaScript écrits en Jasmine avec js-test-driver) ;</li>
<li>la librairie <code>coverage-1.3.4.b.jar</code>, qui est le plugin de calcul de couverture du code JavaScript pour js-test-driver.</li>
</ul>
<p>Au final, la structure de mon projet a la tête suivante :</p>
<pre class="brush: plain;">
chouchoutage (oui, c'est le nom pourri de mon projet)
  + pom.xml
  ` src
      + lib
      |   ` coverage-1.3.4.b.jar
      |   ` jasmine.js
      |   ` jasmineAdapter.js
      + main
      |   + java
      |   |   ` ze-code-java
      |   ` javascript
      |       ` underscore.js
      + test
      |   + java
      |   |   ` test-unitaires
      |   ` javascript
      |       ` underscore-test.js
      ` webapp
          ` toute-la-partie-web
</pre>
<p>Si vous souhaitez plus d&#8217;informations sur cette étape (comme le contenu du fichier <code>jsTestDriver.conf</code> par exemple), allez jeter un oeil sur <a href="http://linsolas.free.fr/wordpress/index.php/2012/04/chouchoutez-votre-code-javascript">mon post décrivant ma session Devoxx</a>.</p>
<p>Voilà, on arrive à quelque chose qui ressemble en gros à votre projet. Maintenant, on va voir comment on va pouvoir exécuter nos codes JavaScript, et en faire l&#8217;analyse Sonar.</p>
<h2>Ne tombons pas dans les poms !</h2>
<p>Attaquons nous au problème principal : la modification du pom. Nous allons d&#8217;abord l&#8217;adapter pour exécuter nos tests JavaScript. Nous verrons ensuite pour l&#8217;analyse Sonar&#8230;</p>
<p>Ajoutons d&#8217;abord la dépendance suivante :</p>
<pre class="brush: xml;">
    &lt;dependency&gt;
        &lt;groupId&gt;com.googlecode.jstd-maven-plugin&lt;/groupId&gt;
        &lt;artifactId&gt;jstd-maven-plugin&lt;/artifactId&gt;
        &lt;version&gt;1.3.2.5&lt;/version&gt;
        &lt;scope&gt;test&lt;/scope&gt;
    &lt;/dependency&gt;
</pre>
<p>On ajoute ensuite le plugin de <code>jstd-maven-plugin</code> :</p>
<pre class="brush: xml;">
    &lt;plugin&gt;
        &lt;groupId&gt;com.googlecode.jstd-maven-plugin&lt;/groupId&gt;
        &lt;artifactId&gt;jstd-maven-plugin&lt;/artifactId&gt;
        &lt;version&gt;1.3.2.5&lt;/version&gt;
        &lt;configuration&gt;
            &lt;port&gt;9876&lt;/port&gt;
            &lt;!-- A adapter ! --&gt;
            &lt;browser&gt;/Applications/Firefox.app/Contents/MacOS/firefox-bin&lt;/browser&gt;
            &lt;tests&gt;all&lt;/tests&gt;
            &lt;config&gt;jsTestDriver.conf&lt;/config&gt;
            &lt;testOutput&gt;target/jstestdriver&lt;/testOutput&gt;
        &lt;/configuration&gt;
        &lt;executions&gt;
            &lt;execution&gt;
                &lt;id&gt;run-tests&lt;/id&gt;
                &lt;goals&gt;
                    &lt;goal&gt;test&lt;/goal&gt;
                &lt;/goals&gt;
            &lt;/execution&gt;
        &lt;/executions&gt;
    &lt;/plugin&gt;
</pre>
<p>Dernier point, nous ajoutons le repository contenant les plugins sus-cités :</p>
<pre class="brush: xml;">
    &lt;repositories&gt;
          &lt;repository&gt;
              &lt;id&gt;jstd-maven-plugin google code repo&lt;/id&gt;
              &lt;url&gt;http://jstd-maven-plugin.googlecode.com/svn/maven2&lt;/url&gt;
          &lt;/repository&gt;
    &lt;/repositories&gt;
    &lt;pluginRepositories&gt;
          &lt;pluginRepository&gt;
              &lt;id&gt;jstd-maven-plugin google code repo&lt;/id&gt;
              &lt;url&gt;http://jstd-maven-plugin.googlecode.com/svn/maven2&lt;/url&gt;
          &lt;/pluginRepository&gt;
    &lt;/pluginRepositories&gt;
</pre>
<p>Voilà, nous pouvons vérifier si cela fonctionne. La commande <code>mvn clean install</code> va nous le dire :</p>
<pre class="brush: plain;">
-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running fr.linsolas.WorldTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.053 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO]
[INFO] --- jstd-maven-plugin:1.3.2.5:test (run-tests) @ chouchoutage ---

-------------------------------------------
 J S  T E S T  D R I V E R
-------------------------------------------

Firefox: Runner reset.
................
Total 16 tests (Passed: 16; Fails: 0; Errors: 0) (10,00 ms)
  Firefox 9.0.1 Mac OS: Run 16 tests (Passed: 16; Fails: 0; Errors 0) (10,00 ms)
</pre>
<p>C&#8217;est plutôt une bonne nouvelle ça ! Surefire a lancé mon test JUnit (<code>fr.linsolas.WorldTest</code>), puis, dans un second temps, a exécuté les tests de js-test-driver.</p>
<h2>Plongeons dans l&#8217;analyse Sonar</h2>
<p>Et bien voilà, il ne nous reste plus qu&#8217;à exécuter une analyse Sonar et le tour est joué&#8230; Mais ce n&#8217;est pas si simple en fait !<br />
Sonar permet bien d&#8217;analyser un projet Java, il permet d&#8217;analyser également un projet JavaScript, mais hélas pas en même temps !<br />
Nous allons devoir donc lancer <strong>deux analyses Sonar</strong> pour arriver à nos fins.</p>
<p>Etant donné que nous ne voulons pouvoir lancer avec le même pom.xml l&#8217;analyse Sonar pour le code Java et l&#8217;analyse Sonar pour le code JavaScript, nous allons créer un profil Maven qui sera dédié à l&#8217;analyse JavaScript :</p>
<pre class="brush: xml;">
    &lt;profiles&gt;
        &lt;profile&gt;
            &lt;id&gt;js&lt;/id&gt;
            &lt;properties&gt;
                &lt;sonar.language&gt;js&lt;/sonar.language&gt;
                &lt;sonar.dynamicAnalysis&gt;reuseReports&lt;/sonar.dynamicAnalysis&gt;
            &lt;/properties&gt;
        &lt;/profile&gt;
    &lt;/profiles&gt;
</pre>
<p>Voyons voir si cela fonctionne. Lançons une première analyse avec <code>mvn clean install sonar:sonar</code>. En exécutant cette commande, l&#8217;analyse Sonar ne montre aucune différence avec celle réalisée plus tôt. Normal, me direz-vous, on reste sur l&#8217;analyse Java.<br />
Lançant maintenant la même commande, mais en activant le profile <strong>js</strong> : <code>mvn -Pjs clean install sonar:sonar</code>. Le résultat n&#8217;est pas celui attendu :</p>
<div id="attachment_273" class="wp-caption center" style="width: 766px"><a href="http://linsolas.free.fr/wordpress/wp-content/uploads/chouchoutage-2.png"><img src="http://linsolas.free.fr/wordpress/wp-content/uploads/chouchoutage-2.png" alt="" title="chouchoutage-2" width="756" height="233" class="size-full wp-image-273" /></a><p class="wp-caption-text">Ooooups</p></div>
<p>Houlà, mais on a tout cassé ! On n&#8217;obtient plus aucun chiffre, ni rien <img src='http://linsolas.free.fr/wordpress/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' />  Le problème vient simplement du fait que le plugin JavaScript pour Sonar va chercher les sources dans le répertoire <code>src/main/java</code> au lieu de <code>src/main/javascript</code>.<br />
Il faut donc lui spécifier ce nouveau répertoire. On va donc spécifier un <code>sourceDirectory</code> dans notre profile <strong>js</strong>. Du moins on aimerait bien, car hélas Maven n&#8217;autorise pas que l&#8217;on redéfinisse ce répertoire dans un profil ! C&#8217;est étrange, mais c&#8217;est comme ça. Enfin pas tant que ça, car Maven &#8211; par défaut &#8211; n&#8217;accepte qu&#8217;un seul chemin de sources. Comme plusieurs profiles peuvent être actifs en même temps, on pourrait bidouiller les profiles pour avoir ainsi plusieurs répertoires de sources. On s&#8217;égare un peu là&#8230;<br />
Nous pourrions passer par le plugin <a href="http://mojo.codehaus.org/build-helper-maven-plugin/" onclick="pageTracker._trackPageview('/outgoing/mojo.codehaus.org/build-helper-maven-plugin/?referer=');">build-helper</a> qui permet de spécifier plusieurs répertoires de sources. Je n&#8217;en ferais rien, je vais &laquo;&nbsp;simplement&nbsp;&raquo; fourvoyer Maven en jouant avec les propriétés :</p>
<pre class="brush: xml;">
    &lt;properties&gt;
        &lt;source.dir&gt;src/main/java&lt;/source.dir&gt;
        &lt;test.source.dir&gt;src/test/java&lt;/test.source.dir&gt;
    &lt;/properties&gt;

    &lt;build&gt;
        &lt;sourceDirectory&gt;${source.dir}&lt;/sourceDirectory&gt;
        &lt;testSourceDirectory&gt;${test.source.dir}&lt;/testSourceDirectory&gt;
        ...
    &lt;/build&gt;

    &lt;profiles&gt;
        &lt;profile&gt;
            &lt;id&gt;js&lt;/id&gt;
            &lt;properties&gt;
                &lt;source.dir&gt;src/main/javascript&lt;/source.dir&gt;
                &lt;test.source.dir&gt;src/test/javascript&lt;/test.source.dir&gt;
                ...
</pre>
<p>Voilà, Maven n&#8217;y voit que du feu, et moi j&#8217;ai réussi à me débrouiller (à bidouiller disons plutôt).</p>
<p>Alors, que donne l&#8217;analyse Sonar maintenant ?</p>
<div id="attachment_274" class="wp-caption center" style="width: 753px"><a href="http://linsolas.free.fr/wordpress/wp-content/uploads/chouchoutage-3.png"><img src="http://linsolas.free.fr/wordpress/wp-content/uploads/chouchoutage-3.png" alt="" title="chouchoutage-3" width="743" height="454" class="size-full wp-image-274" /></a><p class="wp-caption-text">Voilà qui est mieux !</p></div>
<p>OUI ! Enfin, nous réussissons à obtenir notre belle analyse du code JavaScript par Sonar !</p>
<p>Et voilà, c&#8217;est fini.<br />
Vraiment ? Non !<br />
Un dernier souci se pose : si je lance l&#8217;analyse Java, j&#8217;ai un beau rapport Sonar. Mais dès que je lance l&#8217;analyse JavaScript, mon rapport JavaScript efface celui de Java !<br />
Il faut donc trouver un moyen de faire cohabiter les deux. Je propose simplement de profiter de l&#8217;option <code>sonar.branch</code> pour différencier les deux projets. On ajoute donc dans le profil <strong>js</strong> :</p>
<pre class="brush: xml;">
    &lt;profiles&gt;
        &lt;profile&gt;
            &lt;id&gt;js&lt;/id&gt;
            &lt;properties&gt;
                &lt;sonar.branch&gt;javascript&lt;/sonar.branch&gt;
                ...
</pre>
<p>Cette fois-ci, on relance les deux analyses : <code>mvn clean install sonar:sonar</code> puis <code>mvn -Pjs clean install sonar:sonar</code>.<br />
Une fois les deux commandes terminées, nous nous retrouvons avec non plus un mais deux projets Sonar :</p>
<div id="attachment_275" class="wp-caption center" style="width: 627px"><a href="http://linsolas.free.fr/wordpress/wp-content/uploads/chouchoutage-4.png"><img src="http://linsolas.free.fr/wordpress/wp-content/uploads/chouchoutage-4.png" alt="" title="chouchoutage-4" width="617" height="78" class="size-full wp-image-275" /></a><p class="wp-caption-text">Les deux font la paire</p></div>
<p>Chacun de ces projets est adapté à son langage, le premier pour Java, le second pour JavaScript.</p>
<p>Et voilà, c&#8217;est fini.<br />
Vraiment ? Cette fois, oui <img src='http://linsolas.free.fr/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>N&#8217;hésitez pas à faire part, dans les commentaires, de vos propres expériences, ou propositions d&#8217;améliorations !</p>
<a href="javascript:toggleStartStop();PicLensLite.start({feedUrl:'http://linsolas.free.fr/wordpress/wp-content/plugins/wp-piclens/mrss.php?id=277'});">Start Slide Show with PicLens Lite <img src="http://linsolas.free.fr/wordpress/wp-content/plugins/wp-piclens/PicLensButton.png" alt="PicLens" width="16" height="12" border="0" align="top"></a>]]></content:encoded>
			<wfw:commentRss>http://linsolas.free.fr/wordpress/index.php/2012/05/chouchoutez-votre-javascript-dans-un-projet-web/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Etre conférencier à Devoxx France&#8230;</title>
		<link>http://linsolas.free.fr/wordpress/index.php/2012/05/etre-conferencier-a-devoxx-france/</link>
		<comments>http://linsolas.free.fr/wordpress/index.php/2012/05/etre-conferencier-a-devoxx-france/#comments</comments>
		<pubDate>Tue, 01 May 2012 12:55:05 +0000</pubDate>
		<dc:creator>Romain</dc:creator>
				<category><![CDATA[conférence]]></category>
		<category><![CDATA[valtech]]></category>

		<guid isPermaLink="false">http://linsolas.free.fr/wordpress/?p=243</guid>
		<description><![CDATA[Avant toute chose, je tiens à préciser que l&#8217;idée de ce post est honteusement copiée sur un post de Gildas Cuisinier parlant de sa vision de Devoxx en tant que conférencier. Devoxx, je connaissais déjà depuis à peu près 3 ans, mais de façon indirecte. Hélas, je n&#8217;avais jamais eu la chance de me rendre [...]]]></description>
			<content:encoded><![CDATA[<p>Avant toute chose, je tiens à préciser que l&#8217;idée de ce post est honteusement copiée sur un <a href="http://www.gcuisinier.net/2012/04/30/devoxx-france-cote-speaker/" onclick="pageTracker._trackPageview('/outgoing/www.gcuisinier.net/2012/04/30/devoxx-france-cote-speaker/?referer=');">post de Gildas Cuisinier</a> parlant de sa vision de Devoxx en tant que conférencier.</p>
<div id="attachment_257" class="wp-caption aligncenter" style="width: 316px"><a href="http://linsolas.free.fr/wordpress/wp-content/uploads/Badge-Devoxx.jpg"><img src="http://linsolas.free.fr/wordpress/wp-content/uploads/Badge-Devoxx.jpg" alt="" title="Badge Devoxx" width="306" height="408" class="size-full wp-image-257" /></a><p class="wp-caption-text">C'est'y pas collector ?</p></div>
<p>Devoxx, je connaissais déjà depuis à peu près 3 ans, mais de façon indirecte. Hélas, je n&#8217;avais jamais eu la chance de me rendre à Anvers pour assister à LA conférence des développeurs Java. Quand la conférence Devoxx France a été annoncée lors du Devoxx World en fin 2011, je me suis dit que je devais y être. Il ne pourrait pas en être autrement !<br />
Pour m&#8217;y rendre, j&#8217;avais donc 4 possibilités :</p>
<ol>
<li>Devenir conférencier, en proposant un (ou plusieurs) sujet(s) ;</li>
<li>Obtenir une place via le site <a href="http://www.developpez.com" onclick="pageTracker._trackPageview('/outgoing/www.developpez.com?referer=');">Developpez.com</a>, pour lequel je suis rédacteur et modérateur ;</li>
<li>Me faire payer ma place par ma société, si possible par le biais du DIF (Droit Individuel à la Formation) ;</li>
<li>M&#8217;offrir ma place, et poser 3 jours de congés pour m&#8217;y rendre.</li>
</ol>
<p>L&#8217;aventure commence&#8230;<br />
<span id="more-243"></span></p>
<h3>L&#8217;avant CFP</h2>
<p>Début janvier, je commence donc le forcing auprès de ma hierarchie, pour privilégier la solution #3. Visiblement, ça a l&#8217;air plutôt compliqué, mais pas impossible.<br />
Les semaines passent, et nous voici quasiment à la mi-février, date limite pour la soumission des conférences (CFP, ou <em>Call For Papers</em>). Là, je me dis que je m&#8217;en voudrais de ne pas avoir tenté ma chance, je décide donc de me lancer. Bien entendu, j&#8217;avais déjà réfléchit depuis plusieurs semaines à des sujets que je pourrais présenter. J&#8217;avais plus ou moins exclu mon domaine de prédilection, à savoir ce qui touche à l&#8217;usine logicielle (intégration continue, qualité logicielle avec Sonar, etc.) car je savais bien que d&#8217;autres personnes mieux placées que moi auraient plus de chances d&#8217;être sélectionnées. De plus, que dire de vraiment intéressant sur le sujet, sachant que l&#8217;audience d&#8217;un Devoxx est une audience de qualité, avec des gens très compétants qui connaissent très bien leur affaire ?</p>
<p>Bref, j&#8217;opte pour un sujet qui, à mon avis, peut avoir son attrait : l&#8217;industrialisation des tests JavaScript. J&#8217;avoue que je ne suis un grand expert dans le domaine, mais j&#8217;ai suffisament de connaissances pour en parler. Le temps presse avant la fin du CFP, il faut donc soumettre l&#8217;<em>abstract</em> rapidement, même si le contenu n&#8217;est pas encore tout à fait clair. Connaissant l&#8217;esprit et le ton décalés de Devoxx, je choisis un titre un peu fun : <strong>Chouchoutez votre code JavaScript</strong>. J&#8217;envoie donc ma proposition dans la catégorie <em>Tools In Action</em>. Cette catégorie est parfaite pour moi : une durée de 30 minutes, ce qui n&#8217;est ni trop court ni trop long, et un angle démo très prononcé. De plus, l&#8217;entrée à la conférence est offerte pour les speakers des <em>Tools In Action</em>, ce qui ne gâche rien.</p>
<p>Pour le fun, je soumets une deuxième proposition, cette fois-ci sous forme de <em>Quickie</em> (présentation rapide de 15 minutes) : <strong>TestNG, parce que vos tests le valent bien</strong>. J&#8217;ai soumis ce <em>Quickie</em> pour 2 raisons essentiellement :</p>
<ul>
<li>Parler de <a href="http://testng.org/doc/index.html" onclick="pageTracker._trackPageview('/outgoing/testng.org/doc/index.html?referer=');">TestNG</a>, un outil trop méconnu, loin derrière le fameux JUnit, et qui ne manque pourtant pas de qualités ;</li>
<li>Avoir une chance de plus d&#8217;être conférencier, au cas-où mon <em>Tools In Action</em> soit refusé.</li>
</ul>
<p>Voilà, les soumissons sont closes, l&#8217;équipe de Devoxx, en charge de faire le tri parmi tous les sujets, fait déjà une première constatation : c&#8217;est un carton plein ! Pas moins de 464 soumissions ont été faites ! Waouh, c&#8217;est impressionnant. C&#8217;est aussi beaucoup de stress, car on se dit que cela réduit les chances d&#8217;être choisi&#8230;</p>
<h3>En attendant Devoxx France</h3>
<div id="attachment_258" class="wp-caption aligncenter" style="width: 321px"><a href="http://linsolas.free.fr/wordpress/wp-content/uploads/Entree-Devoxx.jpg"><img src="http://linsolas.free.fr/wordpress/wp-content/uploads/Entree-Devoxx.jpg" alt="" title="Entree Devoxx" width="311" height="408" class="size-full wp-image-258" /></a><p class="wp-caption-text">Devoxx, ça arrive à grands pas !</p></div>
<p>L&#8217;équipe de Devoxx travaille vite, et le 16 février au matin, je reçois un mail : <em>Your DevoxxFrance 2012 presentation was approved</em>, qui commence par ces quelques mots : <em>We&#8217;re excited to inform you that your &laquo;&nbsp;Chouchoutez votre code JavaScript&nbsp;&raquo; Tools in Action presentation has been accepted for DevoxxFrance 2012</em>. Ce mail a tout simplement illuminé ma journée, ma semaine. C&#8217;était inespéré, me voilà donc conférencier pour Devoxx !</p>
<p>Ma session <em>Quickie</em> sur TestNG sera également retenue, d&#8217;abord en backup, puis officiellement. Je n&#8217;imaginais pas être voir l&#8217;une de mes soumissions acceptées, mais alors les deux ! Quelle joie&#8230; mais aussi quel défi. Je me rends finalement compte que ma chance a été de taper dans les catégories moins plébiscitée par les autres personnes. En effet, du côté des conférences (de 55 minutes), il me semble que seuls 17% des soumissions ont été acceptées !</p>
<p>Bon, ce n&#8217;est pas tout ça, mais il faut maintenant définir concrètement le contenu de mes deux présentations. Du côté de TestNG, je sais plus ou moins de quoi je parlerais, et comme ce sera avant tout des slides, je mets leur préparation de côté.</p>
<p>Pour <strong>Chouchoutez votre code JavaScript</strong>, j&#8217;ai déjà une ligne directrice assez claire, mais les détails restent flous : je commencerais à travailler avec <a href="http://pivotal.github.com/jasmine/" onclick="pageTracker._trackPageview('/outgoing/pivotal.github.com/jasmine/?referer=');">Jasmine</a>, un framework de tests (orienté BDD) pour du code JavaScript. Puis, je passerais sur une analyse avec l&#8217;outil <a href="http://www.sonarsource.com/" onclick="pageTracker._trackPageview('/outgoing/www.sonarsource.com/?referer=');">Sonar</a>, et je finirais par incorporer le tout dans un serveur d&#8217;intégration continue (<a href="http://jenkins-ci.org/" onclick="pageTracker._trackPageview('/outgoing/jenkins-ci.org/?referer=');">Jenkins</a> dans mon cas). Mes multiples essais sur ma machine donnent de bons résultats, mais il y a hélas un manque : avec tout ceci, je n&#8217;obtiens pas la couverture du code par les tests, chose aisée lorsque l&#8217;on travaille avec du code Java.<br />
Et puis début mars, c&#8217;est la délivrance ! Sur la <em>mailing list</em> de Sonar, je vois un message annonçant l&#8217;arrivée de la version 0.4 du <a href="http://docs.codehaus.org/display/SONAR/JavaScript+Plugin" onclick="pageTracker._trackPageview('/outgoing/docs.codehaus.org/display/SONAR/JavaScript+Plugin?referer=');">plugin JavaScript pour Sonar</a>, avec en particulier le support de la couverture de code par <a href="http://code.google.com/p/js-test-driver/" onclick="pageTracker._trackPageview('/outgoing/code.google.com/p/js-test-driver/?referer=');">js-test-driver</a>. Je m&#8217;intéresse donc à cette librairie, et découvre avec joie que Jasmine propose un adaptateur pour js-test-driver.<br />
Il ne me faudra pas beaucoup de temps pour faire marcher le tout ensemble, et obtenir ce que je voulais. Je suis sauvé <img src='http://linsolas.free.fr/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  !</p>
<p>Je m&#8217;occupe dès lors de mon <em>Quickie</em> sur TestNG. Les choses sont plus faciles, mais je m&#8217;aperçois que j&#8217;ai quelques années de retard <img src='http://linsolas.free.fr/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  En effet, TestNG est une excellente librairie de tests pour Java, qui offre depuis 2004 des fonctionnalités avancées que JUnit ne propose pas, ou alors seulement depuis 1 an ou 2. Je pense aux tests groupes de tests, à la dépendance entre tests, aux <em>listeners</em>, aux tests paramétrés, etc. Mais bon, je vais faire avec, et montrer que même avec les avancées de JUnit, TestNG reste une alternative qui a tout son sens, et qui dispose toujours de beaucoup d&#8217;atouts !</p>
<p><a href="http://linsolas.free.fr/wordpress/wp-content/uploads/producticon_powerpoint.png"><img src="http://linsolas.free.fr/wordpress/wp-content/uploads/producticon_powerpoint.png" alt="" title="producticon_powerpoint" width="54" height="65" class="alignleft size-full wp-image-262" /></a>L&#8217;équipe de Devoxx fournit les templates pour Open Office, Microsoft Office et Apple Keynote. Etant sur Mac, j&#8217;avais tout d&#8217;abord opté pour Open Office. Après moults échecs dans mes tentatives de faire des slides à peu près jolis, je me suis dit que j&#8217;allais les faire sur un PC avec Office, et que je les jouerais avec Open Office sur mon Mac. Pas une très grande idée. Puis, j&#8217;ai décidé d&#8217;installer la version d&#8217;évaluation d&#8217;Office pour Mac, et je dois dire que je suis très rapidement tombé sous le charme.</p>
<p>Les choses vont donc bon train, mais rien ne vaut une vraie répétition. J&#8217;organise donc une répétition sur mon lieu de travail pour une poignée de collègues, une semaine avant le début de Devoxx France. Compte tenu que je vais emporter mon Mac perso, je n&#8217;aurais donc aucun réseau. La veille de cette répétition, je décide donc de la jouer chez moi, tout seul, mais en coupant mon wifi ! Grand bien m&#8217;en a pris ! Maven ne semble pas avoir apprécié sa déconnexion, et c&#8217;est une riche idée que j&#8217;ai eue de le tester en mode déconnecté.</p>
<p>Une chose à ce propos m&#8217;a un peu interpellé : ma démonstration sur le code JavaScript commence par la création d&#8217;un squelette de projet via un archetype JavaScript (<code>de.akquinet.javascript.archetypes:javascript-quickstart</code> pour être précis). Or, en mode déconnecté, la commande <code>mvn archetype:generate</code> ne me liste qu&#8217;une cinquantaine de choix (contre 578 une fois le wifi réactivé). Il m&#8217;a été impossible de trouver une option pour que Maven (ou le plugin Archetype) télécharge de lui-même le catalogue des archetypes sur le repository officiel de Maven. J&#8217;ai dû copié le <em>archetype-catalog.xml</em> manuellement pour qu&#8217;il reconnaisse bien l&#8217;ensemble des archetypes, même en mode déconnecté. Si vous avez une idée du pourquoi, n&#8217;hésitez pas à m&#8217;en faire part !!</p>
<p>Bon, à quelques petits détails près, ma répétition est appréciée, et en plus, j&#8217;ai réussi à tenir mes timings. Ca s&#8217;annonce plutôt pas mal&#8230;</p>
<p>Dernier petit stress : le week-end précédant Devoxx, Nicolas Martignole de l&#8217;équipe d&#8217;organisation, demande aux speakers de bien respecter le format &laquo;&nbsp;officiel&nbsp;&raquo; des slides, à savoir 1280&#215;720, en particulier pour les conférences filmées (à savoir toutes, sauf les <em>Quickies</em>). Et dire que j&#8217;avais tout préparé en 1024&#215;768 (la faute à mon Mac qui ne permet pas l&#8217;affichage en 16:9). Donc par souci de respect du protocole, me voici à copier ma présentation du format 1024&#215;768 vers 1280&#215;720. J&#8217;étais assez content que ma présentation soit surtout basée sur de la démonstration, et que du coup je n&#8217;avais qu&#8217;assez peu de slides (19 quand même).</p>
<h3>Les jours J !</h3>
<p>Mon <em>Tools In Action</em> sur JavaScript a lieu le premier jour de Devoxx France, à savoir le mercredi 18 avril. Je passe en fin d&#8217;après-midi, à 17h40. Tout pourrait aller à merveille, s&#8217;il n&#8217;y avait pas un petit souci d&#8217;ordre médical : je souffrais alors d&#8217;une angine ! 39,5 la veile au soir, j&#8217;avoue que je n&#8217;étais pas en grande forme. C&#8217;est donc à grand renfort de paracétamol (un traitement plus adapté suivra le lendemain, après avoir vu ma guérisseuse) que j&#8217;assiste aux premières conférences. L&#8217;après-midi, je le passerais à peaufiner ma présentation (c&#8217;est d&#8217;ailleurs 30 minutes avant ma présentation que j&#8217;ai rajouté les petits Godzilla en bas de mes slides, pour indiquer l&#8217;avancée dans ma présentation), à discuter avec d&#8217;autres personnes, et à assister à Code Story.<br />
Puis, vint mon tour. Chose assez étrange : je n&#8217;ai pas (ou si peu) stressé avant, pensant que je stresserais comme un fou le jour J. Finalement, rien de tout cela, j&#8217;étais juste excité &#8211; dans le bon sens du terme &#8211; d&#8217;entrer sur scène ! Et pourtant, la salle, d&#8217;une capacité de plus de 200 personnes, était quasiment pleine !</p>
<div id="attachment_241" class="wp-caption aligncenter" style="width: 810px"><a href="http://linsolas.free.fr/wordpress/wp-content/uploads/IMG_1876-web.jpg"><img src="http://linsolas.free.fr/wordpress/wp-content/uploads/IMG_1876-web.jpg" alt="" title="IMG_1876-web" width="800" height="533" class="size-full wp-image-241" /></a><p class="wp-caption-text">Oui, il y avait du monde !</p></div>
<div id="attachment_242" class="wp-caption aligncenter" style="width: 810px"><a href="http://linsolas.free.fr/wordpress/wp-content/uploads/IMG_1880-web.jpg"><img src="http://linsolas.free.fr/wordpress/wp-content/uploads/IMG_1880-web.jpg" alt="" title="IMG_1880-web" width="800" height="533" class="size-full wp-image-242" /></a><p class="wp-caption-text">La preuve que c'était bien moi !</p></div>
<p>Je commence ma présentation, et à peine 3 minutes après le début de celle-ci, je m&#8217;&nbsp;&raquo;offre&nbsp;&raquo; un bel effet démo ! Après avoir créer mon projet via l&#8217;archetype Maven, je m&#8217;en vais l&#8217;importer dans Eclipse&#8230; et là, c&#8217;est le drame ! Je commence par me tromper dans le chemin exact contenant mon projet, puis je me trompe dans la fenêtre de création de projets&#8230; bref, je commençais à paniquer (intérieurement seulement). Fort heureusement, le problème finit très vite par se régler, et le reste de la démonstration se passe à merveille ! Chose inattendue : au moment où j&#8217;obtiens la couverture de mon code JavaScript par mes tests sur Sonar, l&#8217;audience applaudit <img src='http://linsolas.free.fr/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Ca fait chaud au coeur tout ça ! Je termine ma présentation dans les temps, j&#8217;ai même 4 minutes de questions, assez nombreuses d&#8217;ailleurs.</p>
<div id="attachment_244" class="wp-caption aligncenter" style="width: 370px"><a href="http://linsolas.free.fr/wordpress/wp-content/uploads/photo.png"><img src="http://linsolas.free.fr/wordpress/wp-content/uploads/photo.png" alt="" title="avis-devoxx-sur-twitter" width="360" height="540" class="size-full wp-image-244" /></a><p class="wp-caption-text">Visiblement, les retours sont bons, sur Twitter !</p></div>
<p>Le soir, un diner réservé aux speakers est prévu, je comptais y aller, mais j&#8217;ai préféré renoncé, compte tenu de mon état de santé. Ce mercredi, j&#8217;ai quitté Devoxx seulement quelques minutes après ma présentation, avec une énorme satisfaction. Pour moi, la mission était accomplie !</p>
<p>Le jeudi sera plus calme pour moi, car c&#8217;est la seule journée où je ne présente rien.</p>
<p>Le vendredi, mon <em>Quickie</em> passe à 12:35. La salle était, cette fois-ci, presque vide. Mais c&#8217;était à prévoir, les <em>Quickies</em> (surtout les premiers) étant planifiés en plein durant la pause déjeuner. J&#8217;ai fait ma présentation de TestNG sans grand souci, hormis que j&#8217;ai mis exactement 15 minutes pour la faire, alors que je voulais me réserver 2 / 3 minutes pour faire quelques démonstrations sous Eclipse. Tant pis, mais ce n&#8217;est pas grave&#8230;</p>
<h3>Vivement Devoxx World et Devoxx France 2013</h3>
<p>Finalement, Devoxx fut une conférence de très grande qualité, et faire partie des conférenciers fût pour moi une merveilleuse aventure !<br />
Je remercie chaleureusement l&#8217;équipe de sélection de Devoxx pour m&#8217;avoir fait confiance, et avoir sélectionné mes deux présentations. Être conférencier Devoxx, c&#8217;est une énorme fierté en ce qui me concerne, et j&#8217;espère que ce sera partie remise l&#8217;année prochaine. J&#8217;espère d&#8217;ailleurs pouvoir proposer une vraie conférence (d&#8217;une heure), et pourquoi pas avec une autre personne&#8230; Mais d&#8217;ici-là, beaucoup de choses se seront passées !</p>
<p>Mille mercis aussi à <a href="http://cfalguiere.wordpress.com/" onclick="pageTracker._trackPageview('/outgoing/cfalguiere.wordpress.com/?referer=');">Claude Falguière</a> pour ses photos de Devoxx, ce qui me permet d&#8217;avoir un sacré souvenir de ma présentation (en attendant la vidéo sur Parleys <img src='http://linsolas.free.fr/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ) !</p>
<a href="javascript:toggleStartStop();PicLensLite.start({feedUrl:'http://linsolas.free.fr/wordpress/wp-content/plugins/wp-piclens/mrss.php?id=243'});">Start Slide Show with PicLens Lite <img src="http://linsolas.free.fr/wordpress/wp-content/plugins/wp-piclens/PicLensButton.png" alt="PicLens" width="16" height="12" border="0" align="top"></a>]]></content:encoded>
			<wfw:commentRss>http://linsolas.free.fr/wordpress/index.php/2012/05/etre-conferencier-a-devoxx-france/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Devoxx France &#8211; Dernier jour</title>
		<link>http://linsolas.free.fr/wordpress/index.php/2012/04/devoxx-france-dernier-jour/</link>
		<comments>http://linsolas.free.fr/wordpress/index.php/2012/04/devoxx-france-dernier-jour/#comments</comments>
		<pubDate>Mon, 23 Apr 2012 22:23:20 +0000</pubDate>
		<dc:creator>Romain</dc:creator>
				<category><![CDATA[conférence]]></category>

		<guid isPermaLink="false">http://linsolas.free.fr/wordpress/?p=236</guid>
		<description><![CDATA[Toute bonne chose a une fin, Devoxx n&#8217;en est hélas pas l&#8217;exception. Voilà donc le dernier jour qui arrive, avec son lot de keynotes, conférences, rencontres&#8230; Je vais très rapidement zapper la toute première keynote, d&#8217;IBM. C&#8217;est un concentré, en une petite demi-heure, de ce qu&#8217;il ne faut pas faire dans une conférence, surtout à [...]]]></description>
			<content:encoded><![CDATA[<p>Toute bonne chose a une fin, Devoxx n&#8217;en est hélas pas l&#8217;exception. Voilà donc le dernier jour qui arrive, avec son lot de keynotes, conférences, rencontres&#8230;</p>
<p>Je vais très rapidement zapper la toute première keynote, d&#8217;IBM. C&#8217;est un concentré, en une petite demi-heure, de ce qu&#8217;il ne faut <b>pas</b> faire dans une conférence, surtout à Devoxx : commerciale, speaker plutôt mou, et à l&#8217;opposé des présentations zen (c&#8217;est-à-dire avec des slides bourrées de bullets points).<br />
Il suffisait de lire les tweets postés pendant la présentation pour comprendre que ce n&#8217;était pas du goût de l&#8217;auditoire !</p>
<p><span id="more-236"></span></p>
<hr/>
<h3><a href="http://devoxx.fr/display/FR12/Portrait+du+developpeur+en+The+Artist" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Portrait+du+developpeur+en+The+Artist?referer=');">Portrait du développeur en &laquo;&nbsp;The Artist&nbsp;&raquo;</a> par <a href="http://devoxx.fr/display/FR12/Patrick+Chanezon" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Patrick+Chanezon?referer=');">Patrick Chanezon</a></h3>
<p>Le conférencier suivant a un CV déjà bien rempli : il a travaillé chez Accenture, Netscape en France, puis Sun, Google (API / GAE), et enfin VMWare (CloudFoundry) aux USA.<br />
La première partie est consacrée à nous parler de la vie de George, à la façon &laquo;&nbsp;<em>The Artist</em>&laquo;&nbsp;.<br />
George est un développeur talentueux, et très vite devient indispensable à son projet. Ses chefs se disent qu&#8217;il serait bien de le mettre comme chef de projet, puis finalement comme DSI de sa boite&#8230; Mais voilà, George aime la technique, et si son niveau de golf s&#8217;améliore, il n&#8217;arrive déjà plus à lancer Eclipse, et est très vite dépassé par toutes les nouvelles technologies.<br />
Patrick nous explique finalement que si l&#8217;on souhaite conserver son niveau, il faudra rester proche de la technique, et toujours s&#8217;intéresser aux nouvelles technologies&#8230;</p>
<hr/>
<h3><a href="http://devoxx.fr/display/FR12/Abstraction+Distractions+for+France" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Abstraction+Distractions+for+France?referer=');">Abstraction Distractions for France</a> par <a href="http://devoxx.fr/display/FR12/Neal+Ford" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Neal+Ford?referer=');">Neal Ford</a></h3>
<p>Nous continuons avec une troisième keynote, elle aussi de très haut vol. Il faut dire que nous avons en face de nous Neal Ford, un architecte de <a href="http://www.thoughtworks.com/" onclick="pageTracker._trackPageview('/outgoing/www.thoughtworks.com/?referer=');">ThoughtWorks</a>, et plutôt talentueux conférencier.<br />
Cette fois-ci, il nous parle d&#8217;abstraction et de distraction. Difficile de retranscrire ici sa prestation, je vous la recommande sur Parleys dès qu&#8217;elle sera disponible. La moitié de la salle a fini debout pour applaudir le Maitre !</p>
<hr/>
<h3><a href="http://devoxx.fr/display/FR12/TestNG%2C+parce+que+vos+tests+le+valent+bien" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/TestNG_2C+parce+que+vos+tests+le+valent+bien?referer=');">TestNG, parce que vos tests le valent bien</a> par <a href="http://devoxx.fr/display/FR12/Romain+Linsolas" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Romain+Linsolas?referer=');">moi-même</a></h3>
<p>Je reviendrais un peu plus longuement dans un autre billet sur le Quickie que j&#8217;ai présenté.<br />
Il s&#8217;agit ici de montrer que <a href="http://testng.org/doc/index.html" onclick="pageTracker._trackPageview('/outgoing/testng.org/doc/index.html?referer=');">TestNG</a> dispose de nombreux atouts pour remplacer JUnit comme librairie de tests unitaires&#8230;</p>
<hr/>
<h3><a href="http://devoxx.fr/display/FR12/CRaSH+un+shell+pour+etendre+la+plateforme+Java" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/CRaSH+un+shell+pour+etendre+la+plateforme+Java?referer=');">CRaSH</a> par <a href="http://devoxx.fr/display/FR12/Julien+Viet" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Julien+Viet?referer=');">Julien Viet</a></h3>
<p>Julien Viet, de l&#8217;équipe d&#8217;<a href="http://www.exoplatform.com" onclick="pageTracker._trackPageview('/outgoing/www.exoplatform.com?referer=');">eXo plateform</a>, nous propose une petite démonstration de <a href="http://vietj.github.com/crash/" onclick="pageTracker._trackPageview('/outgoing/vietj.github.com/crash/?referer=');">CRaSH</a>, un shell qui permet de travailler directement avec / sur une JVM.<br />
Le principe est très simple : une fois installé et démarré, l&#8217;outil va se connecter sur une JVM, et on pourra alors exécuter un certain nombre de commandes :</p>
<ul>
<li>Lister les threads qui tournent sur la JVM ;</li>
<li>Utiliser CRaSH pour gérer les logs, en changeant par exemple dynamiquement le niveau des logs du serveur d&#8217;applications JBoss AS ;</li>
<li>Se connecter à la dataSource pour exécuter des requêtes SQL !</li>
</ul>
<p>Puis Julien nous explique que les commandes sont écrites en Groovy et toute modification d&#8217;une commande est prise en compte dynamiquement. Il est d&#8217;ailleurs très simple d&#8217;ajouter soit-même de nouvelles commandes.<br />
Bref, un bel outil, très extensible, qui mérite un coup d&#8217;oeil, même s&#8217;il ne faudra pas mettre cela entre toutes les mains !</p>
<hr/>
<h3><a href="http://devoxx.fr/display/FR12/Groovy+2.0+++quoi+de+neuf+doc" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Groovy+2.0+++quoi+de+neuf+doc?referer=');">Groovy 2.0 : quoi de neuf doc ?</a>, par <a href="http://devoxx.fr/display/FR12/Guillaume+Laforge" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Guillaume+Laforge?referer=');">Guillaume Laforge</a> et <a href="http://devoxx.fr/display/FR12/Cedric+Champeau" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Cedric+Champeau?referer=');">Cédric Champeau</a></h3>
<p>Guillaume et Cédric nous font un récapitulatif des nouveautés de Groovy 2.0 (mais aussi un peu de Groovy 1.8).<br />
En effet, déjà pas mal de choses ont été introduites par la version 1.8 du langage. Par exemple, les <em>Command chains</em>, rendant optionnelle l&#8217;écriture des <code>.</code> ou <code>( )</code>, lorsque l&#8217;on chaine des appels.<br />
Ainsi, ces codes :</p>
<pre class="brush: groovy;">
turn left then right
check that: margarita tastes good // named-args
given {} when {} then {}
select all unique() from name // Pour une méthode sans argument, on garde les ()
take 3 cookies
</pre>
<p>sont équivalents à ceux-ci :</p>
<pre class="brush: groovy;">
turn(left).then(right)
check(that: margarita).tastes(good) // named-args
given({})when({})then({})
select(all).unique().from(name)
take(3).cookies
</pre>
<p>Groovy intègre également <a href="http://gpars.codehaus.org/" onclick="pageTracker._trackPageview('/outgoing/gpars.codehaus.org/?referer=');">GPars</a> pour faire du parallélisme, de la concurrence.</p>
<p>Autre nouveauté : les <em>Closure annotation parameters</em>, ainsi que la <em>memoization</em>, c&#8217;est-à-dire que Groovy va se souvenir du dernier appel d&#8217;une closure pour cacher le résultat. Par exemple :</p>
<pre class="brush: groovy;">
                def plus = { a, b -&gt; sleep 1000; a + b}.memoize() // on &quot;simule&quot; un traitement lent avec le sleep...

                assert plus(1, 2) == 3 // Le retour sera fait après 1000ms
                assert plus(1, 2) == 3 // Ici, on utilise le cache, donc le retour est immédiat
                assert plus(2, 2) == 4 // Le retour sera fait après 1000ms, les paramètres étant différents.
                assert plus(2, 2) == 4 // Ici, retour immédiat
</pre>
<p>On peut affiner la façon dont Groovy va cacher les résultats, en limitant par exemple le nombre de valeurs à retenir (<code>.memoizeAtLeast(x)</code>, <code>.memoizeAtMost(42)</code>&#8230;).</p>
<p>Groovy ajoute désormais un support du JSON dans Groovy (avec les <code>JsonSlurper</code>, <code>JsonBuilder</code> et <code>JsonOutput</code>).</p>
<p>De nouvelle annotation (<em>AST transformations</em>) sont également à l&#8217;ordre du jour, comme par exemple <code>@Log</code> pour injecter automatiquement un logger.<br />
Des annotations pour le controle d&#8217;exécution sont là : <code>@ThreadInterrupt</code>, <code>@TimedInterrupt</code>.<br />
Les amateurs de Lombok seront aussi comblés, puisque Groovy intègre des annotations pour simplifier le code : <code>@ToString</code> (qui génère la méthode <code>toString()</code> automatiquement), <code>@TupleConstructor</code> (qui génère un constructeur avec les propriétés de la classe) ou encore <code>@InheritConstructors</code> (utile sur les exceptions où les constructeurs appelent juste des <code>super</code>).</p>
<p>Concernant Groovy 2.0, nous allons voir surtout la vérification stricte, ainsi que la compilation statique.<br />
A noter aussi que cette version offre plus de modularité : ce n&#8217;est plus seulement un gros jar, mais plusieurs modules.<br />
Groovy 2.0 s&#8217;adapte aussi à Java 7 :             </p>
<ul>
<li>project coin (écriture des nombres en binaire, avec des _)</li>
<li>multicatchs ;</li>
<li>opérateur diamand (pour écrire <code>List<String> list = new ArrayList<>();</code> plutôt que <code>List<String> list = new ArrayList<String>();</code>) ;</li>
<li><em>invokeDynamic</em>.</li>
</ul>
<p>Le <code>@TypeChecked</code> fait aussi son apparition. Cette annotation permet de vérifier beaucoup plus de chose lors de la compilation.<br />
Par exemple :</p>
<pre class="brush: groovy;">
@TypeChecked test() {  // On annote la classe ou la méthode
    metthhoood()           // Erreur à la compilation
    def name = &quot;Guillaume&quot;
    println                     // Erreur ici aussi !
}
</pre>
<p>Un autre exemple :</p>
<pre class="brush: groovy;">
@TypeChecked test() {
    [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;].collect(
        it.toUpperCase()
    )
}
</pre>
<p>ne compilera pas, car rien ne permettra d&#8217;assurer à Groovy que le <code>it</code> est bien un <code>String</code> (la méthode <code>collect</code> pourrait être alterée par exemple).<br />
Du coup, pour que le compilateur soit content, il faut caster le <code>it</code> comme ceci :</p>
<pre class="brush: groovy;">
@TypeChecked test() {
    [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;].collect(
        String it -&gt;
            it.toUpperCase()
    )
}
</pre>
<p>Dernier point apporté par Groovy 2.0, et non des moindres : la compilation statique. Celle-ci se dénote par l&#8217;annotation <code>@CompileStatic</code>.<br />
Les avantages d&#8217;une compilation statique sont :</p>
<ul>
<li>Les performances accrues, en particulier sur des JDK avant 7, ne disposant pas du <code>invokeDynamic</code> ;</li>
<li>Evite les problèmes liés au &laquo;&nbsp;<em>Monkey patching</em>&laquo;&nbsp;, c&#8217;est-à-dire que le code est &laquo;&nbsp;immunisé&nbsp;&raquo; contre la modification dynamique ;</li>
<li>Le bytecode généré sera bien plus petit.</li>
</ul>
<p>Reste que la compilation statique fait perdre les fonctionnalités dynamiques de Groovy (du moins sur le code compilé statiquement). Mais là, rien de bien gênant&#8230;</p>
<hr/>
<h3><a href="http://devoxx.fr/display/FR12/Android%2C+Graphisme+et+Performance" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Android_2C+Graphisme+et+Performance?referer=');">Android, graphisme et performances</a> par <a href="http://devoxx.fr/display/FR12/Romain+Guy" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Romain+Guy?referer=');">Romain Guy</a></h3>
<p>Romain Guy est un développeur français parti chez Sun où il a d&#8217;abord travaillé sur Swing, et est désormais chez Google comme développeur Android.<br />
Il nous donne sur cette conférence un aperçu des écueuils à éviter lorsque l&#8217;on développe sur Android, et en particulier de ce qu&#8217;il convient de faire pour avoir des applications performantes.<br />
Bon, je dois l&#8217;admettre, je n&#8217;ai pas retenu grand chose de la présentation car je ne développe pas pour Android. Toutefois, on voit que Romain connait son sujet, et qu&#8217;il maitrise l&#8217;art de la conférence. Bref, c&#8217;était agréable à écouter&#8230;</p>
<hr/>
<h3><a href="http://devoxx.fr/display/FR12/Les+Cast+Codeurs+Podcast" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Les+Cast+Codeurs+Podcast?referer=');">Les CastCodeurs en direct de Devoxx France</a></h3>
<p>Très bonne conclusion du Devoxx avec cet enregistrement en live des <a href="lescastcodeurs.com">CastCodeurs</a>.<br />
Un récapitulatif dans la joie, la bonne humeur et la bière (merci <a href="http://www.atlassian.com/fr/" onclick="pageTracker._trackPageview('/outgoing/www.atlassian.com/fr/?referer=');">Atlassian</a> pour ça !)</p>
<p>Vous pouvez retrouver <a href="http://lescastcodeurs.com/2012/04/les-cast-codeurs-podcast-episode-57-en-direct-de-devoxx-france-2012/" onclick="pageTracker._trackPageview('/outgoing/lescastcodeurs.com/2012/04/les-cast-codeurs-podcast-episode-57-en-direct-de-devoxx-france-2012/?referer=');">l&#8217;épisode spécial Devoxx France ici</a>.</p>
<hr/>
<h3>Conclusion</h3>
<p>Devoxx France, c&#8217;est fini, mais qu&#8217;est-ce que c&#8217;était bien !<br />
Des conférences de haut niveau, un public de geeks très nombreux et aussi de grande qualité, des rencontres vraiment sympas.<br />
Le fait d&#8217;avoir aussi été choisi comme conférencier pour parler de JavaScript (dans une présentation qui a visiblement plû au delà de mes espérances), et de TestNG rend ces jours vraiment inoubliables&#8230;</p>
<p>Bref, encore mille bravos à toute l&#8217;équipe organisatrice !</p>
]]></content:encoded>
			<wfw:commentRss>http://linsolas.free.fr/wordpress/index.php/2012/04/devoxx-france-dernier-jour/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Devoxx France &#8211; Deuxième jour</title>
		<link>http://linsolas.free.fr/wordpress/index.php/2012/04/devoxx-deuxieme-jour/</link>
		<comments>http://linsolas.free.fr/wordpress/index.php/2012/04/devoxx-deuxieme-jour/#comments</comments>
		<pubDate>Mon, 23 Apr 2012 22:03:42 +0000</pubDate>
		<dc:creator>Romain</dc:creator>
				<category><![CDATA[conférence]]></category>

		<guid isPermaLink="false">http://linsolas.free.fr/wordpress/?p=226</guid>
		<description><![CDATA[C&#8217;est parti pour cette deuxième journée. Cette fois-ci, tout le monde est là, environ 1250 geeks pour assister à 2 jours de conférences. Une petite visite chez le médecin en cette matinée m&#8217;a fait raté les keynotes. Je les regarderais sur Parleys lorsqu&#8217;elles seront disponibles. Mais en gros, on salue le succès de cette première [...]]]></description>
			<content:encoded><![CDATA[<p>C&#8217;est parti pour cette deuxième journée. Cette fois-ci, tout le monde est là, environ <strong>1250 geeks</strong> pour assister à 2 jours de conférences.</p>
<p>Une petite visite chez le médecin en cette matinée m&#8217;a fait raté les keynotes. Je les regarderais sur Parleys lorsqu&#8217;elles seront disponibles.<br />
Mais en gros, on salue le succès de cette première édition, et l&#8217;année 2013 verra elle aussi son édition parisienne du Devoxx ! J&#8217;ai déjà hâte d&#8217;y être !</p>
<p><span id="more-226"></span></p>
<hr/>
<h3><a href="http://devoxx.fr/pages/viewpage.action?pageId=6128386" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/pages/viewpage.action?pageId=6128386&amp;referer=');">Spring est mort, longue vie à Spring</a>, par <a href="http://devoxx.fr/display/FR12/Gildas+Cuisinier" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Gildas+Cuisinier?referer=');">Gildas Cuisinier</a></h3>
<p>Lorsque JavaEE 6 est sorti, on annonçait une guerre sans pitié avec Spring, et la fin proche de ce dernier.<br />
Cela fait déjà 2 ans que JavaEE est sorti, mais qu&#8217;en est-il aujourd&#8217;hui ?</p>
<p>A l&#8217;époque, avant sa version 6, JavaEE avait &laquo;&nbsp;menti&nbsp;&raquo;, en partiulier sur la soit disant simplicité du framework JavaEE, ainsi que sur la testabilité des applications l&#8217;utilisant&#8230;<br />
C&#8217;est alors que Spring est arrivé pour résoudre pas mal de problèmes.<br />
Initialement, toute la configuration se faisant avec des fichiers XML. Il faut dire que c&#8217;était à la mode, le XML !<br />
Puis, la complexité de cette configuration augmentant, les namespaces sont arrivés, pour mieux catégoriser sa configuration Spring. On y voyait déjà plus clair !</p>
<p>Un jour, Java 5 est arrivé, en introduisant les annotations dans le code Java. Ceci va impliquer une nouvelle évolution de Spring : la configuration via les annotations.<br />
En voici un exemple :</p>
<pre class="brush: java;">
@Component
public class Jedi {
    private Arme arme;
    @Autowired
    public void setArme(Arme arme) {
        this.arme = arme;
    }
}
</pre>
<p>Seul ombre au tableau : pour se passer d&#8217;écrire de la configuration en XML, il faut écrire&#8230; du XML. En effet, il faut indiquer à Spring quel(s) package(s) doivent être scannés pour y lire les annotations :</p>
<pre class="brush: xml;">
    &lt;context:component-scan base-package=&quot;xxx&quot;/&gt;
</pre>
<p>Entre temps, JavaEE est arrivé, et devient &laquo;&nbsp;sexy&nbsp;&raquo; : simplicité, testabilité, légèreté. Toutefois, cela demande une migration, non seulement du code, mais aussi des serveurs d&#8217;applications, car tous ne sont pas compatibles JavaEE 6.</p>
<p>De son côté, Spring sort en version 3.0 (décembre 2009), disposant de sa configuration par annotations.</p>
<p>Malgré l&#8217;arrivée de JavaEE 6, les équipes ne souhaitent pas abandonner Spring. Gildas nous le montre avec un certain nombre de statistiques tirées de son questionnaire Spring (entre 100 et 130 personnes y ont répondu).<br />
Aujourd&#8217;hui, Spring est toujours très présent, en particulier les version 3.x :</p>
<ul>
<li><b>50%</b> des sondés utilisent Spring 3.0 ;</li>
<li><b>23%</b> sont déjà passés à Spring 3.1 ;</li>
<li><b>19%</b> n&#8217;utilisent pas Spring ;</li>
<li><b>8%</b> sont restés sur des versions 2.0 ou 2.5 de Spring.</li>
<p>D&#8217;ailleurs, dans l&#8217;audience, seules <b>3</b> personnes utilisent JavaEE 6 en production, alors que la quasi totalité utilise Spring 2.5 / 3.0 en production. Très peu (pour l&#8217;heure), utilisent Spring 3.1 en production.</p>
<p>Les principaux reproches faits à Spring :</p>
<ul>
<li>Trop compliqué à mettre en place. Généralement, on travaille sur une application où Spring est déjà en place, on ne regarde pas comment cela fonctionne concrètement.</li>
<li>Invasif.</li>
<li>Trop de XML. Maintenant, on s&#8217;oriente beaucoup plus vers les annotations, comme pour JavaEE. Cependant, cela pose un autre souci : la configuration par annotations étant dispersée dans le code, il devient plus fastidieux d&#8217;avoir une vision globale de celle-ci&#8230;</li>
<li>L&#8217;aspect propriétaire. Toutefois, si SpringSource gère seul le code, mais reste ouvert aux propositions.</li>
</li>
<p>Gildas parle ensuite de Spring 3.1. Qu&#8217;apporte-t-il ?<br />
Spring 3.1 finit ce que Spring 3.0 avait introduit : tout est désormais annotable, on peut faire du &laquo;&nbsp;<em>NoXML</em>&nbsp;&raquo; !<br />
L&#8217;exemple cité plus haut s&#8217;écrira désormais ainsi :</p>
<pre class="brush: java;">
@Configuration
@ComponentScan(&quot;xxx&quot;)
public class Configuration {
    ...
}
</pre>
<p>De nouvelles annotations arrivent, pour gérer le <em>scheduling</em> (<code>@EnableScheduling</code>) ou encore pour configurer Spring MVC (<code>@EnableWebMvc</code>).<br />
Les annotations ne permettent pas tout, et il est parfois nécessaire, en plus d&#8217;annoter sa classe, d&#8217;étendre une classe de Spring (exemple : les Interceptors MVC).</p>
<p>D&#8217;autres points intéressants sur Spring 3.1 :</p>
<ul>
<li>Support d&#8217;Hibernate 4 ;</li>
<li>Namespace <code>c:</code> (pour simplifier les constructeurs) ;</li>
<li>JPA sans le <code>persistence.xml</code> ;</li>
<li>Amélioration du support REST dans Spring MVC ;</li>
<li>FlashMap dans Spring MVC.</li>
</ul>
<p>En conclusion, Spring est loin d&#8217;être mort, car l&#8217;adoption de JavaEE est encore loin d&#8217;être une réalité, et de plus, Spring dispose de tout un écosystème autour de lui : SpringData, SpringMobile, SpringSocial, SpringBatch, etc.</p>
<hr/>
<p>Après la pause déjeuner, je vais zapper les conférences, et aller voir un peu ce qui se fait du côté de <b>Code Story</b>&#8230;</p>
<h3><a href="http://devoxx.fr/display/FR12/Code+story" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Code+story?referer=');">Code Story</a></h3>
<p><a href="http://www.code-story.net/" onclick="pageTracker._trackPageview('/outgoing/www.code-story.net/?referer=');">Le principe</a> : 4 développeurs (<a href="http://devoxx.fr/display/FR12/David+Gageot" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/David+Gageot?referer=');">David Gageot</a>, <a href="http://devoxx.fr/display/FR12/Jean-laurent+De+morlhon" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Jean-laurent+De+morlhon?referer=');">Jean-Laurent de Morlhon</a>, <a href="http://devoxx.fr/display/FR12/Sebastian+Le+merdy" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Sebastian+Le+merdy?referer=');">Sébastien</a> et <a href="http://devoxx.fr/display/FR12/Eric+Le+merdy" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Eric+Le+merdy?referer=');">Eric</a> le Merdy) se chargent du développement d&#8217;une application se connectant à Github pour créer un historique de projet.<br />
Ensuite, cette application va s&#8217;interfacer avec Jenkins, Sonar, Trello, etc. pour pouvoir ajouter des événements dans la vie du projet (build cassé, règle de qualité non respectée, etc.).<br />
Au final, l&#8217;application devrait pouvoir attribuer des badges aux développeurs du projet surveillé : le meilleur casseur de build, le commiteur le plus prolifique, etc.<br />
Tout se fait bien entendu en live, en partant de zéro.</p>
<p>Chaque itération dure environ 1 heure, avec 2 sessions de 25 minutes de développement.<br />
Au début, un petit stand-up meeting pour expliquer ce qui va être fait dans l&#8217;itération, et à la fin, une rétrospective pour expliquer les accomplissements, ainsi que les difficultés rencontrées.<br />
Concrètement, l&#8217;équipe se divise en 2 binômes :</p>
<ul>
<li>Le premier binôme est au front : il code face à l&#8217;audience, et explique à voix haute ce qu&#8217;il fait.</li>
<li>Le second binôme travaille plus en retrait, et on ne voit pas concrètement ce sur quoi il travaille (mais on finit par le savoir lors de la rétrospective de fin d&#8217;itération).</li>
</ul>
<p>Deux vidéo-projecteurs nous permettent de suivre leur travail en direct. Le premier diffuse l&#8217;écran du premier binôme (en général pour montrer soit IntelliJ, soit une console shell, soit le navigateur web), le second montre le &laquo;&nbsp;serveur&nbsp;&raquo;, avec Jenkins ou Sonar qui analysent en permanence le travail commité sur GitHub.</p>
<p>Lorsque j&#8217;y suis allé, le projet n&#8217;en était encore qu&#8217;à ses débuts, et l&#8217;équipe mettait en place le déploiement automatisé, et commençait à écrire ses premières pages web.<br />
Mais il était intéressant de voir 4 développeurs plutôt talentueux (dont 3 ex-collègues à moi <img src='http://linsolas.free.fr/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ) travailler en direct live, dans des conditions proches de la réalité (avec des dead-lines très courtes).<br />
D&#8217;ailleurs, à en voir les retours, ce Code Story a été très apprécié. Plusieurs fois j&#8217;ai voulu y retourner, mais à chaque fois, j&#8217;ai été obligé de rester en dehors de la salle, tant elle était perpétuellement remplie !</p>
<p>A noter que lorsque j&#8217;y suis passé, l&#8217;équipe avait déjà eu recours à pas mal d&#8217;outils ou de librairies :</p>
<ul>
<li><a href="https://github.com" onclick="pageTracker._trackPageview('/outgoing/github.com?referer=');">Github (version entreprise)</a> pour stocker le code ;</li>
<li><a href="http://infinitest.github.com/" onclick="pageTracker._trackPageview('/outgoing/infinitest.github.com/?referer=');">Infinitest</a> pour laisser l&#8217;IDE exécuter en permance les tests unitaires ;</li>
<li><a href="http://zombie.labnotes.org/" onclick="pageTracker._trackPageview('/outgoing/zombie.labnotes.org/?referer=');">Zombie.js</a> un framework JavaScript pour tester l&#8217;interface web ;</li>
<li><a href="http://visionmedia.github.com/mocha/" onclick="pageTracker._trackPageview('/outgoing/visionmedia.github.com/mocha/?referer=');">Mocha</a> un autre framework de tests JavaScript ;</li>
<li><a href="http://jersey.java.net/" onclick="pageTracker._trackPageview('/outgoing/jersey.java.net/?referer=');">Jersey</a>, une librairie Java pour faire du REST ;</li>
<li><a href="http://code.google.com/p/fest/" onclick="pageTracker._trackPageview('/outgoing/code.google.com/p/fest/?referer=');">Fest-assert</a>, une extension à JUnit (ou TestNG) pour écrire des assertions de manière plus fluide (<em>fluent</em>) ;</li>
<li><a href="http://code.google.com/p/guava-libraries/" onclick="pageTracker._trackPageview('/outgoing/code.google.com/p/guava-libraries/?referer=');">Guava</a> l&#8217;incontournable librairie de Google pour ajouter tant de choses manquantes à Java !</li>
<li><a href="http://growl.info/" onclick="pageTracker._trackPageview('/outgoing/growl.info/?referer=');">Growl</a> un outil de notification pour Mac, affichant une notification à chaque fois que l&#8217;application vient à builder ;</li>
<li><a href="http://jenkins-ci.org/" onclick="pageTracker._trackPageview('/outgoing/jenkins-ci.org/?referer=');">Jenkins</a> pour l&#8217;intégration continue ;</li>
<li><a href="http://www.sonarsource.org/" onclick="pageTracker._trackPageview('/outgoing/www.sonarsource.org/?referer=');">Sonar</a> pour l&#8217;analyse qualité ;</a>
<li><a href="http://www.jetbrains.com/idea/" onclick="pageTracker._trackPageview('/outgoing/www.jetbrains.com/idea/?referer=');">IntelliJ</a>, l&#8217;IDE Java de référence ;</li>
<li><a href="https://trello.com/" onclick="pageTracker._trackPageview('/outgoing/trello.com/?referer=');">Trello</a> comme mur à post-its virtuel, permettant de planifier les tâches des itérations ;</li>
<li><a href="http://mustache.github.com/" onclick="pageTracker._trackPageview('/outgoing/mustache.github.com/?referer=');">Mustache.js</a> un framework JavaScript de templating.</li>
</ul>
<p>L&#8217;équipe a mis en place le <b>build incassable</b> : on ne committe que si ça compile bien chez soi. Du coup, Jenkins devient moins utile. D&#8217;ailleurs, à ce propos, il faut noter que David Gageot est <a href="http://blog.javabien.net/2009/12/01/serverless-ci-with-git/" onclick="pageTracker._trackPageview('/outgoing/blog.javabien.net/2009/12/01/serverless-ci-with-git/?referer=');">partisan de l&#8217;intégration continue sans serveur</a> !<br />
Grawl est également mis en place pour offrir un maximum de réactivité : dès qu&#8217;un commit est réalisé sur le repository Git, Grawl nous indique qu&#8217;un build Jenkins démarre&#8230; puis quelques secondes plus tard il nous indique que le build est terminé, avec succès bien sûr !</p>
<p>Une librairie qui a atiré mon attention, c&#8217;est <b>Mustache.js</b>, qui permet de faire du <em>templating</em> en JavaScript.<br />
Voici un exemple tout simple :</p>
<pre class="brush: jscript;">
&lt;script type=&quot;x-template&quot; id=&quot;commit-template&quot;&gt;
    {{#commit}}
        &lt;div class=&quot;commit&quot;&gt;{{author}}&lt;/div&gt;
    {{/commit}}
&lt;/script&gt;

Mustache.to_html($(&quot;commit-template&quot;).html, json);
</pre>
<p>Bref, une très jolie expérience que ce Code Story ! Dommage que je n&#8217;ai pu assister à des sessions vers la fin, pour voir le projet presque abouti.<br />
Toujours est il que le <a href="https://github.com/dgageot/CodeStoryDevoxx" onclick="pageTracker._trackPageview('/outgoing/github.com/dgageot/CodeStoryDevoxx?referer=');">code est à retrouver sur GitHub</a>.</p>
<hr/>
<h3><a href="http://devoxx.fr/pages/viewpage.action?pageId=6128306" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/pages/viewpage.action?pageId=6128306&amp;referer=');">BigData et Hadoop</a> par <a href="http://devoxx.fr/display/FR12/Pablo+Lopez" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Pablo+Lopez?referer=');">Pablio Lopez</a></h3>
<p>Pablo Lopez nous parle d&#8217;une expérience vraiment très intéressante. Il travaille pour une grande société de vente de produits en ligne (il ne le citera pas, mais il s&#8217;agit d&#8217;une société à l&#8217;image ferroviaire vendant différentes prestations de voyages).<br />
Celle-ci gère environ 1,000,000 de visiteurs uniques par jour, et environ 1/5 de ces visiteurs réalisent une commande.<br />
Ce sont ainsi au total environ 65,000,000 commandes par an, avec un pic, autour de mi-octobre, de 350,000 ventes pour une seule journée !<br />
L&#8217;ambition : être le leader mondial dans son activité dans les 3 ans. Rien que ça, pour, ce qui était il y a encore 10 ans à peine, une startup&#8230;</p>
<p>Côté technique, nous avons 500 serveurs de production, gérant environ 80 applications, chaque serveur disposant de 5 JVM. L&#8217;utilisateur navigue sur 13 niveaux de load balancing. Joli !<br />
Au final, chaque serveur va générer 7 Go de logs quotidiennement ! Il est donc difficile de gérer un tel volume !<br />
Ce qu&#8217;il faut, c&#8217;est :</p>
<ul>
<li><b>Centraliser</b> les logs ;</li>
<li><b>Sécuriser</b> les fichiers de logs, les sauvegarder ;</li>
<li><b>Analyser</b> : pouvoir récupérer les informations selon des catégories (paiement, recherche, etc.) ;</li>
<li><b>Informer</b> les bonnes personnes avec les bonnes informations ;</li>
<li><b>Archiver</b>, pouvoir comparer les logs d&#8217;une journée sur l&#8217;autre, d&#8217;une semaine sur l&#8217;autre, d&#8217;un mois sur l&#8217;autre, etc.</li>
<li>Et tout cela en <b>temps réel</b> s&#8217;il vous plait !</li>
</li>
<p>Etant un site de e-commerce, on doit avoir une disponibilité de 99,995%, ainsi qu&#8217;un temps de réponse sous la seconde (voire même sous les 200 ms). Et là dessus, il n&#8217;y a pas de négociation possible !<br />
La base de données étant le &laquo;&nbsp;<em>Single point of failure</em>&nbsp;&raquo; (goulot d&#8217;étranglement), il ne faut surtout pas la surcharger !</p>
<p>Quelles solutions ?</p>
<p>Pour arriver à leurs fins, l&#8217;équipe de Pablo va avoir recours à :</p>
<ul>
<li><a href="http://www.mongodb.org/" onclick="pageTracker._trackPageview('/outgoing/www.mongodb.org/?referer=');">MongoDB</a> une base de données NoSQL ;</li>
<li><a href="http://www.playframework.org/" onclick="pageTracker._trackPageview('/outgoing/www.playframework.org/?referer=');">Play</a> pour afficher des statistiques, des rapports ;</li>
<li><a href="http://hadoop.apache.org/" onclick="pageTracker._trackPageview('/outgoing/hadoop.apache.org/?referer=');">Hadoop</a> </li>
<li><a href="https://github.com/cloudera/flume" onclick="pageTracker._trackPageview('/outgoing/github.com/cloudera/flume?referer=');">Flume</a> </li>
</ul>
<p>Les outils doivent tenir la charge, être scalables, avoir une excellente tolérance à la panne.</p>
<p>Première chose : centraliser les logs, et le plus vite possible. Pour cela, ils font appel à SyslogAppender, un appender de log4j, qui peut transmettre les logs via UDP. De l&#8217;autre côté, syslog-ng est utilisé pour écouter ces packets UDP.</p>
<p><a href="https://github.com/cloudera/flume" onclick="pageTracker._trackPageview('/outgoing/github.com/cloudera/flume?referer=');">Flume</a> est utilisé pour pouvoir copier les logs sur des systèmes de fichiers distribués (hdfs).</p>
<p>Second point : sécuriser les fichiers.<br />
HDFS (Hadoop Distributed File System) est utilisé ici. Chaque log est copié 3 fois, sur des disques &laquo;&nbsp;classiques&nbsp;&raquo;. Cette duplication rend ainsi obsolète des système de type RAID.<br />
hdfs travaille mal avec des &laquo;&nbsp;petits&nbsp;&raquo; fichiers (moins de 64Mo). Pour résoudre ce problème on regroupe plusieurs &laquo;&nbsp;petits&nbsp;&raquo; fichiers un seul (fichier de type .har).</p>
<p>Il faut maintenant analyser les logs, par &laquo;&nbsp;tranche&nbsp;&raquo; de 64M (sur le principe du principe map / reduce).</p>
<p>Les rapports d&#8217;analyse sont stockés sur du MongoDB :</p>
<ul>
<li>Elasticité du modèle, pour le faire évoluer facilement ;</li>
<li>Facilement interrogeable, avec du JSON ;</li>
<li>Maturité de l&#8217;API de requêtage ;</li>
<li>Scalabilité.</li>
</ul>
<p>Play! est utilisé pour représenter les rapports d&#8217;analyse. Play! est choisi pour sa facilité de mise en oeuvre, son intégration de JSON et MongoDB, etc.</p>
<p>Dernière problématique : le temps réel !</p>
<p>Premier souci : Hadoop ne sait pas faire de map / reduce sur des fichiers non fermés (or ici, tout est en streaming). Flume va résoudre ce problème en fermant les fichiers à chaque minute.<br />
Hélas, le temps de traitement du map / reduce est alors d&#8217;environ 45 minutes ! Beaucoup trop long !<br />
La première correction sera de modifier le cluster. Ensuite, les JVM gérées par Hadoop sont tunées, en particulier pour la gestion mémoire.<br />
L&#8217;interaction avec Flume est également améliorée. On arrive maintenant à 6 minutes. C&#8217;est déjà mieux, mais le temps doit encore être réduit !<br />
On optimise l&#8217;utilisation de Java : suppression de librairies tierces, optimisation de la sérialisation des objets, etc.<br />
Au final, on arrive à 45 secondes pour traiter 1 minute de logs.</p>
<p>Quelle est l&#8217;utilisation quotidienne de ce système ?</p>
<ul>
<li>Analyse quotidienne des logs, pour le <em>SLA</em> (&laquo;&nbsp;<em>Service Level Agreement</em>&laquo;&nbsp;, autrement dit un document définissant le niveau de qualité attendu) ;</li>
<li>Corrélation des logs. Si un utilisateur a eu un problème, il faut savoir identifier les serveurs par lesquels il est passé (on rappelle qu&#8217;un utilisateur peut passer par 13 niveaux de load-balancing !) ;</li>
<li>Comparer différentes versions du site, voir si la nouvelle version ne contient pas des liens cassés par exemple.</li>
</ul>
<p>Concernant l&#8217;avenir :</p>
<ul>
<li>L&#8217;équipe soit avoir de nouveaux uses cases : par ex. savoir où passe le robot Google, détecter les utilisations frauduleuses de CB, faire des ratio recherches / achats ;</li>
<li>Agrandir encore la plateforme, remettre à jour les machines ;</li>
<li>Avoir de l&#8217;analyse de logs à la demande, sans avoir à développer et déployer de nouveaux map / reduce. Utiliser Hive ? Cascading ?</li>
<li>Quel avenir pour les produits utilisés ? L&#8217;équipe souhaite contribuer à Flume. Quelques craintes également sur la versatilité d&#8217;Hadoop.</li>
</ul>
<p>Dernier détail : l&#8217;investissement s&#8217;est fait essentiellement au niveau des machines (~ 70K€).<br />
Le projet, quant à lui, est passé des premières discussions à la machine à café à la production en l&#8217;espace d&#8217;environ 7 à 8 mois.</p>
<p>Voilà un joli projet, qui montre une utilisation concrète d&#8217;Hadoop, MongoDB, Flume et Play! pour un traitement massif des logs.</p>
<a href="javascript:toggleStartStop();PicLensLite.start({feedUrl:'http://linsolas.free.fr/wordpress/wp-content/plugins/wp-piclens/mrss.php?id=226'});">Start Slide Show with PicLens Lite <img src="http://linsolas.free.fr/wordpress/wp-content/plugins/wp-piclens/PicLensButton.png" alt="PicLens" width="16" height="12" border="0" align="top"></a>]]></content:encoded>
			<wfw:commentRss>http://linsolas.free.fr/wordpress/index.php/2012/04/devoxx-deuxieme-jour/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Devoxx France &#8211; Premier jour</title>
		<link>http://linsolas.free.fr/wordpress/index.php/2012/04/devoxx-france-premier-jour/</link>
		<comments>http://linsolas.free.fr/wordpress/index.php/2012/04/devoxx-france-premier-jour/#comments</comments>
		<pubDate>Mon, 23 Apr 2012 21:45:41 +0000</pubDate>
		<dc:creator>Romain</dc:creator>
				<category><![CDATA[conférence]]></category>

		<guid isPermaLink="false">http://linsolas.free.fr/wordpress/?p=220</guid>
		<description><![CDATA[L&#8217;arrivée Ca y est. Après plusieurs mois de préparation et d&#8217;attente, la conférence Devoxx a enfin lieu ! Parlons de lieu justement. Devoxx France prend place à l&#8217;hôtel Mariott, dans le 14e arrondissement de Paris. Le lieu est donc plutôt bien choisi, et la conférence va s&#8217;étaler sur 2 niveaux : Au rez-de-chaussée, il y [...]]]></description>
			<content:encoded><![CDATA[<h3>L&#8217;arrivée</h3>
<p>Ca y est. Après plusieurs mois de préparation et d&#8217;attente, la conférence <strong>Devoxx</strong> a enfin lieu !<br />
Parlons de lieu justement. Devoxx France prend place à <a href="http://devoxx.fr/display/FR12/Lieu" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Lieu?referer=');">l&#8217;hôtel Mariott</a>, dans le 14e arrondissement de Paris.<br />
Le lieu est donc plutôt bien choisi, et la conférence va s&#8217;étaler sur 2 niveaux :</p>
<ul>
<li>Au rez-de-chaussée, il y a 3 salles (<em>Seine A</em>, <em>Seine B</em> et <em>Seine C</em>), qui seront réunies en une seule lors des keynotes. C&#8217;est également à ce niveau-là que sont regroupés tous les stands des sponsors : Valtech, Xebia, Zenexity, Ippon, Google, etc. Enfin, c&#8217;est ici qu&#8217;ont lieu les buffets. Parce que ça creuse tout ça !</li>
<li>Au niveau -1, 2 salles sont utilisées (<em>Ella Fitzgerald</em> et <em>Miles Davis</em> qui sera occasionnellement divisée en 3). Il y a aussi un open-space, très sympa pour les discussions un peu à l&#8217;écart, et une petite salle qui héberge 2 jours durant le <b>Code Story</b>.</li>
</ul>
<p>Bref, au niveau des lieux, c&#8217;était un sans faute, même si au moment du buffet du midi, on se marchait un peu dessus&#8230;<br />
On regrettera quelques petits soucis au niveau service, comme par exemple la manque de diversité au repas du midi (quelques salades, 2 ou 3 types de sandwiches, c&#8217;est tout), l&#8217;absence d&#8217;eau tout l&#8217;après-midi (c&#8217;est un peu abusé là je trouve), et des vestiaires qui ferment trop tôt (en particulier pour les gens qui ont des valises).<br />
Ok, on chipote&#8230;</p>
<p>A part ça, au niveau de l&#8217;organisation, et du staff, pour moi, c&#8217;est zéro faute. Toujours présents, très réactifs en cas de soucis, aucune queue pour récupérer son badge. Bref, un seul mot : <b>BRAVO</b>.</p>
<p>Voyons maintenant un peu les sessions du jour&#8230; programme qui sera assez léger en ce qui me concerne.<br />
Ce premier jour est destiné aux universités (des sessions techniques d&#8217;environ 3 heures), des démonstrations d&#8217;outils.<br />
Tout le monde n&#8217;est pas encore là (certains participants ne vennant que les 2 deniers jours), mais nous sommes déjà autour de 800 personnes. Pas mal du tout !!</p>
<p><span id="more-220"></span></p>
<hr/>
<h3><a href="http://devoxx.fr/display/FR12/Les+5+mercenaires+du+DevOps" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Les+5+mercenaires+du+DevOps?referer=');">Les 5 mercenaires du DevOps</a>, par <a href="http://devoxx.fr/display/FR12/Henri+Gomez" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Henri+Gomez?referer=');">Henri Gomez</a>, <a href="http://devoxx.fr/display/FR12/Arnaud+Heritier" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Arnaud+Heritier?referer=');">Arnaud Héritier</a>, <a href="http://devoxx.fr/display/FR12/Gildas+Cuisinier" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Gildas+Cuisinier?referer=');">Gildas Cuisinier</a>, <a href="http://devoxx.fr/display/FR12/Pierre-Antoine+Gregoire" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Pierre-Antoine+Gregoire?referer=');">Pierre-Antoine Grégoire</a>, <a href="http://devoxx.fr/display/FR12/Dimitri+Baeli" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Dimitri+Baeli?referer=');">Dimitri Baeli</a></h3>
<p>Il existe aujourd&#8217;hui dans beaucoup de sociétés un véritable mur entre les équipes de développement et les opérationnels, c&#8217;est-à-dire les &laquo;&nbsp;gardiens&nbsp;&raquo; de la production.<br />
Il arrive fréquemment que les livrables soient donnés aux opérationnels par les développeurs sans que ces derniers ne connaissent l&#8217;environnement de production.<br />
De même, les &laquo;&nbsp;Ops&nbsp;&raquo; ne connaissent que trop peu ce qu&#8217;ils vont mettre en production.<br />
Il en résulte généralement que lorsqu&#8217;un problème arrive en production, c&#8217;est à qui se débarrassera du problème, et surtout d&#8217;en nier la responsabilité (&laquo;&nbsp;<em>Ton livrable est pourri</em>&laquo;&nbsp;, &laquo;&nbsp;<em>Mais tu n&#8217;as pas respecté l&#8217;étape 42 de la page 37 du document de mise en production</em>&laquo;&nbsp;, etc.)!</p>
<p>Bref, nos 5 compères nous expliquent ce que sont les DevOps, mi-développeur mi-opérateur, et vont tenter de nous montrer ce que cela donne en live, grâce à une application qu&#8217;ils ont développé (une application de partage temporaire de fichiers).</p>
<p>Pour évaluer un peu leur audience, nos 5 mercenaires décident de faire les <b>12 tests de Joel</b> : Joel Spolsky a édicté un <a href="http://www.joelonsoftware.com/articles/fog0000000043.html" onclick="pageTracker._trackPageview('/outgoing/www.joelonsoftware.com/articles/fog0000000043.html?referer=');">test de 12 questions</a> pour évaluer la qualité de l&#8217;environnement de travail d&#8217;un développeur.<br />
Ces 12 questions, les voici :</p>
<ol>
<li>Disposez-vous d&#8217;un gestionnaire de source (type SVN, Git, etc.) ?</li>
<li>Pouvez-vous construire vos livrables en une seule étape ?</li>
<li>Construisez-vous l&#8217;application quotidiennement ?</li>
<li>Avez-vous un gestionnaire de défauts ?</li>
<li>Corrigez-vous les bugs de votre application avant d&#8217;écrire du nouveau code ?</li>
<li>Avez-vous un planning à jour ? Autrement dit, avez-vous une visibilité d&#8217;au moins 15 jours dans votre travail ?</li>
<li>Avez-vous des spécifications ?</li>
<li>Les développeurs sont-ils dans un environnement de travail calme ?</li>
<li>Disposez-vous des meilleurs outils, compte tenu de votre budget ?</li>
<li>Avez-vous des testeurs (autres que des développeurs) ?</li>
<li>Les candidats écivent-ils du code avant leur embauche ?</li>
<li>Faites-vous des tests d&#8217;utilisabilité ?</li>
</ol>
<p>Pour Joel, si vous avez une note inférieure à 10, alors vous avez un gros problème.<br />
Notez que ce test, toujours d&#8217;actualité, a été écrit en <b>2000</b> ! Ce test a donc 12 ans, mais hélas beaucoup de développeurs ne peuvent encore jouir d&#8217;un score parfait.<br />
D&#8217;ailleurs, nos 5 mercenaires demandent à l&#8217;audience de se lever, puis ils énumèrent ces règles, chaque participant devant se rassoir dès que l&#8217;une des règles n&#8217;est pas respectée dans son équipe. Au bout du test, seules 3 personnes finiront debout <img src='http://linsolas.free.fr/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ! C&#8217;est peu.</p>
<p>L&#8217;équipe a ensuite montré l&#8217;application qu&#8217;ils ont développée, en montrant les différentes étapes pour pouvoir la déployer (via différents jobs Maven dirigés par un serveur Jenkins). La suite de la conférence &#8211; que je n&#8217;ai pas vraiment pu suivre &#8211; a consisté à modifier en direct l&#8217;applications, puis de la déployer &laquo;&nbsp;en production&nbsp;&raquo;.</p>
<p>Une première session plutôt agréable donc, présentée par quelques personnalités&#8230;</p>
<hr/>
<h3><a href="http://devoxx.fr/display/FR12/Hackergarten+Paris" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Hackergarten+Paris?referer=');">Hackergarten</a></h3>
<p>Le principe du Hackergarten est assez simple : vous réunissez quelques geeks avec leur machine (généralement un Mac <img src='http://linsolas.free.fr/wordpress/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  ), ainsi qu&#8217;un commiteur (voire le créateur) d&#8217;une librairie ou d&#8217;un framework assez connu.<br />
Ensuite, vous commencez à travailler sur le projet, en corrigeant un petit bug par exemple, ou en ajoutant une nouvelle fonctionnalité.</p>
<p>Ici, nous avions du choix : nous pouvions travailler sur <a href="http://jenkins-ci.org/" onclick="pageTracker._trackPageview('/outgoing/jenkins-ci.org/?referer=');">Jenkins</a> (ou un de ses nombreux plugins), <a href="http://groovy.codehaus.org/" onclick="pageTracker._trackPageview('/outgoing/groovy.codehaus.org/?referer=');">Groovy</a>, <a href="https://github.com/FluentLenium/FluentLenium" onclick="pageTracker._trackPageview('/outgoing/github.com/FluentLenium/FluentLenium?referer=');">FluentLenium</a>, <a href="http://code.google.com/p/mockito/" onclick="pageTracker._trackPageview('/outgoing/code.google.com/p/mockito/?referer=');">Mockito</a>, etc. Plusieurs personnes étaient là pour nous aider : <a href="http://devoxx.fr/display/FR12/Arnaud+H%C3%A9ritier" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Arnaud+H_C3_A9ritier?referer=');">Arnaud Héritier</a>, <a href="http://devoxx.fr/display/FR12/Mathilde+Lemee" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Mathilde+Lemee?referer=');">Mathilde Lemée</a>, <a href="http://devoxx.fr/display/FR12/Brice+Dutheil" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Brice+Dutheil?referer=');">Brice Dutheil</a>, <a href="http://devoxx.fr/display/FR12/Guillaume+Laforge" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Guillaume+Laforge?referer=');">Guillaume Laforge</a>, etc.</p>
<p>C&#8217;est une expérience sympathique, mais je n&#8217;y étais sans doute pas très bien préparé, en particulier le fait de devoir télécharger pas mal de sources (et je ne parle pas des dépendances Maven <img src='http://linsolas.free.fr/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> ).<br />
Au final, je n&#8217;ai pas vraiment contribué à Jenkins, mais ce n&#8217;est sans doute que partie remise !</p>
<hr/>
<h3><a href="http://devoxx.fr/display/FR12/Chouchoutez+votre+code+JavaScript" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Chouchoutez+votre+code+JavaScript?referer=');">Chouchoutez votre code JavaScript</a> par <a href="http://devoxx.fr/display/FR12/Romain+Linsolas" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Romain+Linsolas?referer=');">moi-même</a></h3>
<p>Ma présentation, donc forcément une très bonne présentation, vous n&#8217;en doutez-pas <img src='http://linsolas.free.fr/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
Plus sérieusement, cette présentation a un but précis : montrer que l&#8217;on peut faire pour le JavaScript ce que l&#8217;on fait déjà pour son Java, à savoir le tester, l&#8217;analyser, l&#8217;intégrer. Et le tout, sans utiliser de nouveaux outils.</p>
<p>Vous pouvez retrouver pour cette présentation :</p>
<ul>
<li><a href="http://linsolas.free.fr/wordpress/index.php/2012/04/chouchoutez-votre-code-javascript">La retranscription sur mon blog</a></li>
<li><a href="http://www.slideshare.net/linsolas/devoxx-java-script1280720" onclick="pageTracker._trackPageview('/outgoing/www.slideshare.net/linsolas/devoxx-java-script1280720?referer=');">Les slides sur SlideShare</a></li>
<li><a href="https://github.com/linsolas/devoxx-chouchoutez-javascript" onclick="pageTracker._trackPageview('/outgoing/github.com/linsolas/devoxx-chouchoutez-javascript?referer=');">Les sources (mes backups) sur GitHub</a></li>
<li>La vidéo sur Parleys (à venir)</li>
</ul>
<hr/>
<p>Il restait encore une dernière série de présentations, un paquet de BOF (<em>Birds of a Feather</em>, c&#8217;est-à-dire un petit groupe de discussion informel sur un sujet précis) puis une soirée dédiée aux speakers, mais mon état de santé ne m&#8217;a hélas pas permis de rester.</p>
<a href="javascript:toggleStartStop();PicLensLite.start({feedUrl:'http://linsolas.free.fr/wordpress/wp-content/plugins/wp-piclens/mrss.php?id=220'});">Start Slide Show with PicLens Lite <img src="http://linsolas.free.fr/wordpress/wp-content/plugins/wp-piclens/PicLensButton.png" alt="PicLens" width="16" height="12" border="0" align="top"></a>]]></content:encoded>
			<wfw:commentRss>http://linsolas.free.fr/wordpress/index.php/2012/04/devoxx-france-premier-jour/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Chouchoutez votre code JavaScript</title>
		<link>http://linsolas.free.fr/wordpress/index.php/2012/04/chouchoutez-votre-code-javascript/</link>
		<comments>http://linsolas.free.fr/wordpress/index.php/2012/04/chouchoutez-votre-code-javascript/#comments</comments>
		<pubDate>Fri, 20 Apr 2012 21:14:18 +0000</pubDate>
		<dc:creator>Romain</dc:creator>
				<category><![CDATA[conférence]]></category>
		<category><![CDATA[continuous integration]]></category>
		<category><![CDATA[sonar]]></category>
		<category><![CDATA[tests]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://linsolas.free.fr/wordpress/?p=210</guid>
		<description><![CDATA[Voici la retranscription de ma session &#171;&#160;Chouchoutez votre code JavaScript&#171;&#160;, présentée lors de la première édition de Devoxx France, le mercredi 18 avril 2012. Le but de cette présentation est de montrer qu&#8217;il est aussi facile de tester et analyser son code JavaScript que son code Java. Les mêmes outils seront d&#8217;ailleurs utilisés, en particulier [...]]]></description>
			<content:encoded><![CDATA[<p>Voici la retranscription de ma session &laquo;&nbsp;<strong>Chouchoutez votre code JavaScript</strong>&laquo;&nbsp;, présentée lors de la première édition de Devoxx France, le mercredi 18 avril 2012.</p>
<p>Le but de cette présentation est de montrer qu&#8217;il est aussi facile de tester et analyser son code JavaScript que son code Java. Les mêmes outils seront d&#8217;ailleurs utilisés, en particulier Maven, Jenkins et Sonar.</p>
<p><span id="more-210"></span></p>
<p>Avant toute chose, nous allons prendre <a href="http://documentcloud.github.com/underscore/" onclick="pageTracker._trackPageview('/outgoing/documentcloud.github.com/underscore/?referer=');">underscore.js</a> comme cobaye pour nos tests. Pour information, il s&#8217;agit d&#8217;une librairie proposant une soixantaine de fonctions JS permettant de faire de la programmation fonctionnelle.</p>
<h2>Etape #1: Créer le projet</h2>
<p>Mon choix, pour la première librairie de tests, c&#8217;est <a href="http://pivotal.github.com/jasmine/" onclick="pageTracker._trackPageview('/outgoing/pivotal.github.com/jasmine/?referer=');">Jasmine</a>. Il s&#8217;agit d&#8217;une librairie avec une communauté assez active, et disposant d&#8217;un certain nombre de supports : Java et Maven, .Net, Ruby, Node.js, etc.<br />
Pour être plus précis, cette librairie va être surtout utilisée lorsque l&#8217;on souhaite faire du BDD (<em>Behavior Driven Development</em>). D&#8217;ailleurs, dans la terminologie de Jasmine, on ne parle pas de test, mais de <em>spec</em>.</p>
<p>Comme dit précédemment, <a href="http://searls.github.com/jasmine-maven-plugin/" onclick="pageTracker._trackPageview('/outgoing/searls.github.com/jasmine-maven-plugin/?referer=');">Jasmine offre un support Maven</a>. Pour ma présentation, j&#8217;opte pour la création d&#8217;un projet squelette, via un archetype Maven. Cela se fait via cette commande :</p>
<pre class="brush: plain;">mvn archetype:generate
    -DarchetypeRepository=http://searls-maven-repository.googlecode.com/svn/trunk/snapshots
    -DarchetypeGroupId=com.github.searls
    -DarchetypeArtifactId=jasmine-archetype
    -DarchetypeVersion=1.1.0.1-SNAPSHOT
    -DgroupId=fr.devoxx
    -DartifactId=chouchoutez-javascript
    -Dversion=0.0.1-SNAPSHOT</pre>
<p>Une fois ceci réalisé, nous obtenons un projet (que nous allons importer dans notre IDE préféré) ayant la structure suivante :</p>
<pre class="brush: plain;">
pom.xml
  ` src
     + main
     |  ` javascript
     |      ` quickstart.js
     ` test
        ` javascript
           ` quickstartTest.js
</pre>
<p>La partie intéressante dans le pom.xml est la déclaration du plugin Jasmine qui va permettre de lancer les tests via une commande Maven :</p>
<pre class="brush: xml;">
        &lt;plugins&gt;
            &lt;plugin&gt;
                &lt;groupId&gt;com.github.searls&lt;/groupId&gt;
                &lt;artifactId&gt;jasmine-maven-plugin&lt;/artifactId&gt;
                &lt;version&gt;1.0.1-beta-6&lt;/version&gt;
                &lt;executions&gt;
                    &lt;execution&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;generateManualRunner&lt;/goal&gt;
                            &lt;goal&gt;resources&lt;/goal&gt;
                            &lt;goal&gt;testResources&lt;/goal&gt;
                            &lt;goal&gt;test&lt;/goal&gt;
                            &lt;goal&gt;preparePackage&lt;/goal&gt;
                        &lt;/goals&gt;
                    &lt;/execution&gt;
                &lt;/executions&gt;
                &lt;configuration&gt;
                    &lt;jsSrcDir&gt;src/main/javascript&lt;/jsSrcDir&gt;
                    &lt;jsTestSrcDir&gt;src/test/javascript&lt;/jsTestSrcDir&gt;
                &lt;/configuration&gt;
            &lt;/plugin&gt;</pre>
<p>En lançant la commande <code>mvn test</code>, on voit que le test généré par défaut par l&#8217;archetype est lancé :</p>
<pre class="brush: plain;">-------------------------------------------------------
 J A S M I N E   T E S T S
-------------------------------------------------------
[INFO]
describe The quickstart object
  it adds two numbers
[INFO]
Results:

1 specs, 0 failures</pre>
<h2>Etape #2 : Ecrire des tests</h2>
<p>Je copie mon <code>underscore.js</code> dans le répertoire <code>src/main/javascript</code>, et nous allons le tester&#8230;<br />
Jasmine propose une écriture assez intuitive des tests, assez proche de <a href="http://code.google.com/p/fest/" onclick="pageTracker._trackPageview('/outgoing/code.google.com/p/fest/?referer=');">fest-assert</a>. En voici un premier exemple :</p>
<pre class="brush: jscript;">describe(&quot;Mon premier test&quot;, function() {
    it(&quot;should be 42&quot;, function() {
        var resultat = _.max([1, 2, 3, 42]);
        expect(resultat).toBe(42);
    };
};</pre>
<p>Avec Jasmine, on crée une suite de tests en utilisant le mot <code>describe</code>, suivi de son descriptif. Ensuite, on y ajoute une série de tests (voire on imbrique de nouvelles suites), chaque test (ou plus exactement chaque <em>spec</em>) étant défini par le mot clé <code>it</code>. On écrit le code du test, puis au moment de vérifier (i.e. de réaliser les <code>assert</code>), on va simplement utiliser <code>expect</code> suivi d&#8217;un matcher (ici <code>toBe</code>). <a href="https://github.com/pivotal/jasmine/wiki/Matchers" onclick="pageTracker._trackPageview('/outgoing/github.com/pivotal/jasmine/wiki/Matchers?referer=');">Plusieurs autres matchers existent</a> (<code>toEqual</code>, <code>toBeNull</code>, <code>toBeGreaterThan</code>, <code>toContain</code>, <code>toBeUndefined</code>).</p>
<p>A nouveau, je vérifie mes tests avec la commande Maven <code>mvn clean test</code>.</p>
<p>Voici mon fichier de tests final de la librairie underscore.js :</p>
<pre class="brush: jscript;">describe(&quot;Mon premier test&quot;, function() {

  it(&quot;should be 42&quot;, function() {
    var max = _.max([1, 2, 42]);
    expect(max).toBe(42);
  });

});

describe(&quot;Test d'underscore&quot;, function() {

    var myarray;

    beforeEach(function() {
        myarray = [1, 2, 3];
    });

    it(&quot;should return 42 when asked for last item&quot;, function() {
        var res = _.last([1,2,3,42]);
        expect(res).toBe(42);
    });

    it(&quot;be true&quot;, function() {
        var res = _.first([1, 2, 3]);
        expect(res == 1).toBeTruthy();
    });

    it(&quot;should be greater than 2&quot;, function() {
        expect(3).toBeGreaterThan(2);
    });

    it(&quot;should contains 2&quot;, function() {
        expect([1, 2, 3]).toContain(2);
    });

    it(&quot;should have size of 3&quot;, function() {
        expect(myarray.length).toBe(3);
    });

    it(&quot;should not be 1&quot;, function() {
        var res = _.max([1, 2]);
        expect(res).not.toBe(1);
    })

});

describe(&quot;test with spy&quot;, function() {

    it(&quot;should spy on last&quot;, function() {
        spyOn(_, 'last');
        var res = _.last([1, 2, 3]);
        expect(_.last).toHaveBeenCalled();
        expect(res).toBeUndefined();
    });

});</pre>
<p>Vous remarquerez qu&#8217;à l&#8217;instar d&#8217;un <code>@Before</code> de JUnit, Jasmine offre la même possibilité avec <code>beforeEach</code>.<br />
De plus, Jasmine offre aussi des <a href="https://github.com/pivotal/jasmine/wiki/Spies" onclick="pageTracker._trackPageview('/outgoing/github.com/pivotal/jasmine/wiki/Spies?referer=');">fonctionnalités d&#8217;espionnage</a>.</p>
<h2>Etape #3 : Analyser son code</h2>
<p>Pour analyser le code JavaScript, nous allons utiliser le merveilleux outil qu&#8217;est <a href="http://www.sonarsource.com/" onclick="pageTracker._trackPageview('/outgoing/www.sonarsource.com/?referer=');">Sonar</a> ! Il nous faut simplement y ajouter le plugin pour le support du langage JavaScript, qui <a href="http://docs.codehaus.org/display/SONAR/JavaScript+Plugin" onclick="pageTracker._trackPageview('/outgoing/docs.codehaus.org/display/SONAR/JavaScript+Plugin?referer=');">se trouve ici</a>.</p>
<p>Dans notre pom.xml, nous devons ajouter ces quelques lignes, pour spécifier que le projet est de langage JavaScript, et indiquer la localisation de nos sources (et celles des tests) :</p>
<pre class="brush: xml;">
    &lt;properties&gt;
        &lt;sonar.language&gt;js&lt;/sonar.language&gt;
        &lt;sonar.dynamicAnalysis&gt;reuseReports&lt;/sonar.dynamicAnalysis&gt;
    &lt;/properties&gt;

    &lt;build&gt;
        &lt;sourceDirectory&gt;src/main/javascript&lt;/sourceDirectory&gt;
        &lt;testSourceDirectory&gt;src/test/javascript&lt;/testSourceDirectory&gt;
</pre>
<p>Il suffit désormais de lancer la commande <code>mvn sonar:sonar</code> pour réaliser l&#8217;analyse complète, puis de se rendre sur son serveur Sonar pour en lire les résultats !</p>
<p>Tout n&#8217;est pas encore parfait, car nous ne disposons d&#8217;aucune information propres aux tests : pourcentage de réussite, taux de couverture du code, etc.</p>
<h2>Etape #4 : Analyse de la couverture</h2>
<p>Le plugin JavaScript pour Sonar sait lire les résultats des tests exécutés par <a href="http://code.google.com/p/js-test-driver/" onclick="pageTracker._trackPageview('/outgoing/code.google.com/p/js-test-driver/?referer=');">js-test-driver</a>, une autre librairie de tests JavaScript, plus orientée TDD (<em>Tests Driven Development</em>, ou Développement piloté par les tests). Cette librairie apporte une syntaxe très proche de JUnit, en particulier concernant les assertions. En voici un exemple :</p>
<pre class="brush: jscript;">GreeterTest = TestCase(&quot;GreeterTest&quot;);

GreeterTest.prototype.testGreet = function() {
    var greeter = new myapp.Greeter();
    assertEquals(&quot;Hello World!&quot;, greeter.greet(&quot;World&quot;));
};</pre>
<p>Bon. Mais il faut tout réécrire, et perdre ce que l&#8217;on a fait avec Jasmine du coup ? Heureusement non ! Il existe en effet <a href="https://github.com/ibolmo/jasmine-jstd-adapter" onclick="pageTracker._trackPageview('/outgoing/github.com/ibolmo/jasmine-jstd-adapter?referer=');">un adaptateur</a> pour exécuter des tests Jasmine <em>via</em> js-test-driver.<br />
Bien entendu, nous aurions pu partir dès le début avec la librairie js-test-driver, et oublier Jasmine, mais ça n&#8217;aurait pas été fun !</p>
<p>Donc pour faire marcher tout cela, il faut tout d&#8217;abord copier dans un répertoire <code>lib/</code> les fichiers suivants :</p>
<ul>
<li><code>jasmine.js</code> (auparavant, il était chargé <em>via</em> le plugin Maven, que nous n&#8217;allons plus utiliser.</li>
<li><code>JasmineAdapter.js</code>, le fameux adaptateur.</li>
</ul>
<p>Puis, je crée un fichier <code>jsTestDriver.conf</code> à la racine du projet qui contient la configuration pour js-test-driver :</p>
<pre class="brush: plain;">server: http://localhost:9876

load:
  - &quot;lib/jasmine.js&quot;
  - &quot;lib/JasmineAdapter.js&quot;
  - &quot;src/main/javascript/*.js&quot;
  - &quot;src/test/javascript/*.js&quot;</pre>
<p>Ici c&#8217;est très simple, on indique le port où tournera le serveur js-test-driver, ainsi que les librairies à charger&#8230;</p>
<p>Dernière étape : modifier le pom.xml. D&#8217;abord, y supprimer les références au plugin Jasmine, devenu obsolète. Ensuite, ajouter ceci pour la dépendance vers le plugin Maven de js-test-driver :</p>
<pre class="brush: xml;">    &lt;dependencies&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;com.googlecode.jstd-maven-plugin&lt;/groupId&gt;
            &lt;artifactId&gt;jstd-maven-plugin&lt;/artifactId&gt;
            &lt;version&gt;1.3.2.5&lt;/version&gt;
            &lt;scope&gt;test&lt;/scope&gt;
        &lt;/dependency&gt;
    &lt;/dependencies&gt;</pre>
<p>Puis je configure le plugin comme ceci :</p>
<pre class="brush: xml;">    &lt;build&gt;
        ...
        &lt;plugins&gt;
            &lt;plugin&gt;
                &lt;groupId&gt;com.googlecode.jstd-maven-plugin&lt;/groupId&gt;
                &lt;artifactId&gt;jstd-maven-plugin&lt;/artifactId&gt;
                &lt;configuration&gt;
                    &lt;port&gt;9876&lt;/port&gt;
                    &lt;browser&gt;/Applications/Firefox.app/Contents/MacOS/firefox-bin&lt;/browser&gt;
                    &lt;tests&gt;all&lt;/tests&gt;
                    &lt;config&gt;jsTestDriver.conf&lt;/config&gt;
                    &lt;testOutput&gt;target/jstestdriver&lt;/testOutput&gt;
                &lt;/configuration&gt;
                &lt;executions&gt;
                    &lt;execution&gt;
                        &lt;id&gt;run-tests&lt;/id&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;test&lt;/goal&gt;
                        &lt;/goals&gt;
                    &lt;/execution&gt;
                &lt;/executions&gt;
            &lt;/plugin&gt;</pre>
<p>On notera que certaines informations du fichier <code>jsTestDriver.conf</code> (comme le port du serveur) sont reprises ici. On spécifie aussi le chemin vers le navigateur utilisé par js-test-driver pour exécuter ses tests (chose inutile avec Jasmine, car ce dernier ne nécessite même pas de DOM pour exécuter les tests !).<br />
Dernier point : j&#8217;ajoute le repository où se trouve le plugin js-test-driver :</p>
<pre class="brush: xml;">  &lt;repositories&gt;
        &lt;repository&gt;
            &lt;id&gt;jstd-maven-plugin google code repo&lt;/id&gt;
            &lt;url&gt;http://jstd-maven-plugin.googlecode.com/svn/maven2&lt;/url&gt;
        &lt;/repository&gt;
  &lt;/repositories&gt;
  &lt;pluginRepositories&gt;
        &lt;pluginRepository&gt;
            &lt;id&gt;jstd-maven-plugin google code repo&lt;/id&gt;
            &lt;url&gt;http://jstd-maven-plugin.googlecode.com/svn/maven2&lt;/url&gt;
        &lt;/pluginRepository&gt;
  &lt;/pluginRepositories&gt;</pre>
<p>Maintenant, pour voir si tout s&#8217;est bien passé, je vérifie que l&#8217;exécution des tests se réalise bien. J&#8217;exécute donc de nouveau la commande Maven <code>mvn clean test</code> :</p>
<pre class="brush: plain;">-------------------------------------------
 J S  T E S T  D R I V E R
-------------------------------------------

Firefox: Runner reset.
..................
Total 18 tests (Passed: 18; Fails: 0; Errors: 0) (9,00 ms)
  Firefox 9.0.1 Mac OS: Run 18 tests (Passed: 18; Fails: 0; Errors 0) (9,00 ms)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------</pre>
<p>Bravo ! C&#8217;est presque gagné ! Il ne nous reste plus qu&#8217;à pouvoir mesurer la couverture des tests. Rien de plus simple à ce stade : il suffit d&#8217;éditer le fichier <code>jsTestDriver.conf</code> et d&#8217;y ajouter les 4 lignes suivantes :</p>
<pre class="brush: plain;">plugin:
  - name: &quot;coverage&quot;
    jar: &quot;lib/coverage-1.3.4.b.jar&quot;
    module: &quot;com.google.jstestdriver.coverage.CoverageModule&quot;</pre>
<p>Je relance <code>mvn clean package sonar:sonar</code>, et l&#8217;analyse contient désormais les résultats des tests, mais aussi la couverture du code !</p>
<h2>Etape #5 : Intégration continue</h2>
<p>Lors de la présentation, j&#8217;ai manqué de temps et ai dû passé cette étape. Mais ici, rien de magique ni d&#8217;extraordinaire. En effet, comme depuis le début j&#8217;utilise des commandes Maven, les faire jouer par un serveur d&#8217;intégration continue est d&#8217;une simplicité enfantine. Je vous laisse donc le soin de jouer avec <a href="http://jenkins-ci.org/" onclick="pageTracker._trackPageview('/outgoing/jenkins-ci.org/?referer=');">Jenkins</a> ou tout autre serveur&#8230;</p>
<h2>Conclusion</h2>
<p>J&#8217;ai montré en une demi-heure environ qu&#8217;il était très simple de tester son code JavaScript, de l&#8217;analyser. Les mêmes outils sont d&#8217;ailleurs mis en oeuvre que pour le langage Java : Maven, Sonar et Jenkins.</p>
<p>Bref, il ne reste plus qu&#8217;à s&#8217;y mettre <img src='http://linsolas.free.fr/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h2>Références</h2>
<ul>
<li><a href="https://github.com/linsolas/devoxx-chouchoutez-javascript" onclick="pageTracker._trackPageview('/outgoing/github.com/linsolas/devoxx-chouchoutez-javascript?referer=');">Projet sur GitHub</a></li>
<li><a href="http://www.slideshare.net/linsolas/devoxx-java-script1280720" onclick="pageTracker._trackPageview('/outgoing/www.slideshare.net/linsolas/devoxx-java-script1280720?referer=');">Slides sur Slideshare</a></li>
<li><a href="http://devoxx.fr/display/FR12/Chouchoutez+votre+code+JavaScript" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Chouchoutez+votre+code+JavaScript?referer=');">Abstract sur le site de DevoxxFR</a></li>
<li>Vidéo Parleys (à venir)</li>
</ul>
<a href="javascript:toggleStartStop();PicLensLite.start({feedUrl:'http://linsolas.free.fr/wordpress/wp-content/plugins/wp-piclens/mrss.php?id=210'});">Start Slide Show with PicLens Lite <img src="http://linsolas.free.fr/wordpress/wp-content/plugins/wp-piclens/PicLensButton.png" alt="PicLens" width="16" height="12" border="0" align="top"></a>]]></content:encoded>
			<wfw:commentRss>http://linsolas.free.fr/wordpress/index.php/2012/04/chouchoutez-votre-code-javascript/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Grand jeu concours Devoxx !</title>
		<link>http://linsolas.free.fr/wordpress/index.php/2012/03/grand-jeu-concours-devoxx/</link>
		<comments>http://linsolas.free.fr/wordpress/index.php/2012/03/grand-jeu-concours-devoxx/#comments</comments>
		<pubDate>Thu, 29 Mar 2012 17:26:38 +0000</pubDate>
		<dc:creator>Romain</dc:creator>
				<category><![CDATA[conférence]]></category>

		<guid isPermaLink="false">http://linsolas.free.fr/wordpress/?p=205</guid>
		<description><![CDATA[Devoxx arrive à grands pas, dans 3 semaines nous serons en plein dedans ! Il faut venir à cette conférence, orientée Java, web, mais pas que. Il y aura du beau, du très beau monde (la preuve, j&#8217;y vais). Mais voilà, tu n&#8217;as pas ta place, ta (ton) RH n&#8217;a rien compris (ils n&#8217;ont pas [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://devoxx.fr/display/FR12/Accueil" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Accueil?referer=');">Devoxx</a> arrive à grands pas, dans 3 semaines nous serons en plein dedans !</p>
<p><img src="http://devoxx.fr/download/attachments/5342010/Cadre-Devoxx-.png?version=1&#038;modificationDate=1320431903000" alt="Devoxx France 2012" /></p>
<p>Il <strong>faut</strong> venir à cette conférence, orientée Java, web, mais pas que. Il y aura du beau, du très beau monde (la preuve, j&#8217;y vais). Mais voilà, tu n&#8217;as pas ta place, ta (ton) RH n&#8217;a rien compris (ils n&#8217;ont pas Free ?) et ne veux pas t&#8217;envoyer là-bas ? Alors pourquoi ne pas essayer de <strong>gagner</strong> ton pass ?</p>
<p>Pour cela, tu as quatre concours qui n&#8217;attendent que toi :</p>
<ul>
<li>Si tu aimes faire du Java, que tu peux faire mieux que Twitter, alors <a href="http://blog.ippon.fr/2012/03/19/bienvenue-sur-le-tatami-ippon-lance-un-grand-concours-de-code-pour-devoxx-france/" onclick="pageTracker._trackPageview('/outgoing/blog.ippon.fr/2012/03/19/bienvenue-sur-le-tatami-ippon-lance-un-grand-concours-de-code-pour-devoxx-france/?referer=');">lance-toi sur le Tatami</a> ! Attention, la concurrence est déjà rude !</li>
<li>Tu préfères le code JavaScript, avec du Node.JS dedans ? Alors Romain (non, pas moi), <a href="http://www.web-tambouille.fr/2012/03/24/un-pass-3-jours-pour-devoxx-france-a-gagner-sur-web-tambouille-concours.html" onclick="pageTracker._trackPageview('/outgoing/www.web-tambouille.fr/2012/03/24/un-pass-3-jours-pour-devoxx-france-a-gagner-sur-web-tambouille-concours.html?referer=');">te lance un défi</a> !</li>
<li>Tu aimes les JUGs ? Va voir du côté de Nicolas de Loof, <a href="http://blog.loof.fr/2012/03/gagnez-une-place-pour-devoxx.html" onclick="pageTracker._trackPageview('/outgoing/blog.loof.fr/2012/03/gagnez-une-place-pour-devoxx.html?referer=');">là aussi un concours t&#8217;attend</a>&#8230;</li>
<li>Tu n&#8217;as pas le temps de coder ? Tant pis. Alors <a href="http://blog.aheritier.net/devoxx-france-2012-gagnez-votre-place/" onclick="pageTracker._trackPageview('/outgoing/blog.aheritier.net/devoxx-france-2012-gagnez-votre-place/?referer=');">il te restera la chance pour gagner un pass</a>.</li>
</ul>
<p>Bref, il te reste encore quelques jours pour espérer gagner un pass !</p>
<p>Et rendez-vous là-bas !</p>
<a href="javascript:toggleStartStop();PicLensLite.start({feedUrl:'http://linsolas.free.fr/wordpress/wp-content/plugins/wp-piclens/mrss.php?id=205'});">Start Slide Show with PicLens Lite <img src="http://linsolas.free.fr/wordpress/wp-content/plugins/wp-piclens/PicLensButton.png" alt="PicLens" width="16" height="12" border="0" align="top"></a>]]></content:encoded>
			<wfw:commentRss>http://linsolas.free.fr/wordpress/index.php/2012/03/grand-jeu-concours-devoxx/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Devoxx France</title>
		<link>http://linsolas.free.fr/wordpress/index.php/2012/02/devoxx-france/</link>
		<comments>http://linsolas.free.fr/wordpress/index.php/2012/02/devoxx-france/#comments</comments>
		<pubDate>Tue, 28 Feb 2012 23:06:29 +0000</pubDate>
		<dc:creator>Romain</dc:creator>
				<category><![CDATA[conférence]]></category>

		<guid isPermaLink="false">http://linsolas.free.fr/wordpress/?p=198</guid>
		<description><![CDATA[Dans moins de deux mois aura lieu THE conférence pour les geeks Java en France, Devoxx France ! Alors parlons-en un peu (des fois que vous ne seriez pas au courant, sait-on jamais) Mais alors, kézako ? Devoxx, plus anciennement JavaPolis, est une conférence indépendante vieille de 10 ans, qui se tient habituellement à la [...]]]></description>
			<content:encoded><![CDATA[<p>Dans moins de deux mois aura lieu THE conférence pour les geeks Java en France, <b>Devoxx France</b> !<br />
Alors parlons-en un peu (des fois que vous ne seriez pas au courant, sait-on jamais)</p>
<p><img src="http://www.touilleur-express.fr/wp-content/uploads/2012/01/tag_devoxx_fr_transparent.png" alt="Devoxx France" /></p>
<h2>Mais alors, kézako ?</h2>
<p><a href="http://fr.wikipedia.org/wiki/Devoxx" onclick="pageTracker._trackPageview('/outgoing/fr.wikipedia.org/wiki/Devoxx?referer=');">Devoxx</a>, plus anciennement JavaPolis, est une conférence indépendante vieille de 10 ans, qui se tient habituellement à la fin de chaque année à Anvers, en Belgique.<br />
Devoxx, c&#8217;est la plus grosse conférence européenne sur Java, la deuxième au monde après JavaOne (conférence &laquo;&nbsp;officielle&nbsp;&raquo; de Sun-Oracle).<br />
Pour vous donner une idée de ce que ça représente, voici quelques chiffres qui font tourner la tête concernant l&#8217;édition de 2011:</p>
<ul>
<li>5 jours de conférences, d&#8217;ateliers, de démos, d&#8217;échanges&#8230;</li>
<li>167 conférenciers,</li>
<li>plus de 3200 personnes !</li>
<li>sans aucun doute des hectolitres de bière (on est en Belgique quand même)</li>
</ul>
<p>Bref, Devoxx c&#8217;est un peu <b>le salon de l&#8217;automobile pour les développeurs Java</b> (mais sans les hôtesses <img src='http://linsolas.free.fr/wordpress/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  ).</p>
<p>L&#8217;une des annonces fracassante de l&#8217;édition 2011 a été l&#8217;arrivée de Devoxx France, fin avril 2012. Et c&#8217;est de ça dont je vais parler&#8230;</p>
<h2>De quoi ça va causer ?</h2>
<p>Le programme n&#8217;est pas encore finalisé (<a href="http://www.touilleur-express.fr/2012/02/28/ta-conf-na-pas-ete-retenue/" onclick="pageTracker._trackPageview('/outgoing/www.touilleur-express.fr/2012/02/28/ta-conf-na-pas-ete-retenue/?referer=');">l&#8217;équipe de sélection des sujets a énormément bossé là-dessus</a>) mais gross-modo, quatre thèmes seront abordés à Devoxx :</p>
<ul>
<li>Web, cloud et nosql</li>
<li>Langages alternatifs pour la JVM</li>
<li>Java, JavaSE et JavaEE</li>
<li>Entreprises et pratiques</li>
</ul>
<p>Bref, rends-toi sur <a href="http://www.devoxx.com/display/FR12/Agenda" onclick="pageTracker._trackPageview('/outgoing/www.devoxx.com/display/FR12/Agenda?referer=');">cette page</a>, et bientôt tu auras sous tes yeux le magnifique programme des 3 jours de la conférence&#8230;</p>
<h2>Et moi (moi, pas toi en fait) ?</h2>
<p>J&#8217;avais proposé deux sujets et j&#8217;ai eu l&#8217;immense honneur de les voir tous les deux sélectionnés ! Quand on sait qu&#8217;il y a eu près de <b>4 fois plus de soumissions</b> que de places disponibles, ça nous met tout de suite beaucoup de pression ! Il est vrai que je n&#8217;ai pas forcément proposé dans les catégories les plus concurrentielles. Bref, mes sujets sont les suivants :</p>
<ul>
<li><b><a href="http://devoxx.fr/display/FR12/Chouchoutez+votre+code+JavaScript" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Chouchoutez+votre+code+JavaScript?referer=');">Chouchoutez votre code JavaScript</a></b>, dans les <em>Tools in Action</em>. Le but sera ici de montrer que l&#8217;on peut apporter autant de soin à tester et analyser son code JavaScript qu&#8217;on ne le fait déjà avec son code Java.</li>
<li><b>TestNG, parce que vos tests le valent bien !</b>, parmi les <i>Quickies</i>, où j&#8217;exposerais les avantages d&#8217;utiliser cette librairie plutôt que JUnit.</li>
</ul>
<h2>Mais&#8230; mazette, ça coûte des sous !?</h2>
<p>Oui, c&#8217;est le prix de la liberté, de ne pas être sous le contrôle d&#8217;un grand nom de l&#8217;industrie&#8230; Il existe 3 tarifs :</p>
<ul>
<li>450€ les 3 jours</li>
<li>350€ les 2 derniers jours (les conférences)</li>
<li>150€ le premier jour (les universités)</li>
</ul>
<p>Ca peut paraitre cher (c&#8217;est pas négligeable si tu veux payer toi-même ta conférence), mais franchement, ce n&#8217;est pas du tout excessif. Il faut voir ce que cela va t&#8217;apporter : de nouvelles connaissances techniques, mais aussi humaines, de rencontrer tes idoles de toujours (<a href="http://devoxx.fr/display/FR12/Speakers" onclick="pageTracker._trackPageview('/outgoing/devoxx.fr/display/FR12/Speakers?referer=');">la liste des speakers</a> n&#8217;est pas encore terminée, mais il y a déjà du beau monde !). Compare cela avec une formation à 3000€ pour apprendre les bases de JSF, et tu auras compris où je veux en venir <img src='http://linsolas.free.fr/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
Avec un peu de chance, tu arriveras à négocier avec ton employer de prendre cela avec ton DIF !</p>
<p>Et comme dans les lessives Bonux, tu as le petit cadeau qui va bien : un abonnement d&#8217;une année au site <a href="http://www.parleys.com/" onclick="pageTracker._trackPageview('/outgoing/www.parleys.com/?referer=');">Parleys</a>, un site regorgeant de vidéos d&#8217;anciennes conférences (dont Devoxx), de JUG, etc. pour bien apprendre plein de choses merveilleuses !</p>
<p>Bref, vennez nombreux à Devoxx France !!<br />
En attendant, suivez <a href="https://twitter.com/#!/DevoxxFR" onclick="pageTracker._trackPageview('/outgoing/twitter.com/_/DevoxxFR?referer=');">DevoxxFR</a> sur Twitter !</p>
<p>Si tu veux en savoir plus, je te laisse avec <a href="http://www.touilleur-express.fr/category/devoxx-java/" onclick="pageTracker._trackPageview('/outgoing/www.touilleur-express.fr/category/devoxx-java/?referer=');">les nombreux sujets postés par Nicolas Martignole</a> &#8211; alias le Touilleur &#8211; qui est l&#8217;un des organisateurs de la conférence&#8230;</p>
<p><em>Affiche de Devoxx France du <a href="http://www.touilleur-express.fr" onclick="pageTracker._trackPageview('/outgoing/www.touilleur-express.fr?referer=');">Touilleur Express</a></em></p>
<a href="javascript:toggleStartStop();PicLensLite.start({feedUrl:'http://linsolas.free.fr/wordpress/wp-content/plugins/wp-piclens/mrss.php?id=198'});">Start Slide Show with PicLens Lite <img src="http://linsolas.free.fr/wordpress/wp-content/plugins/wp-piclens/PicLensButton.png" alt="PicLens" width="16" height="12" border="0" align="top"></a>]]></content:encoded>
			<wfw:commentRss>http://linsolas.free.fr/wordpress/index.php/2012/02/devoxx-france/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>LessCss et Eclipse</title>
		<link>http://linsolas.free.fr/wordpress/index.php/2012/01/lesscss-et-eclipse/</link>
		<comments>http://linsolas.free.fr/wordpress/index.php/2012/01/lesscss-et-eclipse/#comments</comments>
		<pubDate>Tue, 31 Jan 2012 22:58:36 +0000</pubDate>
		<dc:creator>Romain</dc:creator>
				<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://linsolas.free.fr/wordpress/?p=175</guid>
		<description><![CDATA[Less Css Il y a quelques temps, pour un besoin personnel, j&#8217;ai utilisé l&#8217;excellent Twitter bootstrap. J&#8217;y reviendrais sans doute dans un prochain post, mais succinctement, il s&#8217;agit d&#8217;un bootstrap CSS, c&#8217;est-à-dire tout le nécessaire pour partir avec quelque chose de solide lorsque l&#8217;on démarre un site ou une application web. Twitter bootstrap utilise (éventuellement) [...]]]></description>
			<content:encoded><![CDATA[<h2>Less Css</h2>
<p>Il y a quelques temps, pour un besoin personnel, j&#8217;ai utilisé l&#8217;excellent <a href="http://twitter.github.com/bootstrap/" onclick="pageTracker._trackPageview('/outgoing/twitter.github.com/bootstrap/?referer=');">Twitter bootstrap</a>. J&#8217;y reviendrais sans doute dans un prochain post, mais succinctement, il s&#8217;agit d&#8217;un <em>bootstrap</em> CSS, c&#8217;est-à-dire tout le nécessaire pour partir avec quelque chose de solide lorsque l&#8217;on démarre un site ou une application web.</p>
<p>Twitter bootstrap utilise (éventuellement) <a href="http://lesscss.org/" onclick="pageTracker._trackPageview('/outgoing/lesscss.org/?referer=');">less</a>. Je voulais faire un article à propos de less, mais Cédric Exbrayat <a href="http://hypedrivendev.wordpress.com/2012/01/31/css-sucks-do-less" onclick="pageTracker._trackPageview('/outgoing/hypedrivendev.wordpress.com/2012/01/31/css-sucks-do-less?referer=');">l&#8217;a fait avant moi sur son blog</a>. Il retrace parfaitement les principes de cette extension à CSS, je vous invite donc à le lire pour en savoir plus. Pour faire très court, <strong>less</strong> ajoute au CSS ce qui lui manque depuis toujours : le support de variables, de fonctions, d&#8217;imbrications de règles, etc. Le rêve pour tout développeur web qui se respecte !</p>
<p>Une question se pose alors : un fichier <code>.less</code> est un fichier <code>.css</code> enrichi. Mais quel est le niveau de support des IDE ? Regardons ça de plus près pour Eclipse (nous prendrons comme base la version 3.7).</p>
<p><span id="more-175"></span></p>
<h2>Support natif</h2>
<p>Premier test : ouvrons un fichier <code>.less</code>. Eclipse l&#8217;ouvre alors comme un fichier texte basique :</p>
<p><a href="http://linsolas.free.fr/wordpress/wp-content/uploads/less-ide-11.png"><img src="http://linsolas.free.fr/wordpress/wp-content/uploads/less-ide-11.png" alt="" title="Support LESS 1" width="564" height="460" class="aligncenter size-full wp-image-182" /></a></p>
<p>Configurons Eclipse pour qu&#8217;il assimile les fichiers <code>.less</code> à des fichiers <code>.css</code>. On va donc dans <em>Préférences &gt; General &gt; Editors &gt; File Associations</em>. On y ajoute l&#8217;extension <code>.less</code> et on lui associe l&#8217;éditeur CSS :</p>
<p><a href="http://linsolas.free.fr/wordpress/wp-content/uploads/less-ide-2.png"><img src="http://linsolas.free.fr/wordpress/wp-content/uploads/less-ide-2.png" alt="" title="less-ide-2" width="685" height="311" class="aligncenter size-full wp-image-183" /></a></p>
<p>De même, dans <em>Préférences &gt; General &gt; Content Types</em>, nous ajoutons l&#8217;extension <code>.less</code> au type CSS :</p>
<p><a href="http://linsolas.free.fr/wordpress/wp-content/uploads/less-ide-3.png"><img src="http://linsolas.free.fr/wordpress/wp-content/uploads/less-ide-3.png" alt="" title="less-ide-3" width="648" height="395" class="aligncenter size-full wp-image-184" /></a></p>
<p>On ouvre à nouveau le fichier <code>.less</code>, Eclipse le reconnait comme un fichier <code>.css</code> désormais :</p>
<p><a href="http://linsolas.free.fr/wordpress/wp-content/uploads/less-ide-4.png"><img src="http://linsolas.free.fr/wordpress/wp-content/uploads/less-ide-4.png" alt="" title="less-ide-4" width="453" height="515" class="aligncenter size-full wp-image-185" /></a></p>
<p>C&#8217;est déjà mieux, mais on ne bénéficie pas ici de la force de <strong>less</strong>. Il faut donc passer par un plugin.<br />
Avant toute chose, il est nécessaire d&#8217;installer l&#8217;extension <strong>Xtext</strong> sur Eclipse. Une simple recherche sur le Market place, et zou, c&#8217;est installé :</p>
<p><a href="http://linsolas.free.fr/wordpress/wp-content/uploads/less-ide-5.png"><img src="http://linsolas.free.fr/wordpress/wp-content/uploads/less-ide-5.png" alt="" title="less-ide-5" width="555" height="407" class="aligncenter size-full wp-image-186" /></a></p>
<h2>Eclipse plugin pour Less</h2>
<p>Le plugin <a href="http://www.normalesup.org/~simonet/soft/ow/eclipse-less.fr.html" onclick="pageTracker._trackPageview('/outgoing/www.normalesup.org/_simonet/soft/ow/eclipse-less.fr.html?referer=');">Eclipse plugin pour Less</a> est notre premier candidat. On va dans <em>Help &gt; Install New Software</em>, puis on ajoute un nouveau site de mise à jour :</p>
<p><code>http://www.normalesup.org/~simonet/soft/ow/update/</code></p>
<p>On installe le plugin. Avant toute chose, il faut penser à supprimer les modifications apportées précédemment (sinon les fichiers <code>.less</code> seront considérés comme de &laquo;&nbsp;simples&nbsp;&raquo; fichiers <code>.css</code>). L&#8217;éditeur fourni avec le plugin permet donc de supporter <strong>less</strong> :</p>
<p><a href="http://linsolas.free.fr/wordpress/wp-content/uploads/less-ide-6.png"><img src="http://linsolas.free.fr/wordpress/wp-content/uploads/less-ide-6.png" alt="" title="less-ide-6" width="420" height="254" class="aligncenter size-full wp-image-187" /></a></p>
<p>On le voit sur la capture précédente, l&#8217;auto-complétion fonctionne (la variable <code>@linkColor</code> a bien été reconnue). Toutefois, gros hic pour ce plugin, il ne supporte pas les références entre les fichiers (<strong>less</strong> permet en effet d&#8217;inclure des fichiers grâce à la commande <code>@import "mon-fichier.css</code>). Du coup, Twitter Bootstrap n&#8217;est pas utilisable en tant que tel avec ce plugin. En effet, ce <em>bootstrap</em> dispose d&#8217;un fichier pour les variables, d&#8217;un autre pour les mixins, d&#8217;un troisième pour les classes des tables, etc. Le plugin déclare alors forfait :</p>
<p><a href="http://linsolas.free.fr/wordpress/wp-content/uploads/less-ide-7.png"><img src="http://linsolas.free.fr/wordpress/wp-content/uploads/less-ide-7.png" alt="" title="less-ide-7" width="593" height="430" class="aligncenter size-full wp-image-188" /></a></p>
<p>C&#8217;est d&#8217;ailleurs expliqué sur le site :</p>
<blockquote><p>The following features are not supported in the editor:<br />
Refactoring,<br />
Cross-references between files.</p></blockquote>
<h2>Plugin LessCss</h2>
<p>Testons maintenant le plugin <a href="https://github.com/dslmeinte/LessCss" onclick="pageTracker._trackPageview('/outgoing/github.com/dslmeinte/LessCss?referer=');">LessCss</a>. Ici, pas encore de site de mise à jour. Il faudra donc passer par <a href="https://github.com/dslmeinte/LessCss/downloads" onclick="pageTracker._trackPageview('/outgoing/github.com/dslmeinte/LessCss/downloads?referer=');">la section de téléchargement du site</a>. Nous téléchargeons le ZIP, déposons les .JAR contenus dans le répertoire <code>dropin</code> ou <code>plugins</code> de notre Eclipse, et finissons par le redémarrer&#8230;</p>
<p>Ici aussi, le support des fichiers <code>.less</code> est opérationnel. Toutefois, à nouveau, ce plugin nous offre un support partiel. Comme on peut le voir sur la <a href="https://github.com/dslmeinte/LessCss" onclick="pageTracker._trackPageview('/outgoing/github.com/dslmeinte/LessCss?referer=');">Todo list</a> du plugin, il reste un certain nombre de fonctionnalités à implémenter, en particulier le support du <code>@import</code>. Dommage !</p>
<h2>Conclusion</h2>
<p>Ces premiers pas à la recherche d&#8217;un éditeur solide pour <strong>less</strong> ne s&#8217;avèrent guère concluants : un support natif se limitant au CSS pour Eclipse, et deux plugins loin d&#8217;être terminés. Bref, ce n&#8217;est pas encore ça, mais gageons que le support de <strong>less</strong> par Eclipse ira en s&#8217;améliorant, tant ce framework gagne des nouveaux adeptes !</p>
<p>N&#8217;hésitez pas à faire part de vos trouvailles, ou aussi de votre expérience avec votre propre IDE (NetBeans, IntelliJ, etc.) !</p>
<a href="javascript:toggleStartStop();PicLensLite.start({feedUrl:'http://linsolas.free.fr/wordpress/wp-content/plugins/wp-piclens/mrss.php?id=175'});">Start Slide Show with PicLens Lite <img src="http://linsolas.free.fr/wordpress/wp-content/plugins/wp-piclens/PicLensButton.png" alt="PicLens" width="16" height="12" border="0" align="top"></a>]]></content:encoded>
			<wfw:commentRss>http://linsolas.free.fr/wordpress/index.php/2012/01/lesscss-et-eclipse/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Jouons avec les Entités de Play!</title>
		<link>http://linsolas.free.fr/wordpress/index.php/2011/08/jouons-avec-les-entites-de-play/</link>
		<comments>http://linsolas.free.fr/wordpress/index.php/2011/08/jouons-avec-les-entites-de-play/#comments</comments>
		<pubDate>Thu, 04 Aug 2011 23:09:40 +0000</pubDate>
		<dc:creator>Romain</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[play]]></category>

		<guid isPermaLink="false">http://linsolas.free.fr/wordpress/?p=165</guid>
		<description><![CDATA[J&#8217;avais évoqué il y a quelques temps déjà Play!, et j&#8217;avais même traduit le tutoriel officiel en français montrant les capacités de ce framework. Ayant eu l&#8217;occasion de me remettre sur Play! ces derniers jours, je ne peux m&#8217;empêcher de vous faire partager le plaisir que j&#8217;ai eu à l&#8217;utiliser en vous parlant d&#8217;un aspect [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://linsolas.free.fr/wordpress/index.php/2010/01/jouons/">J&#8217;avais évoqué</a> il y a quelques temps déjà <a href="http://www.playframework.org/" onclick="pageTracker._trackPageview('/outgoing/www.playframework.org/?referer=');">Play!</a>, et j&#8217;avais même traduit le <a href="http://linsolas.developpez.com/articles/java/play/guide/" onclick="pageTracker._trackPageview('/outgoing/linsolas.developpez.com/articles/java/play/guide/?referer=');">tutoriel officiel en français</a> montrant les capacités de ce framework.</p>
<p>Ayant eu l&#8217;occasion de me remettre sur Play! ces derniers jours, je ne peux m&#8217;empêcher de vous faire partager le plaisir que j&#8217;ai eu à l&#8217;utiliser en vous parlant d&#8217;un aspect sympathique de ce framework : la gestion des entités.</p>
<p><span id="more-165"></span></p>
<p>Si vous avez déjà eu l&#8217;occasion de vous faire la main sur Play!, vous ne devriez rien apprendre ici. Il s&#8217;agit surtout de donner envie à ceux qui hésitent à se lancer dans l&#8217;aventure Play!.</p>
<h2>L&#8217;entité User</h2>
<p>Commençons par écrire notre entité, que nous appellerons <code>User</code>. Voici le code :</p>
<pre class="brush: java;">
package models;

import javax.persistence.Entity;
import play.db.jpa.Model;

@Entity
public class User extends Model {

    public String name;
    public String email;
    public boolean isAdmin;

    public User() {
    }

    public User(String name, String email, boolean isAdmin) {
        this.name = name;
        this.email = email;
        this.isAdmin = isAdmin;
    }

}
</pre>
<p>Nous notons déjà deux choses importantes :</p>
<ul>
<li>Les propriétés de notre entité sont publiques, et nous ne polluons plus notre classe avec des getters et setters (en attendant les <code>property</code> de Java 8 <img src='http://linsolas.free.fr/wordpress/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  ).</li>
<li>L&#8217;entité étend la classe <code>play.db.jpa.Model</code>. C&#8217;est ce point que nous allons voir en détail juste après.</li>
</ul>
<h2>La super-classe Model</h2>
<p>Cette super-classe <a href="http://www.playframework.org/documentation/api/1.2.2/play/db/jpa/Model.html" onclick="pageTracker._trackPageview('/outgoing/www.playframework.org/documentation/api/1.2.2/play/db/jpa/Model.html?referer=');">Model</a> (et ses parents) vont nous simplifier grandement la vie, car elle nous évitera l&#8217;écriture d&#8217;un DAO. En effet, nous disposons, simplement grâce à notre entité, des principales méthodes de CRUD (<i>Create, Read, Update, Delete</i>):</p>
<ul>
<li><code>count()</code> pour compter le nombre d&#8217;entités, en fournissant éventuellement des paramètres pour affiner la requête ;</li>
<li><code>save()</code> pour sauver notre entité ;</code></li>
</ul>
<p>Voyons quelques exemples basiques avec un test unitaire :</p>
<pre class="brush: java;">
public class UserTest extends UnitTest {

    @Before
    public void clean() {
        Fixtures.deleteDatabase();
    }

    @Test
    public void testAddition() {
        assertEquals(0, User.count());
        new User(&quot;romain linsolas&quot;, &quot;romain@example.com&quot;, true).save();
        assertEquals(1, User.count());
    }

}
</pre>
<p>On notera que nous nettoyons la base de données en mémoire avant chaque test, afin de ne pas fausser nos résultats. De plus, notre classe JUnit étendant la classe <code>play.test.UnitTest</code> afin de profiter de l'environnement de Play! : création de la base de données en mémoire et la structure des tables, par exemple.</p>
<pre class="brush: java;">
    private void insertUsers() {
        new User(&quot;romain linsolas&quot;, &quot;admin@example.com&quot;, true).save();
        new User(&quot;romain linsolas&quot;, &quot;romain@example.com&quot;, false).save();
        new User(&quot;bob l'eponge&quot;, &quot;bob.leponge@example.com&quot;, false).save();
        new User(&quot;romain gary&quot;, &quot;romain.gary@example.com&quot;, false).save();
    }

    @Test
    public void testFindAll() {
        insertUsers();
        assertEquals(4, User.findAll().size());
    }

    @Test
    public void testFindOneArg() {
        insertUsers();
        List&lt;User&gt; list = User.find(&quot;byName&quot;, &quot;romain linsolas&quot;).fetch();
        assertEquals(2, list.size());
        assertEquals(&quot;romain linsolas&quot;, list.get(0).name);
    }

    @Test
    public void testFindTwoArgs() {
        insertUsers();
        List&lt;User&gt; list = User.find(&quot;byNameAndIsAdmin&quot;, &quot;romain linsolas&quot;, true).fetch();
        assertEquals(1, list.size());
        assertTrue(list.get(0).isAdmin);
    }
</pre>
<p>Dans le code précédent, nous insérons quatre utilisateurs, et nous vérifions que la méthode <code>findAll()</code> nous retourne le nombre correct d'éléments. Nous faisons également une autre vérification, où nous recherchons tous les utilisateurs selon la valeur d'une propriété, ici <code>name</code>. Le dernier test permet de montrer une utilisation un peu plus poussée de la méthode <code>find("…")</code>, où nous cherchons tous les utilisateurs ayant un nom donné et dont l'attribut <code>isAdmin</code> vaut <code>true</code>.</p>
<p>Nous pouvons encore améliorer les choses en fournissant encore plus de détails sur la recherche, par exemple comme ceci :</p>
<pre class="brush: java;">
    @Test
    public void testFindAndOrder() {
        insertUsers();
        List&lt;User&gt; list = User.find(&quot;name = ? order by email desc&quot;, &quot;romain linsolas&quot;).fetch();
        assertEquals(2, list.size());
        assertFalse(list.get(0).isAdmin);
    }
</pre>
<p>où nous cherchons les utilisateurs selon un nom donné, puis en les triant selon l'adresse mail. Nous aurions pu encore corsé les choses en mettant en place des jointures avec d'autres entités...</p>
<p>Bien entendu, cette fonctionnalité ne marche pas seulement avec les méthodes de comptage ou de recherche, on pourra l'utiliser avec la méthode <code>delete()</code> :</p>
<pre class="brush: java;">
    @Test
    public void testDelete() {
        insertUsers();
        User.delete(&quot;name = ?&quot;, &quot;romain linsolas&quot;);
        assertEquals(2, User.count());
    }
</pre>
<p>Ce ne sont là que quelques possibilités, la classe <code>Model</code> offre d'autres fonctionnalités permettant les opérations de <i>CRUD</i>.</p>
<h2>Conclusion</h2>
<p>Au final, il n'y rien de révolutionnaire ici, mais que de temps gagné grâce à ces méthodes si utiles ! C'est sans doute ça la force première de Play! : nous offrir un retour rafraichissant à la <b>simplicité</b>. Et ça, c'est bon !</p>
<p>Pour aller plus loin :</p>
<ul>
<li><a href="http://www.playframework.org/" onclick="pageTracker._trackPageview('/outgoing/www.playframework.org/?referer=');">Site de Play!</a></li>
<li><a href="http://linsolas.developpez.com/articles/java/play/guide/" onclick="pageTracker._trackPageview('/outgoing/linsolas.developpez.com/articles/java/play/guide/?referer=');">Tutoriel que j'ai traduit en français sur Play!</a></li>
<li><a href="http://www.playframework.org/documentation/1.2.2/jpa" onclick="pageTracker._trackPageview('/outgoing/www.playframework.org/documentation/1.2.2/jpa?referer=');">Les entités JPA de Play!</a></li>
</ul>
<a href="javascript:toggleStartStop();PicLensLite.start({feedUrl:'http://linsolas.free.fr/wordpress/wp-content/plugins/wp-piclens/mrss.php?id=165'});">Start Slide Show with PicLens Lite <img src="http://linsolas.free.fr/wordpress/wp-content/plugins/wp-piclens/PicLensButton.png" alt="PicLens" width="16" height="12" border="0" align="top"></a>]]></content:encoded>
			<wfw:commentRss>http://linsolas.free.fr/wordpress/index.php/2011/08/jouons-avec-les-entites-de-play/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Calculer sa couverture de code par les tests d&#8217;intégration</title>
		<link>http://linsolas.free.fr/wordpress/index.php/2011/07/calculer-sa-couverture-de-code-par-les-tests-dintegration/</link>
		<comments>http://linsolas.free.fr/wordpress/index.php/2011/07/calculer-sa-couverture-de-code-par-les-tests-dintegration/#comments</comments>
		<pubDate>Fri, 08 Jul 2011 08:07:20 +0000</pubDate>
		<dc:creator>Romain</dc:creator>
				<category><![CDATA[article]]></category>
		<category><![CDATA[continuous integration]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[sonar]]></category>
		<category><![CDATA[tests]]></category>

		<guid isPermaLink="false">http://linsolas.free.fr/wordpress/?p=159</guid>
		<description><![CDATA[Nous allons voir ici comment, grâce à Sonar, Maven et JaCoCo nous pouvons obtenir la couverture de code par des tests d&#8217;intégration. Contexte Dans mon exemple, je me baserais sur les outils suivants : Sonar 2.8, Maven 2.2.1, Java 1.6. Au sein de l&#8217;un de mes projets, je dispose de quelques rares tests unitaires, qui [...]]]></description>
			<content:encoded><![CDATA[<p>Nous allons voir ici comment, grâce à Sonar, Maven et JaCoCo nous pouvons obtenir la couverture de code par des tests d&#8217;intégration.</p>
<p><span id="more-159"></span></p>
<h2>Contexte</h2>
<p>Dans mon exemple, je me baserais sur les outils suivants : <a href="http://www.sonarsource.org/" onclick="pageTracker._trackPageview('/outgoing/www.sonarsource.org/?referer=');">Sonar 2.8</a>, <a href="http://maven.apache.org" onclick="pageTracker._trackPageview('/outgoing/maven.apache.org?referer=');">Maven 2.2.1</a>, Java 1.6.</p>
<p>Au sein de l&#8217;un de mes projets, je dispose de quelques rares tests unitaires, qui couvre environ 7% de l&#8217;application. C&#8217;est peu. Très peu. Trop peu même.<br />
Mais nous avons également des tests d&#8217;intégration.<br />
En gros, ces tests d&#8217;intégration vont exécuter un jeu d&#8217;environ 300 fichiers d&#8217;entrée, qui seront ensuite analysés par mon application.</p>
<p>Mon but est donc de connaître, en plus de ma couverture de test par les tests JUnit, la couverture du code exécuté par mes tests d&#8217;intégration.</p>
<p>La structure de mon projet ressemble en gros à ceci :</p>
<pre class="brush: plain;">
mon-projet
  +- pom.xml (ce pom-là n'est qu'un pom d'aggrégation)
  +- parent
  |   +- pom.xml (c'est le vrai parent de tous les autres modules)
  +- module-1
  |   +- pom.xml
  +- module-2
  |   +- pom.xml
  +- ...
  +- module-tests
      +- pom.xml
      +- src/test/java/
          +- foo/bar/IntegrationTestsRunner.java
</pre>
<p><i>module-tests</i> est un module ne contenant que quelques classes de tests, en particulier <code>IntegrationTestsRunner.java</code> dont le but est d&#8217;aller lire mes fichiers de tests, et les exécuter.</p>
<p>Afin de ne pas lancer ces tests d&#8217;intégration à chaque build, nous définissons un profil Maven dans le <code>pom.xml</code> de <i>module-tests</i>, comme suit :</p>
<pre class="brush: xml;">
    &lt;profiles&gt;
        &lt;profile&gt;
            &lt;id&gt;run-it&lt;/id&gt;
            &lt;activation&gt;
                &lt;property&gt;
                    &lt;name&gt;runIT&lt;/name&gt;
                    &lt;value&gt;true&lt;/value&gt;
                &lt;/property&gt;
            &lt;/activation&gt;
            &lt;build&gt;
                &lt;plugins&gt;
                    &lt;plugin&gt;
                        &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
                        &lt;artifactId&gt;maven-surefire-plugin&lt;/artifactId&gt;
                        &lt;configuration&gt;
                            &lt;includes&gt;
                                &lt;include&gt;**/IntegrationTestRunner.java&lt;/include&gt;
                            &lt;/includes&gt;
                        &lt;/configuration&gt;
                    &lt;/plugin&gt;
                &lt;/plugins&gt;
            &lt;/build&gt;
        &lt;/profile&gt;
    &lt;/profiles&gt;
</pre>
<p>Ce profil sera activé soit en ajoutant <code>-DrunIT=true</code> soit <code>-Prun-it</code> dans la ligne de commande Maven.</p>
<p>Avec une méthode &laquo;&nbsp;traditionnelle&nbsp;&raquo;, c&#8217;est-à-dire l&#8217;exécution de tests unitaires via Surefire, aucune couverture de code ne sera détectée, car le code exécuté par les tests d&#8217;intégration l&#8217;est sur les autres modules du projet. Or Cobertura ne va instrumentaliser que les classes du module courant et non les dépendances (i.e. <i>module-1</i>, <i>module-2</i>, etc.).</p>
<h2>Mise en place de JaCoCo</h2>
<p>Pour résoudre mon problème, je vais faire appel à <a href="http://www.eclemma.org/jacoco/" onclick="pageTracker._trackPageview('/outgoing/www.eclemma.org/jacoco/?referer=');">JaCoCo</a>, un outil de couverture de test plus performant que Cobertura. Son principal avantage est de pouvoir instrumentaliser les classes au runtime. Dans mon cas présent, JaCoCo va donc pouvoir vérifier la couverture du code sur les différents modules au moment où l&#8217;on exécute <i>module-tests</i>.</p>
<p>Avant toute chose, il va nous falloir configurer un peu notre environnement :</p>
<ul>
<li>Installer le plugin <a href="http://docs.codehaus.org/display/SONAR/JaCoCo+Plugin" onclick="pageTracker._trackPageview('/outgoing/docs.codehaus.org/display/SONAR/JaCoCo+Plugin?referer=');">JaCoCo pour Sonar</a> (à copier dans le répertoire <i>extensions/plugins</i> de son installation Sonar).</li>
<li>Une fois Sonar redémarré, penser à ajouter dans le dashboard le widget <i>IT Coverage Widget</i> (il faudra sans doute pour cela être connecté en tant qu&#8217;administrateur).</li>
<li>Télécharger l&#8217;<a href="http://www.eclemma.org/jacoco/trunk/doc/agent.html" onclick="pageTracker._trackPageview('/outgoing/www.eclemma.org/jacoco/trunk/doc/agent.html?referer=');">agent JaCoCo</a>. Pour cela, il faut récupérer le ZIP de JaCoCo <a href="http://www.eclemma.org/jacoco/" onclick="pageTracker._trackPageview('/outgoing/www.eclemma.org/jacoco/?referer=');">ici</a>, l&#8217;agent se trouvant alors dans <i>lib/jacocoagent.jar</i>.</li>
</ul>
<p>Maintenant que ceci est en place, nous allons devoir indiquer à Surefire d&#8217;utiliser un agent Java spécifique (l&#8217;agent JaCoCo).<br />
Etant donné que nous n&#8217;avons besoin de cet agent qu&#8217;au moment de l&#8217;exécution des tests d&#8217;intégration, nous le définirons que pour le profil <code>run-it</code>.<br />
Au sein du <code>pom.xml</code> parent, j&#8217;ai donc ajouté :</p>
<pre class="brush: xml;">
    &lt;profiles&gt;
        &lt;!-- Profile used to run Integration Tests. In such case, we add the Java agent for JaCoCo... --&gt;
        &lt;profile&gt;
            &lt;id&gt;run-it&lt;/id&gt;
            &lt;activation&gt;
                &lt;property&gt;
                    &lt;name&gt;runIT&lt;/name&gt;
                    &lt;value&gt;true&lt;/value&gt;
                &lt;/property&gt;
            &lt;/activation&gt;
            &lt;build&gt;
                &lt;plugins&gt;
                    &lt;plugin&gt;
                        &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
                        &lt;artifactId&gt;maven-surefire-plugin&lt;/artifactId&gt;
                        &lt;configuration&gt;
                            &lt;argLine&gt;-javaagent:${jacoco.agent.path}=destfile=${jacoco.file.path}&lt;/argLine&gt;
                        &lt;/configuration&gt;
                    &lt;/plugin&gt;
                &lt;/plugins&gt;
            &lt;/build&gt;
        &lt;/profile&gt;
    &lt;/profiles&gt;
</pre>
<p>J&#8217;ai défini mon profil deux fois, dans le <code>pom.xml</code> parent et dans celui de <i>module-tests</i>. Nous aurions pu tout mettre dans le parent.</p>
<h2>Execution</h2>
<p>Nous allons avoir besoin d&#8217;exécuter maintenant deux commandes Maven :</p>
<ul>
<li>mvn clean install -DrunIT=true -Djacoco.agent.path=C:\dev\jacocoagent.jar -Djacoco.file.path=C:\dev\monprojet\jacoco.exec</li>
<li>mvn -Dsonar.jacoco.itReportPath=C:\dev\monprojet\jacoco.exec sonar:sonar</li>
</ul>
<p>La première ligne va activer le profil <i>run-it</i>, ce qui aura pour conséquence de lancer le tests d&#8217;intégration.<br />
On y définit les deux paramètres (<code>jacoco.agent.path</code> et <code>jacoco.file.path</code>) qui seront passés à Surefire pour définir un agent Java.</p>
<p>La seconde ligne va simplement exécuter l&#8217;analyse Sonar sur mon projet, mais en définissant le paramètre <code>sonar.jacoco.itReportPath</code> (généré lors de la première commande), cette analyse comprendra également la couverture des tests d&#8217;intégration.</p>
<p>Une fois les deux commandes exécutées, il suffit de se rendre sur son serveur Sonar pour apprécier cette nouvelle mesure de couverture de code !</p>
<p>Comme le montre <a href="http://www.sonarsource.org/measure-code-coverage-by-integration-tests-with-sonar/" onclick="pageTracker._trackPageview('/outgoing/www.sonarsource.org/measure-code-coverage-by-integration-tests-with-sonar/?referer=');">les captures d&#8217;écran sur le post du blog de Sonar à ce sujet</a>, il est possible, à l&#8217;instar de la couverture de code, de visualiser la couverture de code de tests d&#8217;intégration directement dans la fenêtre de visualisation du code source d&#8217;une classe.</p>
<p><img src="http://linsolas.free.fr/wordpress/wp-content/uploads/it-code-coverage.jpg"/></p>
<a href="javascript:toggleStartStop();PicLensLite.start({feedUrl:'http://linsolas.free.fr/wordpress/wp-content/plugins/wp-piclens/mrss.php?id=159'});">Start Slide Show with PicLens Lite <img src="http://linsolas.free.fr/wordpress/wp-content/plugins/wp-piclens/PicLensButton.png" alt="PicLens" width="16" height="12" border="0" align="top"></a>]]></content:encoded>
			<wfw:commentRss>http://linsolas.free.fr/wordpress/index.php/2011/07/calculer-sa-couverture-de-code-par-les-tests-dintegration/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>How to categorize JUnit tests with Maven</title>
		<link>http://linsolas.free.fr/wordpress/index.php/2011/02/howto-categorize-junit-tests-with-maven/</link>
		<comments>http://linsolas.free.fr/wordpress/index.php/2011/02/howto-categorize-junit-tests-with-maven/#comments</comments>
		<pubDate>Thu, 17 Feb 2011 12:24:35 +0000</pubDate>
		<dc:creator>Romain</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[tests]]></category>

		<guid isPermaLink="false">http://linsolas.free.fr/wordpress/?p=152</guid>
		<description><![CDATA[NB: This article is the english version of my previous article, written in french. For some reasons, I wanted to categorize my JUnit tests, in order to run only a subset of them. But this is not as simple as it seems&#8230; Context In one of my projects, I have many unit tests. It appears [...]]]></description>
			<content:encoded><![CDATA[<p><em>NB: This article is the english version of <a href="http://linsolas.free.fr/wordpress/index.php/2011/02/categoriser-ses-tests-junit-avec-maven/">my previous article</a>, written in french.</em></p>
<p>For some reasons, I wanted to categorize my JUnit tests, in order to run only a subset of them.<br />
But this is not as simple as it seems&#8230;</p>
<p><span id="more-152"></span></p>
<h2>Context</h2>
<p>In one of my projects, I have many unit tests. It appears that many of them are not <em>unit</em> at all.<br />
Some of them require a real Oracle connection, some others need to load a complex Spring context&#8230;</p>
<p>My goal is to split these tests into several categories.</p>
<p>To ease the explanations, I will only consider the two following categories: <code>@FastTest</code> and <code>@SlowTest</code>.</p>
<h2>Possible solutions</h2>
<p><a href="http://www.junit.org" onclick="pageTracker._trackPageview('/outgoing/www.junit.org?referer=');">JUnit</a> introduced recently, in version 4.8, the <code>@Category</code> annotation (see <a href="http://kentbeck.github.com/junit/doc/ReleaseNotes4.8.html" onclick="pageTracker._trackPageview('/outgoing/kentbeck.github.com/junit/doc/ReleaseNotes4.8.html?referer=');">the changelog</a> and also <a href="http://weblogs.java.net/blog/johnsmart/archive/2010/04/25/grouping-tests-using-junit-categories-0" onclick="pageTracker._trackPageview('/outgoing/weblogs.java.net/blog/johnsmart/archive/2010/04/25/grouping-tests-using-junit-categories-0?referer=');">an example here</a>).<br />
The principle is to annotate a class (or a method) with <code>@Category</code>, and then to define the category on which it belongs. For my needs, I could write:</p>
<pre class="brush: java;">
// Interfaces that define my test categories
public interface FastTest { }
public interface SlowTest { }

@Category(SlowTest.class)
public class ASlowTest {
    @Test
    public void foo() { ... }
}

@Category(FastTest.class)
public class ARealUnitTest {
    @Test
    public void foo() { ... }
}
</pre>
<p>This seems pretty good. But if we go into the details, in order to run all the tests that belong to a specific category, I have to write:</p>
<pre class="brush: java;">
@RunWith(Categories.class)
@IncludeCategory(FastTest.class)
@SuiteClasses( { ARealUnitTest.class, AnotherRealUnitTest.class })
public class FastTestsSuite { }
</pre>
<p>Here comes the problem: I have to create a <code>Suite</code> (using the annotation <code>@SuiteClasses</code>) to define the classes that should be executed.<br />
That means I have to maintain a list of all the tests for a given <code>Suite</code>. The omissions are therefore likely to be frequent&#8230;</p>
<h2>Not using JUnit Suite?</h2>
<p>How to solve this problem? Here are some ideas:</p>
<ul>
<li>Write the JUnit <code>Suite</code> manually as I just explained before, but I may forget to maintain them&#8230;</li>
<li>Let a Maven plugin creates the <code>Suite</code>. I wrote such a plugin some years ago, and I can reuse it now. However, I need to define when this plugin should be executed. Indeed, as the purpose of this plugin is to create or modify Java classes, I can&#8217;t run it automatically or anytime. Moreover, it is possible that some classes should not be included in these suites. So this solution will not be considered here.</li>
<li>Use specific patterns for the filenames of the test classes. For example, the fast tests will be named <code>**FastTest.java</code>, while the other ones will be named <code>**SlowTest.java</code>. Then, I will configure Maven, and some profiles, to use the correct pattern regarding which kind of tests category I want to run. I will not consider this solution neither, as this may also lead to errors.</li>
<li>Use <a href="http://testng.org" onclick="pageTracker._trackPageview('/outgoing/testng.org?referer=');">TestNG</a> instead of JUnit. TestNG is another test framework, which provides some advanced features. One of them is the definition of <code>groups</code> that would be perfect for our needs, especially since Surefire (the test plugin for Maven) <a href="http://maven.apache.org/plugins/maven-surefire-plugin/examples/testng.html" onclick="pageTracker._trackPageview('/outgoing/maven.apache.org/plugins/maven-surefire-plugin/examples/testng.html?referer=');">natively supports them</a>. This is maybe the best solution for our current concern, but I want to keep JUnit, so, again, I will ignore this idea.</li>
<li>Modify the Surefire plugin (or why not JUnit directly?) in order to manage the <code>@Category</code> without having to define a <code>Suite</code>. However, this is not a good idea to modify these libraries&#8230;</li>
</ul>
<p>So none of these ideas seems to be helpful&#8230;</p>
<h2>The last idea: Using JUnit Suite!</h2>
<p>The solution I will explain now is based on JUnit <code>Suite</code>. However, these suites will define <b>dynamically</b> the test classes that should be run.<br />
This <code>Suite</code> will look into the classpath for all the classes that are annotated with a particular annotation.</p>
<p>During <a href="http://stackoverflow.com/questions/2176570/how-to-run-all-tests-belonging-to-a-certain-category-in-junit-4" onclick="pageTracker._trackPageview('/outgoing/stackoverflow.com/questions/2176570/how-to-run-all-tests-belonging-to-a-certain-category-in-junit-4?referer=');">my searches</a>, I found a project called <a href="http://johanneslink.net/projects/cpsuite.jsp" onclick="pageTracker._trackPageview('/outgoing/johanneslink.net/projects/cpsuite.jsp?referer=');">classpathSuite</a>. One of the purpose of this project is to build a <code>Suite</code> by looking into the ClassPath for some specific classes. Exactly what I want to do!</p>
<p>Using this library, I write the following classes:</p>
<pre class="brush: java;">
@RunWith(Categories.class)
@Categories.IncludeCategory(FastTest.class)
@Suite.SuiteClasses( { AllTests.class })
public class FastTestsSuite {
}

@RunWith(ClasspathSuite.class)
public class AllTests {
}
</pre>
<p>and classpathSuite will find all the classes in the ClassPath that belong to the category <code>FastTest</code>.<br />
Nice! But this seems to work only when I run my tests in Eclipse, not in a Maven context <img src='http://linsolas.free.fr/wordpress/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' />  <a href="http://stackoverflow.com/questions/4970196/running-all-tests-from-a-category-using-maven" onclick="pageTracker._trackPageview('/outgoing/stackoverflow.com/questions/4970196/running-all-tests-from-a-category-using-maven?referer=');">Or did I miss something?</a></p>
<p>So I have to re-implement this feature, but that will work with Maven!</p>
<h2>The solution</h2>
<p>First step: I create two simple annotations, <code>@FastTest</code> and <code>@SlowTest</code>.<br />
They will be used to annotate my JUnit test classes. Note that my solution will only allow you to categorize an entire class, not a method. These annotations will be a replacement for <code>@Category(FastTest.class)</code> and <code>@Category(SlowTest.class)</code>.</p>
<p>Now, I create a utility class that will look into the classpath and find the list of classes that are annotated with a specific annotation (<code>@FastTest</code> or <code>@SlowTest</code> in my case) and that belong to a given package (this condition is not technically mandatory, it is just to limit the searches).</p>
<p>On the Java point of view, I get:</p>
<pre class="brush: java;">
public final class ClasspathClassesFinder {

    /**
     * Get the list of classes of a given package name, and that are annotated by a given annotation.
     *
     * @param packageName The package name of the classes.
     * @param testAnnotation The annotation the class should be annotated with.
     * @return The List of classes that matches the requirements.
     */
    public static Class&lt;?&gt;[] getSuiteClasses(String packageName, Class&lt;? extends Annotation&gt; testAnnotation) {
        try {
            return getClasses(packageName, testAnnotation);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Get the list of classes of a given package name, and that are annotated by a given annotation.
     *
     * @param packageName The package name of the classes.
     * @param annotation The annotation the class should be annotated with.
     * @return The List of classes that matches the requirements.
     * @throws ClassNotFoundException If something goes wrong...
     * @throws IOException If something goes wrong...
     */
    private static Class&lt;?&gt;[] getClasses(String packageName, Class&lt;? extends Annotation&gt; annotation) throws ClassNotFoundException, IOException {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        String path = packageName.replace('.', '/');
        // Get classpath
        Enumeration&lt;URL&gt; resources = classLoader.getResources(path);
        List&lt;File&gt; dirs = new ArrayList&lt;File&gt;();
        while (resources.hasMoreElements()) {
            URL resource = resources.nextElement();
            dirs.add(new File(resource.getFile()));
        }
        // For each classpath, get the classes.
        ArrayList&lt;Class&lt;?&gt;&gt; classes = new ArrayList&lt;Class&lt;?&gt;&gt;();
        for (File directory : dirs) {
            classes.addAll(findClasses(directory, packageName, annotation));
        }
        return classes.toArray(new Class[classes.size()]);
    }

    /**
     * Find classes, in a given directory (recursively), for a given package name, that are annotated by a given annotation.
     *
     * @param directory The directory where to look for.
     * @param packageName The package name of the classes.
     * @param annotation The annotation the class should be annotated with.
     * @return The List of classes that matches the requirements.
     * @throws ClassNotFoundException If something goes wrong...
     */
    private static List&lt;Class&lt;?&gt;&gt; findClasses(File directory, String packageName, Class&lt;? extends Annotation&gt; annotation)
            throws ClassNotFoundException {
        List&lt;Class&lt;?&gt;&gt; classes = new ArrayList&lt;Class&lt;?&gt;&gt;();
        if (!directory.exists()) {
            return classes;
        }
        File[] files = directory.listFiles();
        for (File file : files) {
            if (file.isDirectory()) {
                classes.addAll(findClasses(file, packageName + &quot;.&quot; + file.getName(), annotation));
            } else if (file.getName().endsWith(&quot;.class&quot;)) {
                // We remove the .class at the end of the filename to get the class name...
                Class&lt;?&gt; clazz = Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6));
                // Does the file is annotated with the given annotation?
                if (clazz.getAnnotation(annotation) != null) {
                    classes.add(clazz);
                }
            }
        }
        return classes;
    }
</pre>
<p>NB: I used the example given in <a href="http://snippets.dzone.com/posts/show/4831" onclick="pageTracker._trackPageview('/outgoing/snippets.dzone.com/posts/show/4831?referer=');">this post</a> to write this code.</p>
<p>Thus, the code <code>ClasspathClassesFinder.getSuiteClasses("my.company", FastTest.class)</code> will return an array of classes that belong to the package <code>my.company</code> and annotated with <code>@FastTest</code>.</p>
<p>The next step consists in building a <code>Suite</code> that will use my utility class to find all the fast tests:</p>
<pre class="brush: java;">
public class FastTestsSuite extends org.junit.runners.Suite {

    public FastTestsSuite(Class&lt;?&gt; clazz, RunnerBuilder builder) throws InitializationError {
        this(builder, clazz, ClasspathClassesFinder.getSuiteClasses(&quot;my.company&quot;, FastTest.class));
    }

    public FastTestsSuite(RunnerBuilder builder, Class&lt;?&gt; clazz, Class&lt;?&gt;[] suiteClasses) throws InitializationError {
        super(builder, clazz, suiteClasses);
    }

}
</pre>
<p>Last class to write: the entry point for the Maven Surefire plugin (this class will only run <code>@FastTest</code>, so I will have to write the same class for <code>@SlowTest</code>):</p>
<pre class="brush: java;">
@RunWith(FastTestsSuite.class)
public class RunAllFastTests {

}
</pre>
<p>Now, I just need to configure Maven in order to run &laquo;&nbsp;only&nbsp;&raquo; this test:</p>
<pre class="brush: xml;">
&lt;plugin&gt;
    &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
    &lt;artifactId&gt;maven-surefire-plugin&lt;/artifactId&gt;
    &lt;configuration&gt;
        &lt;!-- Run only tests annotated with @FastTest. --&gt;
        &lt;includes&gt;
            &lt;include&gt;**/RunAllFastTests.java&lt;/include&gt;
        &lt;/includes&gt;
        ...
    &lt;/configuration&gt;
&lt;/plugin&gt;
</pre>
<p>Please note that if you are working on a project with multi-modules (this is my case), you will have to define this <code>RunAllFastTests.java</code> in <em>each</em> module.</p>
<p>Regarding the slow tests, I just have to define a Maven profile that will launch the <code>RunAllSlowTests</code> class, which calls the Suite <code>SlowTestsSuite</code>. This Suite will use the utility class to find all classes annotated with <code>@SlowTest</code>. My continuous integration server <strike>Hudson</strike> Jenkins will activate this profile during the nightly-builds.</p>
<h2>Conclusion</h2>
<p>Finally, this solution is not really complex, and when the mechanism is developed, you just have to annotate your JUnit test class with the adequate annotation. This is simple.</p>
<p>However, I am quite disappointed that JUnit, a widely used test framework, does not provide such a mechanism natively. I hope that it will change in the near future&#8230;</p>
<p>Feel free to post your comments if you think that my solution is not the best one to solve this kind of problem.</p>
<h2>Sources</h2>
<p><a href="http://twitter.com/jpbriend" onclick="pageTracker._trackPageview('/outgoing/twitter.com/jpbriend?referer=');">Jean-Philippe Briend</a> suggested me on Twitter to provide the sources of the classes. Here they are:</p>
<p><a href="http://linsolas.free.fr/wordpress/wp-content/uploads/maven-junit-categories.zip"><img src="http://linsolas.free.fr/wordpress/wp-content/uploads/icon_zip.png"/>ZIP</a></p>
<p>This project requires Maven 2 or 3, Java 1.6 and JUnit 4.8.1.</p>
<p>In addition to all the classes required for the mechanism, this project contains three basic unit tests:</p>
<ul>
<li><code>OneFastTest</code>, annotated with <code>@FastTest</code> ;</li>
<li><code>OneSlowTest</code>, annotated with <code>@SlowTest</code> ;</li>
<li><code>TestWithoutAnnotation</code>, without any annotation. As this test should not be executed, it contains a method that will call the JUnit <code>fail()</code> method. Thus, if this class is executed, the test will fail.</li>
</ul>
<p>If you run the command <code>mvn clean install</code>, only the class annotated with <code>@FastTest</code> will be executed.<br />
If you run the command <code>mvn clean install -Djenkins=true</code> (or <code>-Pjenkins</code>), both annotated classes will be executed.</p>
<a href="javascript:toggleStartStop();PicLensLite.start({feedUrl:'http://linsolas.free.fr/wordpress/wp-content/plugins/wp-piclens/mrss.php?id=152'});">Start Slide Show with PicLens Lite <img src="http://linsolas.free.fr/wordpress/wp-content/plugins/wp-piclens/PicLensButton.png" alt="PicLens" width="16" height="12" border="0" align="top"></a>]]></content:encoded>
			<wfw:commentRss>http://linsolas.free.fr/wordpress/index.php/2011/02/howto-categorize-junit-tests-with-maven/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Catégoriser ses tests JUnit avec Maven</title>
		<link>http://linsolas.free.fr/wordpress/index.php/2011/02/categoriser-ses-tests-junit-avec-maven/</link>
		<comments>http://linsolas.free.fr/wordpress/index.php/2011/02/categoriser-ses-tests-junit-avec-maven/#comments</comments>
		<pubDate>Wed, 16 Feb 2011 15:37:54 +0000</pubDate>
		<dc:creator>Romain</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[tests]]></category>

		<guid isPermaLink="false">http://linsolas.free.fr/wordpress/?p=139</guid>
		<description><![CDATA[J&#8217;ai eu envie de &#171;&#160;catégoriser&#160;&#187; mes tests JUnit, et de pouvoir ne lancer que certains d&#8217;entre eux via Maven. Ce qui semblait une tâche relativement simple s&#8217;est avérée être en réalité un chemin semé d&#8217;embuches&#8230; Voici mon carnet de voyage&#8230; Le contexte Dans l&#8217;un de mes projets, je dispose d&#8217;une grande quantité de tests unitaires. [...]]]></description>
			<content:encoded><![CDATA[<p>J&#8217;ai eu envie de &laquo;&nbsp;catégoriser&nbsp;&raquo; mes tests JUnit, et de pouvoir ne lancer que certains d&#8217;entre eux via Maven.<br />
Ce qui semblait une tâche relativement simple s&#8217;est avérée être en réalité un chemin semé d&#8217;embuches&#8230;</p>
<p>Voici mon carnet de voyage&#8230;</p>
<p><span id="more-139"></span></p>
<h2>Le contexte</h2>
<p>Dans l&#8217;un de mes projets, je dispose d&#8217;une grande quantité de tests <em>unitaires</em>.<br />
En réalité, parmi ceux-ci, beaucoup d&#8217;entre eux ne sont pas unitaires du tout. Ils nécessitent parfois un accès à la base Oracle, parfois un contexte Spring plutôt lourd à charger, etc. Bref, ce ne sont pas là de bons tests unitaires, lancés en isolation.</p>
<p>Le but est donc de pouvoir séparer les tests en diverses catégories.</p>
<p>Afin de simplifier les choses, je ne considèrerais que deux catégories ici : <code>@FastTest</code> et <code>@SlowTest</code>.</p>
<h2>Solutions envisagées</h2>
<p><a href="http://www.junit.org" onclick="pageTracker._trackPageview('/outgoing/www.junit.org?referer=');">JUnit</a> a introduit dans la version 4.8 les <code>@Category</code> (voir <a href="http://kentbeck.github.com/junit/doc/ReleaseNotes4.8.html" onclick="pageTracker._trackPageview('/outgoing/kentbeck.github.com/junit/doc/ReleaseNotes4.8.html?referer=');">le changelog</a> et <a href="http://weblogs.java.net/blog/johnsmart/archive/2010/04/25/grouping-tests-using-junit-categories-0" onclick="pageTracker._trackPageview('/outgoing/weblogs.java.net/blog/johnsmart/archive/2010/04/25/grouping-tests-using-junit-categories-0?referer=');">un exemple</a>).<br />
Le principe est d&#8217;annoter une classe (ou une méthode) avec <code>@Category</code>, et de définir à quelle catégorie ce(s) test(s) appartient(-nent). Pour notre besoin, nous pourrions donc écrire :</p>
<pre class="brush: java;">
// Interfaces pour catégoriser les tests...
public interface FastTest { }
public interface SlowTest { }

@Category(SlowTest.class)
public class ASlowTest {
    @Test
    public void foo() { ... }
}

@Category(FastTest.class)
public class ARealUnitTest {
    @Test
    public void foo() { ... }
}
</pre>
<p>Bref, ça s&#8217;annonce plutôt bien. Mais si l&#8217;on regarde dans le détail, pour pouvoir lancer tous les tests d&#8217;une catégorie spécifique, il faut faire :</p>
<pre class="brush: java;">
@RunWith(Categories.class)
@IncludeCategory(FastTest.class)
@SuiteClasses( { ARealUnitTest.class, AnotherRealUnitTest.class })
public class FastTestsSuite { }
</pre>
<p>Et c&#8217;est là notre souci : il faut créer une <code>Suite</code> (via l&#8217;annotation <code>@SuiteClasses</code>) afin de définir les classes devant être exécutées. Cela nous oblige donc à maintenir une liste exhaustive des tests à lancer pour une suite donnée. Les oublis risquent donc d’être fréquents&#8230;</p>
<h2>Se passer des Suite JUnit</h2>
<p>Comment pallier ce problème de <code>Suite</code> ? Rapidement, quelques idées me viennent :</p>
<ul>
<li>Ecrire des <code>Suite</code> manuellement comme on vient de le dire, mais avec le risque d&#8217;en oublier.</li>
<li>Ecrire des <code>Suite</code> via un plugin Maven. J&#8217;en avais écrit un dans ce but il y a environ 2 ans et je pourrais m&#8217;en resservir. Mais la question est de savoir à quel moment il doit être lancé. Etant donné que mon plugin écrit ou modifie des classes de tests, on ne peut pas l&#8217;exécuter automatiquement ni n&#8217;importe quand. De plus, il se peut que certaines classes ne doivent pas être ajoutées dans ces suites, donc on ne peut pas considérer cette solution comme viable.</li>
<li>Se baser sur des nommages spécifiques pour les classes de test. Par exemple tous les tests <em>vraiment</em> unitaires portent le nom de <code>***FastTest.java</code>, les autres étant nommés <code>***SlowTest.java</code>. Maven, et ses profiles, se chargeant ensuite de choisir quel pattern donné à Surefire. Bien qu’il s&#8217;agisse d&#8217;une idée intéressante, je ne suis que moyennement pour, car on risque d&#8217;avoir là aussi des oublis ou des erreurs.</li>
<li>Utiliser <a href="http://testng.org" onclick="pageTracker._trackPageview('/outgoing/testng.org?referer=');">TestNG</a>, un autre framework de tests, proposant plus de fonctionnalités que JUnit. En particulier, TestNG permet de créer des groupes sur les tests, ce qui correspond à nos <code>@Category</code> de JUnit, mais qui marchent mieux. Le plugin Maven de tests &#8211; Surefire &#8211; <a href="http://maven.apache.org/plugins/maven-surefire-plugin/examples/testng.html" onclick="pageTracker._trackPageview('/outgoing/maven.apache.org/plugins/maven-surefire-plugin/examples/testng.html?referer=');">gère nativement le support des groupes</a>. C&#8217;est très simple, il suffit de définir une propriété dans la configuration Maven du plugin Surefire ! Mais dans mon cas, je souhaite rester sur du JUnit, bien que cette solution soit sans doute la plus élégante&#8230;</li>
<li>Modifier le plugin surefire de Maven pour gérer les <code>@Category</code> de JUnit. Ne rigolez pas, j’ai essayé de le faire <img src='http://linsolas.free.fr/wordpress/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  Mais modifier un plugin du coeur de Maven n’est forcément pas une bonne idée !</li>
</ul>
<p>Sur ces cinq solutions, j&#8217;ai donc opté pour pour la sixième !</p>
<h2>La sixième solution : Ne pas se passer des Suite !</h2>
<p>L&#8217;idée consiste à utiliser des <code>Suite</code> de JUnit, mais que celles-ci soit générées dynamiquement.</p>
<p>Cette <code>Suite</code> va aller chercher dans le classpath les classes de tests annotées avec une annotation particulière.</p>
<p>Lors de mes <a href="http://stackoverflow.com/questions/2176570/how-to-run-all-tests-belonging-to-a-certain-category-in-junit-4" onclick="pageTracker._trackPageview('/outgoing/stackoverflow.com/questions/2176570/how-to-run-all-tests-belonging-to-a-certain-category-in-junit-4?referer=');">recherches</a>, je suis tombé sur le projet <a href="http://johanneslink.net/projects/cpsuite.jsp" onclick="pageTracker._trackPageview('/outgoing/johanneslink.net/projects/cpsuite.jsp?referer=');">classpathSuite</a>. L&#8217;un des intérêts de ce projet est de pouvoir construire une <code>Suite</code> en cherchant des classes présentes dans le ClassPath.</p>
<p>Ainsi il suffit d&#8217;écrire :</p>
<pre class="brush: java;">
@RunWith(Categories.class)
@Categories.IncludeCategory(FastTest.class)
@Suite.SuiteClasses( { AllTests.class })
public class FastTestsSuite {
}

@RunWith(ClasspathSuite.class)
public class AllTests {
}
</pre>
<p>pour que classpathSuite cherche toutes les classes présentes dans le ClassPath appartenant à la catégorie <code>FastTest</code>.<br />
Magique. Sauf que si ça marche très bien avec Eclipse, cela ne fonctionne pas lorsque les tests sont lancés par Maven.</p>
<p><a href="http://stackoverflow.com/questions/4970196/running-all-tests-from-a-category-using-maven" onclick="pageTracker._trackPageview('/outgoing/stackoverflow.com/questions/4970196/running-all-tests-from-a-category-using-maven?referer=');">Ou alors j&#8217;ai raté quelque chose !</a></p>
<p>Donc il faut refaire quelque chose de proche, mais qui marche avec Maven !</p>
<h2>La solution</h2>
<p>Première étape, je créé deux annotations simples : <code>@FastTest</code> et <code>@SlowTest</code>.<br />
Ces annotations vont être utilisées pour annoter des classes de tests unitaires (dans cette solution, nous n&#8217;annoterons que les classes, et pas les méthodes). Grosso-modo ça remplacera les annotations <code>@Category(FastTest.class)</code> et <code>@Category(SlowTest.class)</code>.</p>
<p>Ensuite, je crée une classe utilitaire qui va chercher dans tout le classpath les classes étant annotées par une annotation donnée (donc essentiellement <code>@FastTest</code> ou <code>@SlowTest</code>) et qui appartiennent à un package donné (ou un package fils).</p>
<p>Cela nous donne :</p>
<pre class="brush: java;">
public final class ClasspathClassesFinder {

    /**
     * Get the list of classes of a given package name, and that are annotated by a given annotation.
     *
     * @param packageName The package name of the classes.
     * @param testAnnotation The annotation the class should be annotated with.
     * @return The List of classes that matches the requirements.
     */
    public static Class&lt;?&gt;[] getSuiteClasses(String packageName, Class&lt;? extends Annotation&gt; testAnnotation) {
        try {
            return getClasses(packageName, testAnnotation);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Get the list of classes of a given package name, and that are annotated by a given annotation.
     *
     * @param packageName The package name of the classes.
     * @param annotation The annotation the class should be annotated with.
     * @return The List of classes that matches the requirements.
     * @throws ClassNotFoundException If something goes wrong...
     * @throws IOException If something goes wrong...
     */
    private static Class&lt;?&gt;[] getClasses(String packageName, Class&lt;? extends Annotation&gt; annotation) throws ClassNotFoundException, IOException {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        String path = packageName.replace('.', '/');
        // Get classpath
        Enumeration&lt;URL&gt; resources = classLoader.getResources(path);
        List&lt;File&gt; dirs = new ArrayList&lt;File&gt;();
        while (resources.hasMoreElements()) {
            URL resource = resources.nextElement();
            dirs.add(new File(resource.getFile()));
        }
        // For each classpath, get the classes.
        ArrayList&lt;Class&lt;?&gt;&gt; classes = new ArrayList&lt;Class&lt;?&gt;&gt;();
        for (File directory : dirs) {
            classes.addAll(findClasses(directory, packageName, annotation));
        }
        return classes.toArray(new Class[classes.size()]);
    }

    /**
     * Find classes, in a given directory (recurively), for a given package name, that are annotated by a given annotation.
     *
     * @param directory The directory where to look for.
     * @param packageName The package name of the classes.
     * @param annotation The annotation the class should be annotated with.
     * @return The List of classes that matches the requirements.
     * @throws ClassNotFoundException If something goes wrong...
     */
    private static List&lt;Class&lt;?&gt;&gt; findClasses(File directory, String packageName, Class&lt;? extends Annotation&gt; annotation)
            throws ClassNotFoundException {
        List&lt;Class&lt;?&gt;&gt; classes = new ArrayList&lt;Class&lt;?&gt;&gt;();
        if (!directory.exists()) {
            return classes;
        }
        File[] files = directory.listFiles();
        for (File file : files) {
            if (file.isDirectory()) {
                classes.addAll(findClasses(file, packageName + &quot;.&quot; + file.getName(), annotation));
            } else if (file.getName().endsWith(&quot;.class&quot;)) {
                // We remove the .class at the end of the filename to get the class name...
                Class&lt;?&gt; clazz = Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6));
                // Does the file is annotated with the given annotation?
                if (clazz.getAnnotation(annotation) != null) {
                    classes.add(clazz);
                }
            }
        }
        return classes;
    }
</pre>
<p>NB: Je me suis inspiré de <a href="http://snippets.dzone.com/posts/show/4831" onclick="pageTracker._trackPageview('/outgoing/snippets.dzone.com/posts/show/4831?referer=');">ce post</a> pour ce code, mais adapté à mes besoins.<br />
Je n&#8217;ai pas regardé en détail, mais il est possible que <a href="http://code.google.com/p/reflections/" onclick="pageTracker._trackPageview('/outgoing/code.google.com/p/reflections/?referer=');">le projet Reflections</a> puisse faciliter l&#8217;écriture d&#8217;une telle classe, mais bon&#8230;</p>
<p>Ainsi, le code <code>ClasspathClassesFinder.getSuiteClasses("my.company", FastTest.class)</code> va me retourner un tableau de classes ayant comme package ancêtre <code>my.company</code> et annotées par <code>@FastTest</code>.</p>
<p>Je construit maintenant une <code>Suite</code> qui va utiliser cette précédente classe utilitaire pour me trouver les tests rapides :</p>
<pre class="brush: java;">
public class FastTestsSuite extends org.junit.runners.Suite {

    public FastTestsSuite(Class&lt;?&gt; clazz, RunnerBuilder builder) throws InitializationError {
        this(builder, clazz, ClasspathClassesFinder.getSuiteClasses(&quot;my.company&quot;, FastTest.class));
    }

    public FastTestsSuite(RunnerBuilder builder, Class&lt;?&gt; clazz, Class&lt;?&gt;[] suiteClasses) throws InitializationError {
        super(builder, clazz, suiteClasses);
    }

}
</pre>
<p>Dernier élément, le point d&#8217;entrée de mes tests pour le plugin Maven Surefire :</p>
<pre class="brush: java;">
@RunWith(FastTestsSuite.class)
public class RunAllFastTests {

}
</pre>
<p>Il ne me reste plus qu&#8217;à indiquer à Maven de ne prendre &laquo;&nbsp;que&nbsp;&raquo; ce test là :</p>
<pre class="brush: xml;">
&lt;plugin&gt;
    &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
    &lt;artifactId&gt;maven-surefire-plugin&lt;/artifactId&gt;
    &lt;configuration&gt;
        &lt;!-- Run only tests annotated with @FastTest. --&gt;
        &lt;includes&gt;
            &lt;include&gt;**/RunAllFastTests.java&lt;/include&gt;
        &lt;/includes&gt;
        ...
    &lt;/configuration&gt;
&lt;/plugin&gt;
</pre>
<p>Un petit bémol : si l&#8217;on travaille avec des projets multi-modules Maven (ce qui est mon cas), il faut que chaque module dispose de sa propre classe nommée <code>RunAllFastTests</code>.</p>
<p>Concernant les SlowTest, il me suffit de définir un profile Maven qui lancera la classe <code>RunAllSlowTests</code>, qui fera appel à la suite <code>SlowTestsSuite</code> qui appelle ma classe utilitaire pour trouver toutes les classes annotées par <code>@SlowTest</code>. Le serveur d&#8217;Intégration Continue <strike>Hudson</strike> Jenkins activant alors ce profile lors des nightly-builds.</p>
<h2>Conclusion</h2>
<p>Au final, il n&#8217;y a rien de bien méchant là-dedans, le principe une fois en place est simple (il suffit d&#8217;annoter la classe JUnit avec la bonne annotation). Mais je trouve cela regrettable que JUnit, pourtant très largement utilisé, soit aussi peu flexible pour un besoin somme toute très simple.</p>
<p>Donc si vous trouvez que j&#8217;ai sorti l&#8217;artillerie lourde pour rien, faites m&#8217;en part dans les commentaires, je suis curieux de voir comment vous vous y seriez pris !</p>
<h2>Bonus</h2>
<p>Suite à une suggestion de <a href="http://twitter.com/jpbriend" onclick="pageTracker._trackPageview('/outgoing/twitter.com/jpbriend?referer=');">Jean-Philippe Briend</a>, j&#8217;ai mis à disposition le code source d&#8217;un petit projet contenant toutes les classes évoquées ici.</p>
<p><a href="http://linsolas.free.fr/wordpress/wp-content/uploads/maven-junit-categories.zip"><img src="http://linsolas.free.fr/wordpress/wp-content/uploads/icon_zip.png"/> ZIP</a></p>
<p>Le projet se builde avec Maven 2 ou 3, Java 1.6 et JUnit 4.8.1.</p>
<p>En plus de toutes les classes nécessaires au bon fonctionnement du mécanisme, il contient trois classes de test unitaires, pour montrer le principe en action :</p>
<ul>
<li><code>OneFastTest</code>, annotée avec <code>@FastTest</code> ;</li>
<li><code>OneSlowTest</code>, annotée avec <code>@SlowTest</code> ;</li>
<li><code>TestWithoutAnnotation</code>, classe non annotée. Afin de montrer que ce test n&#8217;est pas exécuté, il contient une méthode qui appelle le <code>fail</code> de JUnit. Ainsi, si la classe est exécutée, le test échouera.</li>
</ul>
<p>En lançant la commande <code>mvn clean install</code>, seule la classe annotée avec <code>@FastTest</code> est exécutée.<br />
En lançant la commande <code>mvn clean install -Djenkins=true</code> (ou <code>-Pjenkins</code>), les deux classes annotées sont exécutées.</p>
<p>N&#8217;hésitez pas à me faire un retour sur ce projet si vous trouvez là aussi des énormités&#8230;</p>
<a href="javascript:toggleStartStop();PicLensLite.start({feedUrl:'http://linsolas.free.fr/wordpress/wp-content/plugins/wp-piclens/mrss.php?id=139'});">Start Slide Show with PicLens Lite <img src="http://linsolas.free.fr/wordpress/wp-content/plugins/wp-piclens/PicLensButton.png" alt="PicLens" width="16" height="12" border="0" align="top"></a>]]></content:encoded>
			<wfw:commentRss>http://linsolas.free.fr/wordpress/index.php/2011/02/categoriser-ses-tests-junit-avec-maven/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Première demi-journée Valtech TechDay</title>
		<link>http://linsolas.free.fr/wordpress/index.php/2010/10/premiere-demi-journee-valtech-techday/</link>
		<comments>http://linsolas.free.fr/wordpress/index.php/2010/10/premiere-demi-journee-valtech-techday/#comments</comments>
		<pubDate>Wed, 20 Oct 2010 19:52:19 +0000</pubDate>
		<dc:creator>Romain</dc:creator>
				<category><![CDATA[conférence]]></category>
		<category><![CDATA[news]]></category>
		<category><![CDATA[valtech]]></category>

		<guid isPermaLink="false">http://linsolas.free.fr/wordpress/?p=136</guid>
		<description><![CDATA[Valtech va organiser demain 21 octobre dans ses nouveaux locaux la première demi-journée technique pour ses consultants. Le programme est le suivant : 13h30 &#8211; 14h20 : NoSQL, tour d&#8217;horizon par Claude Falguière et Grégory Paul 14h30 &#8211; 15h05 : Migration top chrono d&#8217;une application JEE sur le Cloud Amazon par Fréderic Sauzet et Hervé Desaunois 14h10 [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.valtech.fr/fr/index.html" onclick="pageTracker._trackPageview('/outgoing/www.valtech.fr/fr/index.html?referer=');">Valtech</a> va organiser demain 21 octobre dans ses nouveaux locaux la première demi-journée technique pour ses consultants. Le programme est le suivant :</p>
<ul>
<li>13h30 &#8211; 14h20 : <em>NoSQL, tour d&#8217;horizon</em> par Claude Falguière et Grégory Paul</li>
<li>14h30 &#8211; 15h05 : <em>Migration top chrono d&#8217;une application JEE sur le Cloud Amazon</em> par Fréderic Sauzet et Hervé Desaunois</li>
<li>14h10 &#8211; 15h45 : <em>Migration top chrono d&#8217;une application .NET sur le Cloud Azure</em> par Lionel Molas et Cyril Aigoin</li>
<li>16h00 &#8211; 17h30 : <em>Ateliers de réflexion sur le thème de la mobilité</em></li>
<li>17h50 &#8211; 19h50 : <em>Coding Dojo Android, Windows Phone 7 et iPhone</em> animés par Pascal Ognibene, Philippe Miossec et Sylvain Rousseau</li>
</ul>
<p>Demain s&#8217;annonce donc être une journée passionnante et très instructive !</p>
<p>Suivez en direct <a href="http://twitter.com/romaintaz" onclick="pageTracker._trackPageview('/outgoing/twitter.com/romaintaz?referer=');">mes tweets</a> ainsi que ceux de <a href="http://twitter.com/ValtechTechno" onclick="pageTracker._trackPageview('/outgoing/twitter.com/ValtechTechno?referer=');">@ValtechTechno</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://linsolas.free.fr/wordpress/index.php/2010/10/premiere-demi-journee-valtech-techday/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
