<?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>Blog de Bruno Orsier &#187; BDD</title>
	<atom:link href="https://blog.developpez.com/bruno-orsier/pcategory/bdd/feed" rel="self" type="application/rss+xml" />
	<link>https://blog.developpez.com/bruno-orsier</link>
	<description></description>
	<lastBuildDate>Thu, 04 Apr 2013 16:06:21 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.1.42</generator>
	<item>
		<title>Quelques r&#233;f&#233;rences pour apprendre le BDD</title>
		<link>https://blog.developpez.com/bruno-orsier/p11819/bdd/quelques-rfrences-pour-apprendre-le-bdd</link>
		<comments>https://blog.developpez.com/bruno-orsier/p11819/bdd/quelques-rfrences-pour-apprendre-le-bdd#comments</comments>
		<pubDate>Wed, 06 Mar 2013 21:42:39 +0000</pubDate>
		<dc:creator><![CDATA[Bruno Orsier]]></dc:creator>
				<category><![CDATA[BDD]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/bruno-orsier/?p=63</guid>
		<description><![CDATA[On m’a demandé récemment quelques références sur le sujet du BDD – c’est un thème que j’ai déjà abordé dans des billets qui datent un peu. Voici quelques points de départ qui eux sont d’actualité : En fonction du langage de programmation: en .NET, voir Specflow : www.specflow.org en Java, voir jBehave : http://jbehave.org/ en Ruby, voir Cucumber : http://cukes.info/ Il existe aussi des outils moins dépendants d’un langage, comme GreenPepper : http://www.greenpeppersoftware.com/confluence/display/GPW/Home/, Fitnesse : [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>On m’a demandé récemment quelques références sur le sujet du BDD – c’est un thème que j’ai déjà abordé dans des billets qui datent un peu. Voici quelques points de départ qui eux sont d’actualité :</p>
<p>En fonction du langage de programmation:</p>
<ul>
<li>en .NET, voir Specflow : <a href="https://mail.persistent.co.in/OWA/redir.aspx?C=635bb828da144e5e8a6627df2767ee96&amp;URL=http%3a%2f%2fwww.specflow.org">www.specflow.org</a></li>
<li>en Java, voir jBehave : <a href="https://mail.persistent.co.in/OWA/redir.aspx?C=635bb828da144e5e8a6627df2767ee96&amp;URL=http%3a%2f%2fjbehave.org%2f">http://jbehave.org/</a></li>
<li>en Ruby, voir Cucumber : <a href="http://cukes.info/">http://cukes.info/</a></li>
</ul>
<p>Il existe aussi des outils moins dépendants d’un langage, comme</p>
<ul>
<li>GreenPepper : <a href="http://www.greenpeppersoftware.com/confluence/display/GPW/Home/">http://www.greenpeppersoftware.com/confluence/display/GPW/Home/</a>, </li>
<li>Fitnesse : <a href="http://fitnesse.org/">http://fitnesse.org/</a>&#160;</li>
</ul>
<p>Pour prendre du recul par rapport aux outils, il faut étudier les travaux de Dan North, qui a introduit la notion de BDD vers 2003 je crois, et qui a écrit cette <a href="http://dannorth.net/introducing-bdd/" target="_blank">introduction au BDD</a> (en anglais, mais <a href="http://philippe.poumaroux.free.fr/index.php?post/2012/02/06/Introduction-au-Behaviour-Driven-Developement" target="_blank">traduite en français</a> par <em>Philippe Poumaroux</em>). On peut voir le BDD comme la spécification du comportement attendu d’un logiciel.</p>
<p>Il est aussi très utile d’étudier le concept de <strong>Spécification par l’exemple</strong>, concept inventé par Gojko Adzic. On peut trouver une introduction ici : <a href="http://specificationbyexample.com/key_ideas.html">http://specificationbyexample.com/key_ideas.html</a>, mais Gojko a aussi écrit un livre complet sur la question, <a href="http://www.amazon.fr/Specification-Example-Gojko-Adzic/dp/1617290084" target="_blank">Specification By Example</a>. </p>
<p>Ces deux concepts, spécification par l’exemple et spécification du comportement attendu, permettent de comprendre l’utilité des outils mentionnés plus haut.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Du BDD vers le TDD, et vice-versa</title>
		<link>https://blog.developpez.com/bruno-orsier/p8594/tests-unitaires/du_bdd_vers_le_tdd_et_vice_versa</link>
		<comments>https://blog.developpez.com/bruno-orsier/p8594/tests-unitaires/du_bdd_vers_le_tdd_et_vice_versa#comments</comments>
		<pubDate>Thu, 04 Feb 2010 16:00:26 +0000</pubDate>
		<dc:creator><![CDATA[Bruno Orsier]]></dc:creator>
				<category><![CDATA[BDD]]></category>
		<category><![CDATA[Tests unitaires]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Avant de passer au compte-rendu du dojo d&#8217;aujourd&#8217;hui, voici un nouvel éclairage sur l&#8217;articulation entre TDD et BDD, que j&#8217;emprunte à ce billet Behavior Driven Development with NBehave (trouvé grâce à cet autre billet Bien Tester une application Asp.net MVC sur le BDD par Guillaume Saint Etienne). Je pense que dans les dojos précédents nous avons bien compris et bien pratiqué le cycle RED/GREEN/REFACTOR du TDD : Nous voulons maintenant comprendre comment cela s&#8217;articule avec [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Avant de passer au compte-rendu du dojo d&rsquo;aujourd&rsquo;hui, voici un nouvel éclairage sur l&rsquo;articulation entre TDD et BDD, que j&rsquo;emprunte à ce billet <a href="http://pebblesteps.com/post/Behavior-Driven-Development-with-NBehave.aspx" target="_blank">Behavior Driven Development with NBehave</a> (trouvé grâce à cet autre billet <a href="http://www.dotnetguru2.org/gse/index.php/2010/01/21/bien-tester-une-application-asp-net-mvc" target="_blank">Bien Tester une application Asp.net MVC</a> sur le BDD par Guillaume Saint Etienne).</p>
<p>Je pense que dans les dojos précédents nous avons bien compris et bien pratiqué le cycle RED/GREEN/REFACTOR du TDD :</p>
<p><a href="http://pebblesteps.com/post/Behavior-Driven-Development-with-NBehave.aspx"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/e64affed95e6_8F87/image4.png" width="248" height="46" /></a> </p>
<p>Nous voulons maintenant comprendre comment cela s&rsquo;articule avec le BDD (partant du principe que nous sommes convaincus que cela vaut le coup de <a href="http://blog.developpez.com/bruno-orsier/p8534/developpement-agile/pourquoi-sarsquo-interesser-au-bdd-behav/" target="_blank">s&rsquo;intéresser au BDD</a>). </p>
<p>Je trouve que le schéma ci-dessous de <a href="http://pebblesteps.com/post/Behavior-Driven-Development-with-NBehave.aspx" target="_blank">Behavior Driven Development with NBehave</a> illustre assez bien la manière de procéder, du BDD vers le TDD :</p>
<p><a href="http://pebblesteps.com/post/Behavior-Driven-Development-with-NBehave.aspx" target="_blank"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/e64affed95e6_8F87/image.png" width="456" height="106" /></a> </p>
<p><span id="more-47"></span></p>
<p>Voici comment je comprends ce schéma :</p>
<ul>
<li>On se laisse donc guider par une user story (ce qui évite un risque du TDD qui est de s&rsquo;égarer sur des questions peu pertinentes pour l&rsquo;utilisateur final, étant donné que l&rsquo;on travaille très près du code). </li>
<li>La première étape est d&rsquo;avoir des scénarios &laquo;&nbsp;Pending&nbsp;&raquo; &#8211; en Cucumber cela correspond au premier fragment de pont que Cucumber génère automatiquement. </li>
<li>En implémentant ces scénarios, on définit itérativement l&rsquo;API des classes métier. Pour cela on suit un cycle RED/GREEN/REFACTOR au niveau de l&rsquo;outil de BDD, et on ne cherche pas nécessairement à implémenter le comportement réel et final : on peut utiliser des comportements &laquo;&nbsp;codés en dur&nbsp;&raquo;, ou simplistes &#8211; c&rsquo;est ce qu&rsquo;illustrait le dojo précédent finalement. C&rsquo;est la partie &laquo;&nbsp;Stubbed Scenario&nbsp;&raquo; ci-dessus. </li>
<li>Une fois que l&rsquo;API est stable, on implémente le comportement réel, et pour cela on pratique le RED/GREEN/REFACTOR en changeant d&rsquo;outil : cette fois on fait du TDD avec un outil du type xUnit. </li>
<li>Et l&rsquo;on obtient un test d&rsquo;acceptance (sous forme de scénario exécutable) à la fin du processus. </li>
</ul>
<p>Aujourd&rsquo;hui dans le dojo nous avons travaillé essentiellement au niveau &laquo;&nbsp;Real Behavior&nbsp;&raquo;, l&rsquo;API de notre classe <em>CalibrationCurve</em> avait en effet été stabilisée grâce au travail de la dernière fois, nous n&rsquo;avons pas eu à la retoucher. Par contre nous avons complètement reprogrammé son comportement interne.</p>
<p>Pour commencer à programmer, nous nous sommes appuyés sur le test unitaire suivant :</p>
<div id="codeSnippetWrapper" class="csharpcode-wrapper">
<pre id="codeSnippet" class="csharpcode"><span class="kwrd">class</span> LinearRegressionTest ? Test::Unit::TestCase<br /><br />  def setup<br />    @curve = CalibrationCurve.<span class="kwrd">new</span><br />    @curve.ajoute_points(0, 10)<br />    @curve.ajoute_points(10, 100)<br />  end<br /><br />  def test_calcul_slope<br />    assert_in_delta(0.111, @curve.calcule_slope, 0.001)<br />  end<br /><br />  def test_calcule_ordinate<br />    assert_in_delta(-1.111, @curve.calcule_ordinate, 0.001)<br />  end<br /><br />end<br /></pre>
<p></div>
<p><em><font size="2">(désolé, pour d&rsquo;obscures raisons le moteur de blog ne me laisse pas insérer le caractère &laquo;&nbsp;inférieur&nbsp;&raquo;, et j&rsquo;ai mis &#8804; à la place dans les morceaux de code qui en avaient besoin)</font></em></p>
<p>On peut noter que nous n&rsquo;avons pas inventé de nouvelles données du test, nous avons simplement utilisé les données déjà présentes dans le scénario qui échouait à la fin de la dernière séance :</p>
<p><img src="http://ftp-developpez.com/bruno-orsier/blog/images/1180c6cc8ff6_A297/image_5.png" /> </p>
<p>Avec le recul, on peut se demander si ce test unitaire n&rsquo;est pas complètement redondant avec le scénario, et s&rsquo;il présente vraiment de l&rsquo;intérêt ! En effet nous exerçons l&rsquo;API de notre classe exactement comme dans le pont entre le scénario et la classe CalibrationCurve. </p>
<p>Par contre, en programmant les calculs nous avons identifié un cas limite (un seul point fourni par l&rsquo;utilisateur) et nous avons dû prendre une décision sur le comportement attendu. Voici un test unitaire qui couvre ce cas :</p>
<div id="codeSnippetWrapper" class="csharpcode-wrapper">
<pre id="codeSnippet" class="csharpcode"><span class="kwrd">class</span> LinearRegressionTestLimite ? Test::Unit::TestCase<br /><br />  def setu&lt;<br />    @curve = CalibrationCurve.<span class="kwrd">new</span><br />    @curve.ajoute_points(0, 0)<br />  end<br /><br />  def test_slope_should_be_zero<br />    assert_equal(@curve.calcule_slope, 0)<br />  end<br /><br />  def test_ordinate_should_be_zero<br />      assert_equal(@curve.calcule_ordinate, 0)<br />    end<br /><br />end</pre>
<p></div>
<p>On peut alors se demander si cette information doit rester &laquo;&nbsp;cachée&nbsp;&raquo; dans un test unitaire, ou bien s&rsquo;il faut la faire remonter à l&rsquo;utilisateur, via un complément de scénario. La décision dépend surement d&rsquo;un dialogue avec les utilisateurs : est-ce que ce cas limite est pertinent pour eux ou non ? est-ce qu&rsquo;ils sont intéressés par spécifier le comportement attendu ?</p>
<p>En tout cas ce petit exemple nous indique déjà que le schéma ci-dessus <strong>Story ==> Acceptance Test</strong> n&rsquo;est pas si linéaire que cela : <strong><font color="#ff0000">en travaillant en TDD, nous pouvons découvrir des compléments de scénarios !</font></strong></p>
<p>Sur un point plus technique, nous avons également éprouvé le besoin d&rsquo;un test unitaire pour nous assurer du bon fonctionnement de notre extension du module Enumerable, auquel nous avons ajouté une méthode <em>mean</em> comme ci-dessous :</p>
<div id="codeSnippetWrapper" class="csharpcode-wrapper">
<pre id="codeSnippet" class="csharpcode">module Enumerable<br />  def mean<br />    sum = self.inject(0.0) <span class="kwrd">do</span> |sum, xi|<br />      sum = sum + xi<br />    end<br />    <span class="kwrd">return</span> sum / self.size<br />  end  <br />end</pre>
<p></div>
<p>Comme nous ne connaissions pas suffisamment le principe du <em>inject</em>, le test unitaire nous a rassuré sur le bon fonctionnement de notre extension <em>mean</em> :</p>
<div id="codeSnippetWrapper" class="csharpcode-wrapper">
<pre id="codeSnippet" class="csharpcode"><span class="kwrd">class</span> EnumerableTest ? Test::Unit::TestCase<br /><br />  def setup<br />    @array = [10, 100]<br />  end<br /><br />  def test_mean<br />    assert_equal(55, @array.mean)<br />  end  <br />end</pre>
<p></div>
<p>En ce qui me concerne, je garderais comme test unitaire uniquement ce dernier point très technique, et je me contenterais du scénario et d&rsquo;un complément de scénario pour le cas limite. Et vous, comment feriez-vous ?</p>
<p>Pour finir, le code de <em>CalibrationCurve</em> qui passe avec succès nos scénarios et tests unitaires :</p>
<div id="codeSnippetWrapper" class="csharpcode-wrapper">
<pre id="codeSnippet" class="csharpcode"><span class="kwrd">class</span> CalibrationCurve<br /><br />  def initialize<br />    @x = []<br />    @y = []<br />  end<br /><br />  def compute<br />    xbar = @x.mean   <br />    ybar = @y.mean<br />    sx2= @x.map{|xi| (xi-xbar)**2}.mean<br /><br />    sum = 0<br />    @x.each_with_index <span class="kwrd">do</span> |xi, i|<br />      sum = sum + (@x[i]-xbar)*(@y[i]-ybar)<br />    end<br />    sxy = sum / @x.size<br /><br />    <span class="kwrd">if</span> sx2.abs != 0 then<br />      @a = sxy / sx2<br />      @b = ybar - @a*xbar<br />    <span class="kwrd">else</span><br />      @a = 0<br />      @b = 0<br />    end<br />  end<br /><br />  def ajoute_points (area,concentration)<br />    @x.push(concentration)<br />    @y.push(area)<br /><br />    compute<br />  end<br /><br />  def calcul_concentration(area)<br />    <span class="kwrd">return</span> (area - @b) / @a<br />  end<br /><br />  def calcule_slope<br />    <span class="kwrd">return</span> @a<br />  end<br /><br />  def calcule_ordinate<br />    <span class="kwrd">return</span> @b<br />  end<br /><br />end</pre>
<p></div>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>BDD, l&#8217;exemple des courbes de calibration</title>
		<link>https://blog.developpez.com/bruno-orsier/p8590/developpement-agile/bdd_larsquo_exemple_des_courbes_de_calib</link>
		<comments>https://blog.developpez.com/bruno-orsier/p8590/developpement-agile/bdd_larsquo_exemple_des_courbes_de_calib#comments</comments>
		<pubDate>Wed, 03 Feb 2010 12:28:26 +0000</pubDate>
		<dc:creator><![CDATA[Bruno Orsier]]></dc:creator>
				<category><![CDATA[BDD]]></category>
		<category><![CDATA[Développement agile]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Dans le 18e coding dojo du Club Agile Rhône Alpes, ce 5 janvier dernier, j&#8217;avais pris un exemple réel issu de nos plans de tests, et basé sur les courbes de calibration, un concept très utilisé en chimie (et donc dans nos applications). Demain, dans la 20ème session, nous poursuivrons sur cet exemple. Comme pas mal de jours ont passé, ce billet est destiné à nous rafraîchir la mémoire sur la question, à moi le [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Dans le <a href="http://groups.google.fr/group/cara-dojo/browse_thread/thread/192b5623e0e5d1de" target="_blank">18e coding dojo</a> du <a href="http://clubagile.org/" target="_blank">Club Agile Rhône Alpes</a>, ce 5 janvier dernier, j&rsquo;avais pris un exemple réel issu de nos plans de tests, et basé sur les <a href="http://en.wikipedia.org/wiki/Calibration_curve" target="_blank">courbes de calibration</a>, un concept très utilisé en chimie (et donc dans nos applications). Demain, dans la <a href="http://groups.google.fr/group/cara-dojo/browse_thread/thread/ff615604b9efdc5d/655a8949709eb347?show_docid=655a8949709eb347" target="_blank">20ème session</a>, nous poursuivrons sur cet exemple. Comme pas mal de jours ont passé, ce billet est destiné à nous rafraîchir la mémoire sur la question, à moi le premier !</p>
<p><span id="more-46"></span></p>
<p>Le but du dojo est de faire exécuter un scénario réaliste comme celui-ci dessous, que j&rsquo;avais mis au point avec une collègue chimiste :</p>
<p><a href="http://ftp-developpez.com/bruno-orsier/blog/images/1180c6cc8ff6_A297/image.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/1180c6cc8ff6_A297/image_thumb.png" width="559" height="446" /></a> </p>
<p>Ce qui nous intéresse c&rsquo;est qu&rsquo;il faut implémenter un calcul de <a href="http://fr.wikipedia.org/wiki/R%C3%A9gression_lin%C3%A9aire" target="_blank">régression linéaire</a>,  et pour cela il sera probablement nécessaire de pratiquer un peu de TDD en plus du BDD ci-dessus, et c&rsquo;est pourquoi l&rsquo;exemple peut nous montrer comment s&rsquo;articulent BDD et TDD.</p>
<p>Dans la séance du 5 janvier j&rsquo;avais proposé un scénario simplifié, afin de prendre en main l&rsquo;environnement de développement (j&rsquo;utilise <a href="http://www.jetbrains.com/ruby/index.html" target="_blank">RubyMine</a>, mais on peut aussi travailler directement en ligne de commande avec Cucumber).</p>
<p><a href="http://ftp-developpez.com/bruno-orsier/blog/images/1180c6cc8ff6_A297/image_3.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/1180c6cc8ff6_A297/image_thumb_3.png" width="544" height="462" /></a> </p>
<p>L&rsquo;idée était d&rsquo;aligner tous les points sur une droite passant par zéro, comme cela on pouvait trouver l&rsquo;équation de la droite sans la régression linéaire (dans un premier temps), et donc juste se familiariser avec l&rsquo;IDE et les diverses notions (les scénarios, le pont, le code métier).</p>
<p>J&rsquo;avais aussi un deuxième scénario pour vérifier qu&rsquo;on savait bien faire des vérifications sur les nombres flottants :</p>
<p><a href="http://ftp-developpez.com/bruno-orsier/blog/images/1180c6cc8ff6_A297/image_4.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/1180c6cc8ff6_A297/image_thumb_4.png" width="500" height="142" /></a> </p>
<p>Pas très excitant, mais important en calcul scientifique !</p>
<p>Et le troisième scénario proposait une droite qui ne passait plus par zéro :</p>
<p><a href="http://ftp-developpez.com/bruno-orsier/blog/images/1180c6cc8ff6_A297/image_5.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/1180c6cc8ff6_A297/image_thumb_5.png" width="493" height="150" /></a> </p>
<p>Et justement le dojo s&rsquo;était arrêté sur l&rsquo;échec de ce dernier test &#8211; notre calcul de l&rsquo;équation était vraiment trop simpliste :</p>
<p><a href="http://ftp-developpez.com/bruno-orsier/blog/images/1180c6cc8ff6_A297/image_6.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/1180c6cc8ff6_A297/image_thumb_6.png" width="353" height="438" /></a> </p>
<p>D&rsquo;après la rétrospective de la session, ces scénarios simplifiés n&rsquo;étaient pas forcément une bonne idée, car ils nous ont un peu éloigné de l&rsquo;objectif d&rsquo;aller vers du TDD. Il n&rsquo;est pas simple dans l&rsquo;animation des dojos de trouver le bon équilibre entre pédagogie et bonne progression !</p>
<p>Ils nous ont tout de même permis de mettre au point le pont suivant vers le code métier, pont qui sera utilisé tel quel dans la session de demain :</p>
<div id="codeSnippetWrapper" class="csharpcode-wrapper">
<pre id="codeSnippet" class="csharpcode">Given /^the calibration mode is R=f\(Q\)$/ <span class="kwrd">do</span><br />   #nothing<br />end<br /><br />Given /^a calibration curve <span class="kwrd">for</span> component CO2 <span class="kwrd">with</span> the points:$/ <span class="kwrd">do</span> |table|<br />  @curve = CalibrationCurve.new  <br />  table.hashes.each <span class="kwrd">do</span> |hash|<br />    area = hash[<span class="str">"Area"</span>]<br />    concentration=hash[<span class="str">"Concentration"</span>]<br />    @curve.ajoute_points(area.to_f, concentration.to_f)<br />  end<br />end<br /><br /><span class="kwrd">Then</span> /^the computed concentration <span class="kwrd">for</span> area (.*) should be (.*)$/ <span class="kwrd">do</span> |area, expected_concentration|<br />  calcul_concentration = @curve.calcul_concentration(area.to_f)<br />  calcul_concentration.should be_close(expected_concentration.to_f, 0.001)<br />end<br /><br />When /^the slope should be (.*)$/ <span class="kwrd">do</span> |expected_slope|<br />  @curve.calcule_slope.should == expected_slope.to_f<br /><br />end<br /><br />When /^the ordinate at origin should be (.*)$/ <span class="kwrd">do</span> |expected_ordinate|<br />  @curve.calcule_ordinate.should == expected_ordinate.to_f<br />end<br /><br />When /^the following table should be valid:$/ <span class="kwrd">do</span> |table|<br />    table.hashes.each <span class="kwrd">do</span> |hash|<br />    area = hash[<span class="str">"Area"</span>]<br />    concentration=hash[<span class="str">"Concentration"</span>]<br />    @curve.calcul_concentration(area.to_f).should == concentration.to_f<br />  end<br />end<br /></pre>
<p></div>
<p>Alors à demain à l&rsquo;ENSIMAG salle 206 de 12 à 14h pour la suite !</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Un exemple de rédaction de spécifications exécutables avec Cucumber</title>
		<link>https://blog.developpez.com/bruno-orsier/p8551/developpement-agile/un_exemple_de_redaction_de_specification</link>
		<comments>https://blog.developpez.com/bruno-orsier/p8551/developpement-agile/un_exemple_de_redaction_de_specification#comments</comments>
		<pubDate>Fri, 29 Jan 2010 15:03:46 +0000</pubDate>
		<dc:creator><![CDATA[Bruno Orsier]]></dc:creator>
				<category><![CDATA[BDD]]></category>
		<category><![CDATA[Développement agile]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Pour démarrer la discussion sur la rédaction de spécifications exécutables l&#8217;autre soir au CARA, j&#8217;avais pris l&#8217;exemple de la réalisation d&#8217;un logiciel de comptage de calories. L&#8217;exemple n&#8217;est pas gratuit : je trouve que la plupart des logiciels de ce genre ont une interface utilisateur très influencée par l&#8217;implémentation avec une base de données, et pas très influencée par les besoins utilisateurs. Pardonnez l&#8217;expression, mais ce genre de logiciel &#171;&#160;pue la base de données&#160;&#187;, alors [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Pour démarrer la discussion sur la rédaction de spécifications exécutables <a href="http://blog.developpez.com/bruno-orsier/p8534/developpement-agile/pourquoi-sarsquo-interesser-au-bdd-behav/" target="_blank">l&rsquo;autre soir au CARA</a>, j&rsquo;avais pris l&rsquo;exemple de la réalisation d&rsquo;un logiciel de comptage de calories. L&rsquo;exemple n&rsquo;est pas gratuit : je trouve que la plupart des logiciels de ce genre ont une interface utilisateur très influencée par l&rsquo;implémentation avec une base de données, et pas très influencée par les besoins utilisateurs. Pardonnez l&rsquo;expression, mais ce genre de logiciel &laquo;&nbsp;pue la base de données&nbsp;&raquo;, alors que la base de donnée n&rsquo;a que peu de valeur pour l&rsquo;utilisateur &#8211; c&rsquo;est juste un choix d&rsquo;implémentation bien pratique pour les développeurs. </p>
<p>Par conséquent, il me semble que travailler sur un tel logiciel est intéressant pour apprendre le BDD, car justement nous aimerions éviter de &laquo;&nbsp;polluer&nbsp;&raquo; les scénarios par des concepts purement techniques comme des questions de base de données. Le challenge est donc de parvenir à exprimer les scénarios avec des mots d&rsquo;utilisateur et pas du jargon informatique.</p>
<p>Dans ce billet je vais détailler mon point de départ et illustrer les premières leçons que j&rsquo;ai tirées des discussions. Bien sûr cela reste un exemple &laquo;&nbsp;jouet&nbsp;&raquo; mais je parviendrai peut-être à en faire une application complète dans quelque temps.</p>
<p>Je suis également passé à la rédaction de scénarios en français, ce qui est possible en Cucumber (tapez la commande <font face="Courier New">cucumber -i18n fr</font> pour avoir les équivalences).</p>
<p>Mon point de départ était la fonctionnalité suivante :</p>
<p><a href="http://ftp-developpez.com/bruno-orsier/blog/images/13a27bf0274f_E501/image.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/13a27bf0274f_E501/image_thumb.png" width="492" height="76" /></a> </p>
<p>
<span id="more-45"></span></p>
<p>Les discussions ont fait apparaître que &laquo;&nbsp;qui veut perdre du poids&nbsp;&raquo; n&rsquo;avait aucune influence pour le moment (je voulais souligner que cela pourrait avoir de l&rsquo;importance dans de futures fonctionnalités, mais cette information superflue ici rend simplement plus difficile la compréhension de la fonctionnalité). Donc une<strong> leçon à retenir : ne pas &laquo;&nbsp;sur-spécifier&nbsp;&raquo;</strong> !</p>
<p>J&rsquo;ai ensuite écrit de très petits scénarios comme : </p>
<p><a href="http://ftp-developpez.com/bruno-orsier/blog/images/13a27bf0274f_E501/image_3.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/13a27bf0274f_E501/image_thumb_3.png" width="644" height="173" /></a></p>
<p>ce qui m&rsquo;a permit ensuite d&rsquo;écrire un scénario couvrant une journée complète (<em>les lignes commençant par # sont des commentaires</em>) :</p>
<p><a href="http://ftp-developpez.com/bruno-orsier/blog/images/13a27bf0274f_E501/image_4.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/13a27bf0274f_E501/image_thumb_4.png" width="647" height="252" /></a> </p>
<p>et ainsi de suite. Cela m&rsquo;a permis d&rsquo;arriver un scénario vérifiant la fonctionnalité &laquo;&nbsp;connaître le nombre total de calories pour la journée&nbsp;&raquo;.</p>
<p>Les petits scénarios m&rsquo;ont été utiles pour mettre au point le code derrière tout cela en faisant de petits pas (tout comme quand on pratique le TDD). Mais ils contribuent à l&rsquo;impression de &laquo;&nbsp;verbosité excessive&nbsp;&raquo; que mes scénarios ont donné durant la présentation, donc il faut surement accepter de les supprimer une fois que leur intention a été capturée par ailleurs dans le scénario final.</p>
<p>J&rsquo;ai ensuite travaillé sur une deuxième fonctionnalité :</p>
<p><a href="http://ftp-developpez.com/bruno-orsier/blog/images/13a27bf0274f_E501/image_5.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/13a27bf0274f_E501/image_thumb_5.png" width="574" height="87" /></a> </p>
<p>Fonctionnalité que j&rsquo;ai souhaité vérifier de la manière suivante :</p>
<p><a href="http://ftp-developpez.com/bruno-orsier/blog/images/13a27bf0274f_E501/image_6.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/13a27bf0274f_E501/image_thumb_6.png" width="678" height="271" /></a> </p>
<p>Un point qui a posé problème est que je ne vérifie pas la totalité du contenu de la table des aliments &#8211; cela ne me paraît pas nécessaire. Mais mes attentes sont peu claires pour le lecteur, et pour lever l&rsquo;ambiguïté il aurait sans doute suffit d&rsquo;écrire &laquo;&nbsp;<font color="#ff0000"><font color="#000000">la table des aliments contient</font> notamment</font><font color="#000000">:&nbsp;&raquo;. Il faut donc <strong>rédiger les vérifications avec beaucoup de précision et de clarté</strong>.</font></p>
<p>Un deuxième problème est que mon scénario est bien plus long que la copie d&rsquo;écran ci-dessus &#8211; en effet j&rsquo;avais à nouveau couvert avec mes exemples une journée complète. Ce qui est inutile vu que le calcul pour la journée était déjà couvert par la vérification de la fonctionnalité précédente ! Donc une autre<strong> leçon à retenir est de ne pas &laquo;&nbsp;sur-vérifier&nbsp;&raquo;</strong>.</p>
<p>La troisième fonctionnalité consistait à travailler à partir d&rsquo;une table pré-remplie :</p>
<p><a href="http://ftp-developpez.com/bruno-orsier/blog/images/13a27bf0274f_E501/image_7.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/13a27bf0274f_E501/image_thumb_7.png" width="647" height="221" /></a> </p>
<p>etc.</p>
<p>Mes scénarios ci-dessus ont suscité un vif débat, car ils semblent représenter un effort démesuré par rapport au volume de code qui est testé derrière. En effet il s&rsquo;agit d&rsquo;implémenter une simple règle de trois, de parcourir des listes, d&rsquo;utiliser une table de hachage. Je pense que la critique était justifiée, et que mes scénarios auraient pu contenir moins d&rsquo;information, mais que cela ne remet pas en cause l&rsquo;intérêt du BDD et l&rsquo;intérêt de travailler avec des exemples (ces derniers méritant certainement d&rsquo;être réhabilités dans nos processus de développement logiciel &#8211; voir mon <a href="http://blog.developpez.com/bruno-orsier/p8534/developpement-agile/pourquoi-sarsquo-interesser-au-bdd-behav/">billet précédent</a>).</p>
<p>Un autre élément de débat était de savoir comment se positionner par rapport à une éventuelle interface graphique. Etant donné la manière dont j&rsquo;ai écrit et réalisé les fonctionnalités, l&rsquo;application n&rsquo;existe pas encore, je suis simplement en train de mettre au point une bibliothèque de classes, indépendamment de la manière dont elles seront ultérieurement présentées à un utilisateur. Cette approche était confortable par certains, mais d&rsquo;autres auraient préféré travailler à partir d&rsquo;une interface graphique (le risque étant de mettre au point un bon modèle métier bien testé, mais de ne pas satisfaire les utilisateurs qui veulent voir très vite une interface graphique).</p>
<p>Je pense que le schéma suivant de <a title="http://www.dddfrance.org/DDDViteFait" href="http://www.dddfrance.org/DDDViteFait" target="_blank">DDD Vite Fait</a> illustre l&rsquo;endroit où j&rsquo;essaie de me placer pour l&rsquo;instant &#8211; mes scénarios concernent le domaine, et pas l&rsquo;application, ce qui est source de confusion :</p>
<p><a href="http://ftp-developpez.com/bruno-orsier/blog/images/13a27bf0274f_E501/image_8.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/13a27bf0274f_E501/image_thumb_8.png" width="354" height="212" /></a> </p>
<p>Pour finir ce billet, au cas ou vous soyez curieux de ce qu&rsquo;il y a derrière (c&rsquo;est généralement le cas quand je présente les scénarios), je vous montre le code que j&rsquo;ai écrit pour le pont entre les scénarios exécutables et les classes du domaine :</p>
</p>
<div id="codeSnippetWrapper" class="csharpcode-wrapper">
<pre id="codeSnippet" class="csharpcode"># encoding: UTF-8<br /><br />require 'F:\ruby\cucumber\comptageCalories\ComptageCalories\compteur_calories.rb'<br />require 'F:\ruby\cucumber\comptageCalories\ComptageCalories\table_aliments.rb'<br /><br />Before <span class="kwrd">do</span><br />  @compteur = CompteurCalories.new<br />  @table_aliments = TableAliments.new<br />end<br /><br /><br />When /^le nombre total de calories devrait être (.*)$/ <span class="kwrd">do</span> |calories|<br />  #puts @compteur.total_calories<br />  @compteur.total_calories.should be_equal calories.to_i<br />end<br /><br />When /^une table des aliments vide$/ <span class="kwrd">do</span><br />  #rien<br />end<br /><br />When /^la table des aliments contient:$/ <span class="kwrd">do</span> |table|<br />  # table is a | confiture | 1 | cuillère à café | 30 |<br />  table.hashes.each <span class="kwrd">do</span> |hash|<br />    reference = @table_aliments.reference(hash[<span class="str">"aliment"</span>])<br />    reference.quantite.should == hash[<span class="str">"quantite"</span>]<br />    reference.unite.should == hash[<span class="str">"unite"</span>]<br />    reference.calories.should == hash[<span class="str">"calories"</span>]<br />  end<br />end<br /><br />When /^je mange (\d+\.?\d*) (.*) (de\s+|d')(.*\w|.*%) \((\d+) (.*) valant (.*) calories\)$/ <span class="kwrd">do</span>  |quantite_dans_unite,unite1, de, nom_aliment,reference_dans_unite,unite2,reference_en_calories|<br />  @table_aliments.ajoute(nom_aliment, reference_dans_unite,unite2, reference_en_calories)<br />  @compteur.ajoute(nom_aliment,quantite_dans_unite, reference_dans_unite, reference_en_calories)<br />end<br /><br />When /^je mange (\d+\.?\d*) (.*) (de\s+|d')(.*\w|.*%)$/ <span class="kwrd">do</span> |quantite_dans_unite,unite1, de, nom_aliment|<br />     reference = @table_aliments.reference(nom_aliment)                   <br />     reference_dans_unite = reference.quantite                                <br />     reference_en_calories = reference.calories<br />     @compteur.ajoute(nom_aliment,quantite_dans_unite, reference_dans_unite, reference_en_calories)  <br />end<br /><br /><br />When /^la table des aliments suivante:$/ <span class="kwrd">do</span> |table|<br />  # table is a | confiture | 1 | cuillère à café | 30 |<br />  table.hashes.each <span class="kwrd">do</span> |hash|<br />    @table_aliments.ajoute(hash[<span class="str">"aliment"</span>],hash[<span class="str">"quantite"</span>],hash[<span class="str">"unite"</span>],hash[<span class="str">"calories"</span>])<br />  end<br />end<br /></pre>
<p></div>
<div>Le pont implique de manipuler des expressions régulières et d&rsquo;utiliser classes et méthodes du domaine, il faut donc absolument un développeur pour le réaliser. Il y a certainement moyen de rendre le pont plus lisible &#8211; sans doute avec le concept récent de <a href="http://www.engineyard.com/blog/2009/cucumber-step-argument-transforms/" target="_blank">Step Argument Transforms</a> que m&rsquo;a signalé récemment <a href="http://21croissants.blogspot.com/" target="_blank">Jean-Michel Garnier</a>. Je regarderai comment faire dans un deuxième temps. D&rsquo;ailleurs, dans ma TODO list, il y a également l&rsquo;étude de <a href="http://www.engineyard.com/blog/2009/15-expert-tips-for-using-cucumber/" target="_blank">15 Expert Tips for Using Cucumber</a>.</div>
<div> </div>
<div>Je vous passe le code final, les deux classes CompteurCalories et TableAliments, elles représentent vraiment peu de code pour le moment ! Je les ai codées en Ruby, mais comme je l&rsquo;ai indiqué dans d&rsquo;autres billets il n&rsquo;y pas de difficulté technique à les réaliser en .NET.</div>
<div></div>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pourquoi s&#8217;intéresser au BDD (Behavior Driven Development) ?</title>
		<link>https://blog.developpez.com/bruno-orsier/p8534/developpement-agile/pourquoi_sarsquo_interesser_au_bdd_behav</link>
		<comments>https://blog.developpez.com/bruno-orsier/p8534/developpement-agile/pourquoi_sarsquo_interesser_au_bdd_behav#comments</comments>
		<pubDate>Tue, 19 Jan 2010 12:22:09 +0000</pubDate>
		<dc:creator><![CDATA[Bruno Orsier]]></dc:creator>
				<category><![CDATA[BDD]]></category>
		<category><![CDATA[Développement agile]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[La réunion du CARA sur la rédaction de spécifications exécutables grâce au BDD (Behavior Driven Development) a été très intense. Merci aux nombreux participants pour cette soirée stimulante et aux camarades du CARA pour l&#8217;organisation ! J&#8217;ai le sentiment que tout le monde a pu gagner une compréhension plus concrète du BDD, et a pu appréhender l&#8217;aspect collaboratif de la rédaction de scénarios. Les discussions ont certainement dérivé de l&#8217;objectif initial qui était d&#8217;explorer différentes [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>La réunion du CARA sur la rédaction de spécifications exécutables grâce au BDD (Behavior Driven Development) a été très intense. Merci aux nombreux participants pour cette soirée stimulante et aux camarades du CARA pour l&rsquo;organisation ! J&rsquo;ai le sentiment que tout le monde a pu gagner une compréhension plus concrète du BDD, et a pu appréhender l&rsquo;aspect <strong>collaboratif</strong> de la rédaction de scénarios.</p>
<p>Les discussions ont certainement dérivé de l&rsquo;objectif initial qui était d&rsquo;explorer différentes manière d&rsquo;écrire des spécifications exécutables, mais elles n&rsquo;en ont pas moins été très intéressantes. Il y a eu trop d&rsquo;échanges pour tout retracer dans un seul billet, donc ici je vais me concentrer sur l&rsquo;un des aspects : pourquoi s&rsquo;intéresser au BDD ?</p>
<p><span id="more-27"></span></p>
<p>En effet, certains participants ont pu être surpris par l&rsquo;approche elle-même : en gros, pourquoi passer tant d&rsquo;énergie à <strong>décrire des exemples</strong> alors que l&rsquo;application pourrait très bien être décrite par des règles plus abstraites voire des formules mathématiques ? Le BDD, avec son caractère très verbeux, semble un effort inutile, et en tout cas ne paraît pas &laquo;&nbsp;<em>faire gagner du temps</em>&laquo;&nbsp;. Il y a eu des échanges assez vifs sur ce thème, et voici quelques éléments qui ressortent en faveur du BDD :</p>
<ul>
<li>le pouvoir des exemples est souvent sous-estimé. Je viens de parcourir le livre de Gojko Adzic <br />
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td><img src="http://ecx.images-amazon.com/images/I/51phjDwqiLL._SL75_.jpg" /> </td>
<td valign="top"><a href="http://www.acceptancetesting.info/the-book/">Bridging the Communication Gap: Specification by Example and Agile Acceptance Testing</a> </td>
</tr>
</tbody>
</table>
<p>            pour trouver des arguments complémentaires sur ce thème :
<ul>
<li>les exemples sont un medium de communication simple et naturel, nous les utilisons tout le temps, sans même nous en rendre compte. </li>
<li>les gens qui élaborent les règles métiers abstraites le font généralement à partir d&rsquo;exemples, <strong><font color="#ff0000">qui sont ensuite perdus</font></strong>. Les développeurs doivent souvent <strong>ré-inventer d&rsquo;autres exemples</strong> pour comprendre ce qu&rsquo;il faut faire, ou pour explorer les cas limites. Plus tard les testeurs vont également ré-inventer d&rsquo;autres exemples. Pourquoi ne pas travailler sur des exemples explicites dès le départ, les partager et les faire vivre tout au long du projet ? </li>
<li>les exemples, tests et spécifications sont des notions fortement liées de la manière suivante :          <br /><a href="http://ftp-developpez.com/bruno-orsier/blog/images/PourquoisintresserauBDDBehaviorDrivenDev_B8EA/image.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/PourquoisintresserauBDDBehaviorDrivenDev_B8EA/image_thumb.png" width="304" height="194" /></a>           <br />Par conséquent, les exemples devraient avoir leur place dans nos méthodes de travail. </li>
<li>en comparaisons avec les exigences ou spécifications abstraites, les exemples réalistes laissent beaucoup moins de place pour l&rsquo;incompréhension. </li>
<li>les exemples réalistes nous forcent à penser plus concrètement, et nous évitent de laisser des choses de côté trop vite. </li>
</ul>
</li>
<li>les scénarios du BDD sont exécutables. On ne parle pas ici de tests fonctionnels sous la forme d&rsquo;un document Word, mais de fichiers textes qui peuvent être joués automatiquement et  aussi souvent qu&rsquo;on le souhaite (dans l&rsquo;intégration continue, dans les tests exploratoires). Par conséquent cette approche favorise le <strong>feedback</strong> fréquent que l&rsquo;on recherche dans une approche agile. </li>
<li>les scénarios du BDD constituent des tests d&rsquo;<strong>anti-régression</strong>. </li>
<li>il y a des cas où le côté verbeux et détaillé est clairement un avantage, par exemple quand on travaille avec des équipes offshore avec lesquelles il est difficile de communiquer. </li>
<li>une fois au point, les scénarios textuels du BDD peuvent être modifiés, complétés, enrichis directement par les gens du métier, sans avoir besoin de faire appel à un développeur (lequel reste indispensable pour écrire le &laquo;&nbsp;pont&nbsp;&raquo; initial avec le code de l&rsquo;application testée). </li>
<li>les scénarios du BDD sont compréhensibles par le Product Owner, et peuvent servir de preuve de la bonne réalisation de la fonctionnalité souhaitée. </li>
<li>le BDD sert également à découvrir le modèle métier, à se mettre d&rsquo;accord sur un langage commun. Souvent les professionnels d&rsquo;un domaine utilisent des abus de langage : travailler en BDD permet de lever les ambiguïtés correspondantes.  </li>
</ul>
<p>Pour moi, la raison initiale de mon intérêt pour le BDD est l&rsquo;intérêt que d&rsquo;autres professionnels y portent. Certains travaillent de plus en plus avec ces outils, et pour preuve récente on peut consulter les chiffres suivants sur <a href="http://blog.octo.com/demarches-de-tests-fonctionnels/">ce billet de Christian Blavier</a> :</p>
<blockquote><p>Voici quelques métriques que je viens de réunir dans différents contextes :      <br />- secteur media, sur un projet avec 3 développeurs qui dure depuis 9 mois on a plus de 100 scénarios de test GreenPepper       <br />- secteur media, plusieurs équipes de 3 développeurs, ils ajoutaient en moyenne 5 tests fitnesse par itération de 2 semaines, soit plus d&rsquo;une centaine de tests par an       <br />- encore media, équipe de 7 développeurs avec 2 MOA à plein temps et qui font des tests GP depuis 18 mois : 8743 assertions (dans 122 pages) soit 153 assertions en moyenne par itération d&rsquo;une semaine       <br />- secteur assurance, une équipe de 2 développeurs + 1 MOA sur 6 mois pour tester une plateforme de services (20 web services) : 200 pages de tests Fitnesse et 5000 assertions. Un retour d&rsquo;exp complet est disponible ici : <a href="http://usi2008.universite-du-si.com/WebcastArchi.aspx">http://usi2008.universite-du-si.com/WebcastArchi.aspx</a> (session A10)       <br />- secteur open source <img alt=";-)" src="http://blog.octo.com/wp-includes/images/smilies/icon_wink.gif" /> , octopus microfinance et son harnais de test GP disponible ici : <a href="http://wiki.octopusnetwork.org/display/OPUS/Home">http://wiki.octopusnetwork.org/display/OPUS/Home</a></p>
</blockquote>
<p>De plus je constate que dans nos projets, l&rsquo;incompréhension entre équipe et <em>product owner</em> reste source de gaspillages importants, et se traduit en &laquo;&nbsp;retravail&nbsp;&raquo; sur des histoires utilisateurs que tous pensaient honnêtement bien terminées. La raison : tout simplement des points qui paraissaient tellement évidents pour tous que personne n&rsquo;en avait discuté les détails. Dans certains cas, se forcer à écrire des exemples du comportement attendu aurait fait dissipé instantanément l&rsquo;incompréhension.</p>
</p>
<p>C&rsquo;est pourquoi je suis motivé pour poursuivre l&rsquo;exploration du BDD. Il reste bien sûr à gagner plus d&rsquo;expérience pour comprendre quelle est la place de cet outil dans la réalisation d&rsquo;un logiciel et comment il s&rsquo;articule avec le reste (notamment avec les maquettes d&rsquo;interfaces graphiques &#8211; un autre thème de discussion de la soirée), quand l&rsquo;employer et quand ne pas l&rsquo;employer. En tout cas le BDD apparaît comme un outil complémentaire, qui ne remplace peut-être rien d&rsquo;existant, mais qui probablement peut éviter des erreurs d&rsquo;incompréhension, et donc au final fera gagner du temps à l&rsquo;échelle d&rsquo;un projet.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Spécifications exécutables, illustration de la flexibilité avec GreenPepper</title>
		<link>https://blog.developpez.com/bruno-orsier/p8523/developpement-agile/specifications_executables_illustration_</link>
		<comments>https://blog.developpez.com/bruno-orsier/p8523/developpement-agile/specifications_executables_illustration_#comments</comments>
		<pubDate>Fri, 15 Jan 2010 12:32:58 +0000</pubDate>
		<dc:creator><![CDATA[Bruno Orsier]]></dc:creator>
				<category><![CDATA[BDD]]></category>
		<category><![CDATA[Développement agile]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Pour illustrer un cas (extrême) de la flexibilité du format Given/When/Then que je mentionnais précédemment, voici un exemple GreenPepper (à partir de la version 2.6 GreenPepper supporte l&#8217;écriture de scénarios à la Cucumber &#8211; merci Emmanuel pour l&#8217;information). GreenPepper est tellement flexible que les mots-clés Given/When/Then ne sont même pas obligatoires. Ainsi on peut écrire des scénarios comme celui-ci : Voici le résultat de l&#8217;exécution : Au début l&#8217;absence totale des mots-clés m&#8217;a un peu [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Pour illustrer un cas (extrême) de la flexibilité du format Given/When/Then que <a href="http://blog.developpez.com/bruno-orsier/p8521/bdd/ce-18-janvier-session-du-cara-sur-la-red/">je mentionnais précédemment</a>, voici un exemple <a href="http://www.greenpeppersoftware.com/confluence/display/GPW/Home">GreenPepper</a> (à partir de la version 2.6 <a href="http://www.greenpeppersoftware.com/confluence/display/GPW/Home">GreenPepper</a> supporte l&rsquo;écriture de <a href="http://www.greenpeppersoftware.com/confluence/display/GPW/GreenPepper+2.6+release+notes">scénarios à la Cucumber</a> &#8211; merci Emmanuel pour l&rsquo;information).</p>
<p>GreenPepper est tellement flexible que les mots-clés Given/When/Then ne sont même pas obligatoires. Ainsi on peut écrire des scénarios comme <a href="http://www.greenpeppersoftware.com/confluence/display/GREENPEPPERDEMO/Bank+Scenario">celui-ci</a> :</p>
<p><span id="more-44"></span></p>
<p><a href="http://ftp-developpez.com/bruno-orsier/blog/images/Spcificationsexcutablesillustrationdelaf_BACF/image.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/Spcificationsexcutablesillustrationdelaf_BACF/image_thumb.png" width="554" height="384" /></a> </p>
<p>Voici le résultat de l&rsquo;exécution :</p>
<p><a href="http://ftp-developpez.com/bruno-orsier/blog/images/Spcificationsexcutablesillustrationdelaf_BACF/image_3.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/Spcificationsexcutablesillustrationdelaf_BACF/image_thumb_3.png" width="525" height="352" /></a> </p>
<p>Au début l&rsquo;absence totale des mots-clés m&rsquo;a un peu dérouté. Mais à la réflexion c&rsquo;est la même logique qui me conduit à ne pas utiliser de When dans mes scénarios !</p>
<p>Et vous, qu&rsquo;en pensez-vous ? Est-ce que ce scénario vous paraît facilement compréhensible ?</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Ce 18 janvier, session du CARA sur la rédaction de spécifications exécutables</title>
		<link>https://blog.developpez.com/bruno-orsier/p8521/developpement-agile/ce_18_janvier_session_du_cara_sur_la_red</link>
		<comments>https://blog.developpez.com/bruno-orsier/p8521/developpement-agile/ce_18_janvier_session_du_cara_sur_la_red#comments</comments>
		<pubDate>Fri, 15 Jan 2010 10:00:46 +0000</pubDate>
		<dc:creator><![CDATA[Bruno Orsier]]></dc:creator>
				<category><![CDATA[BDD]]></category>
		<category><![CDATA[Développement agile]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Le dojo du 5 janvier à Grenoble concernait l&#8217;exploration de l&#8217;articulation entre TDD et BDD, sur la base d&#8217;un exemple que j&#8217;avais proposé. L&#8217;exemple s&#8217;appuie sur la problématique de la calibration des instruments scientifiques, problématique que nous devons souvent traiter dans nos logiciels. L&#8217;exemple est donc tout à fait concret et réaliste, implique des calculs assez rapides à programmer (comme la régression linéaire) qu&#8217;il serait néanmoins judicieux de traiter en TDD. De plus il comporte [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Le <a href="http://clubagile.org/2010/01/18e-session-du-coding-dojo/">dojo du 5 janvier</a> à Grenoble concernait l&rsquo;exploration de l&rsquo;articulation entre TDD et BDD, sur la base d&rsquo;un exemple que j&rsquo;avais proposé. L&rsquo;exemple s&rsquo;appuie sur la problématique de la <a href="http://en.wikipedia.org/wiki/Calibration_curve">calibration</a> des instruments scientifiques, problématique que nous devons souvent traiter dans nos logiciels. L&rsquo;exemple est donc tout à fait concret et réaliste, implique des calculs assez rapides à programmer (comme la <a href="http://fr.wikipedia.org/wiki/R%C3%A9gression_lin%C3%A9aire">régression linéaire</a>) qu&rsquo;il serait néanmoins judicieux de traiter en TDD. De plus il comporte des spécifications trompeusement simples (source de diverses incompréhensions entre développeurs et utilisateurs) que le BDD pourrait certainement traiter. Le BDD devrait d&rsquo;ailleurs permettre d&rsquo;élaborer un modèle métier satisfaisant. C&rsquo;est pourquoi cet exemple me paraît bien approprié et j&rsquo;espère que nous le poursuivrons dans de futures séances. </p>
<p>Durant le dojo il y a eu des questions sur la manière dont j&rsquo;avais rédigé les spécifications en Cucumber, ce qui est normal car le format Given/When/Then offre beaucoup de flexibilité. Rien ne vous force à utiliser When par exemple, ou à limiter les tests à des sections Then. En ce qui me concerne, j&rsquo;ai l&rsquo;habitude quand je code de faire les calculs au moment où l&rsquo;on demande les résultats (ce qui est possible quand il y a peu de données, et évite de gérer des questions de cohérence données/résultats). Donc je n&rsquo;éprouve pas trop le besoin de mentionner un déclenchement avec un When par exemple. Mais c&rsquo;est probablement un cas où mon style et mes habitudes de programmation influencent directement sur la rédaction des spécifications exécutables, ce qui n&rsquo;est guère souhaitable &#8211; dans le BDD nous souhaitons justement éviter de polluer les spécifications par des concepts très liés à l&rsquo;implémentation, pour rester focalisés sur le modèle métier.</p>
<p><span id="more-43"></span></p>
<p>Ces questions rejoignent mes propres interrogations, car je trouve encore difficile, face à une feuille blanche, de me lancer dans l&rsquo;écriture de spécifications. Il serait de plus souhaitable, sur un exemple donné, de comparer diverses manières d&rsquo;utiliser le format Given/When/Then, pour déterminer ce qui est le plus clair, pour voir ce qui permet d&rsquo;arriver à une meilleure collaboration et compréhension entre plusieurs personnes, et pour voir comment s&rsquo;élabore un langage commun au sujet d&rsquo;une application. C&rsquo;est pourquoi nous allons utiliser la prochaine <a href="http://clubagile.org/2010/01/recontre-autour-de-lagilite-a-grenoble-le-18-janvier-2010/">réunion du CARA, ce lundi 18 janvier</a> (de 18h45 à 21h) pour faire un atelier concret sur la question. </p>
<p>Si le sujet vous intéresse, <strong>venez apprendre avec nous</strong> ! Il n&rsquo;y aura pas de programmation a priori, simplement du travail sur papier ou tableau. Pas de présentation théorique non plus ! Nous démarrerons la séance en montrant des exemples concrets de scénarios pour ceux qui ne sont pas familiers avec la syntaxe.</p>
<p>A titre d&rsquo;illustration de mon propos sur Given/When/Then et l&rsquo;absence de When, voici les scénarios Cucumber que nous avons utilisés le 5 janvier. Le 18 janvier j&rsquo;apporterai un autre exemple sur une application plus &laquo;&nbsp;grand public&nbsp;&raquo;, un logiciel de comptage de calories &#8211; sujet intéressant pour ceux qui viennent de prendre de bonnes résolutions !</p>
<p> </p>
<p><a href="http://ftp-developpez.com/bruno-orsier/blog/images/SessionduCARAsurlardactiondebonstests_8FB4/image.png" target="_blank"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/SessionduCARAsurlardactiondebonstests_8FB4/image_thumb.png" width="548" height="826" /></a></p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Behavior Driven Development avec Cuke4Nuke</title>
		<link>https://blog.developpez.com/bruno-orsier/p8444/developpement-agile/behavior_driven_development_avec_cuke4nu</link>
		<comments>https://blog.developpez.com/bruno-orsier/p8444/developpement-agile/behavior_driven_development_avec_cuke4nu#comments</comments>
		<pubDate>Wed, 09 Dec 2009 12:23:30 +0000</pubDate>
		<dc:creator><![CDATA[Bruno Orsier]]></dc:creator>
				<category><![CDATA[BDD]]></category>
		<category><![CDATA[Développement agile]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Pour conclure mon exploration des moyens de pratiquer le BDD en .NET, il me restait à examiner Cuke4Nuke, l&#8217;équivalent de Cuke4Duke de Java. C&#8217;est chose faite, et ce billet montre comment installer tout ce qu&#8217;il faut pour arriver à faire tourner l&#8217;exemple du jeu du pendu qui m&#8217;a servi dans les billets précédents. J&#8217;ai suivi les instructions de cette page How to Install Cuke4Nuke :       Par contre j&#8217;avais Ruby 1.9, cela n&#8217;a [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Pour conclure mon exploration des moyens de pratiquer le BDD en .NET, il me restait à examiner Cuke4Nuke, l&rsquo;équivalent de Cuke4Duke de Java. C&rsquo;est chose faite, et ce billet montre comment installer tout ce qu&rsquo;il faut pour arriver à faire tourner l&rsquo;exemple du jeu du pendu qui m&rsquo;a servi dans les billets précédents.</p>
<p><span id="more-42"></span></p>
<p>J&rsquo;ai suivi les instructions de cette page <a href="http://wiki.github.com/richardlawrence/Cuke4Nuke">How to Install Cuke4Nuke</a> :</p>
<p> </p>
<p><a href="http://ftp-developpez.com/bruno-orsier/blog/images/ab3f1089bfde_E26C/image.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/ab3f1089bfde_E26C/image_thumb.png" width="427" height="425" /></a>  </p>
<p> </p>
<p>Par contre j&rsquo;avais Ruby 1.9, cela n&rsquo;a pas fonctionné (étape 6, installation de cuke4nuke) :</p>
<p><a href="http://ftp-developpez.com/bruno-orsier/blog/images/ab3f1089bfde_E26C/image_3.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/ab3f1089bfde_E26C/image_thumb_3.png" width="565" height="220" /></a> </p>
<p>donc il faut bien partir sur Ruby 1.8.6. Problème, la page <a href="http://wiki.github.com/richardlawrence/Cuke4Nuke">How to Install Cuke4Nuke</a> m&rsquo;a pointé sur le téléchargement d&rsquo;un installateur ruby186-26.exe, sur lequel Cuke4Nuke ne s&rsquo;installe pas bien du tout, apparemment parce que RubyGems ne fonctionne pas bien dans cette version 186-26. Après une bonne heure passée à chercher des informations sur des messages cryptiques, un forum m&rsquo;a fait découvrir un installeur <a href="http://files.rubyforge.vm.bytemark.co.uk/rubyinstaller/ruby186-27_rc2.exe">ruby186-27_rc2.exe</a> sur cette <a href="http://rubyforge.org/frs/?group_id=167&amp;release_id=28426">page</a>. Eh bien les instructions d&rsquo;installation ne fonctionnent qu&rsquo;avec cette version !</p>
<p>Ensuite j&rsquo;ai suivi les explications &laquo;&nbsp;How to use it&nbsp;&raquo; sur la page <a href="http://wiki.github.com/richardlawrence/Cuke4Nuke">How to Install Cuke4Nuke</a>, mais j&rsquo;ai encore eu quelques ennuis d&rsquo;installation. A l&rsquo;exécution, cuke4nuke ne reconnaissait pas le fichier .wire qui fait le lien avec .NET, ce que j&rsquo;ai fini par découvrir grâce à l&rsquo;option -v (pour verbose) :</p>
<p><a href="http://ftp-developpez.com/bruno-orsier/blog/images/ab3f1089bfde_E26C/image_4.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/ab3f1089bfde_E26C/image_thumb_4.png" width="804" height="172" /></a> </p>
<p>J&rsquo;en ai déduit que cela indique qu&rsquo;il manque &lsquo;&nbsp;&raquo;json&nbsp;&raquo;, à installer de la manière suivante :</p>
<p><a href="http://ftp-developpez.com/bruno-orsier/blog/images/ab3f1089bfde_E26C/image_5.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/ab3f1089bfde_E26C/image_thumb_5.png" width="515" height="89" /></a> </p>
<p>Et j&rsquo;ai eu de la chance, car ensuite Cuke4Nuke a fonctionné comme attendu :</p>
<p><a href="http://ftp-developpez.com/bruno-orsier/blog/images/ab3f1089bfde_E26C/image_6.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/ab3f1089bfde_E26C/image_thumb_6.png" width="795" height="571" /></a> </p>
<p>Bien sûr j&rsquo;ai dû réaliser un pont spécifique, avec le code ci-dessous dans ma solution :</p>
<pre class="code"><span style="color: blue">using </span>Cuke4Nuke.Framework;
<span style="color: blue">using </span>NUnit.Framework;

<span style="color: blue">namespace </span>PenduAvecCuke
{
    <span style="color: blue">public class </span><span style="color: #2b91af">Scenarios
    </span>{
        <span style="color: blue">private </span><span style="color: #2b91af">Game </span>game;

        [<span style="color: #2b91af">Given</span>(<span style="color: #a31515">@"^the secret word (.*) and the remaining count (\d+)$"</span>)]
        <span style="color: blue">public void </span>InitializeGame(<span style="color: blue">string </span>secret, <span style="color: blue">int </span>remaining)
        {
            game = <span style="color: blue">new </span><span style="color: #2b91af">Game</span>(secret, remaining);
        }

        [<span style="color: #2b91af">Given</span>(<span style="color: #a31515">@"^the user has already proposed the letters (.*)$"</span>)]
        <span style="color: blue">public void </span>ProposeLetters(<span style="color: blue">string </span>letters)
        {
            <span style="color: blue">foreach </span>(<span style="color: blue">char </span>c <span style="color: blue">in </span>letters)
            {
                game.ProposedLetter = c;
            }
        }

        [<span style="color: #2b91af">When</span>(<span style="color: #a31515">@"^the user proposes the letter (.*)$"</span>)]
        <span style="color: blue">public void </span>ProposeLetter(<span style="color: blue">char </span>letter)
        {
            game.ProposedLetter = letter;
        }

        [<span style="color: #2b91af">Then</span>(<span style="color: #a31515">@"the game displays (.*) and the remaining count is (\d+)$"</span>)]
        <span style="color: blue">public void </span>DisplayResult(<span style="color: blue">string </span>display, <span style="color: blue">int </span>remaining)
        {
            <span style="color: #2b91af">Assert</span>.That(game.DisplayedWord, <span style="color: #2b91af">Is</span>.EqualTo(display));
            <span style="color: #2b91af">Assert</span>.That(game.Remaining, <span style="color: #2b91af">Is</span>.EqualTo(remaining));
        }

    }</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>C&rsquo;est donc très similaire à la classe équivalente dans <a href="http://blog.developpez.com/bruno-orsier/p8428/bdd/nbehave-a-la-cucumber/">mon exemple avec NBehave</a>. </p>
<p>La grande différence, si j&rsquo;ai bien tout suivi, c&rsquo;est que dans le cas de Cuke4Nuke, Cucumber (sous Ruby 1.8) tourne de manière cachée, vous permettant de l&rsquo;utiliser sans écrire une seule ligne de Ruby. Cuke4Nuke sert en fait d&rsquo;intermédiaire entre Cucumber/Ruby et la DLL .NET, en reroutant les appels de Cucumber vers la DLL.</p>
<p>Dans le cas de NBehave, c&rsquo;est NBehave qui fait tout, et Ruby n&rsquo;est pas du tout impliqué. </p>
<p>En conclusion, pas mal de difficultés d&rsquo;installation liées à la version de Ruby, et des instructions incomplètes. C&rsquo;est surement facilement surmontable pour quelqu&rsquo;un qui connaît bien Ruby, mais ce n&rsquo;est pas mon cas et cela m&rsquo;a couté environ 4 heures de travail juste pour arriver au bout de cet exemple.</p>
<p>Comme j&rsquo;ai passé ces derniers jours le nez collé à la fenêtre de commandes, j&rsquo;ai du mal à prendre du recul, et à donner autre chose que des impressions. A première vue, je ne saisis pas trop l&rsquo;intérêt de toute la machinerie Cuke4Nuke, disons par rapport à la simplicité d&rsquo;une approche native comme NBehave. Si le but c&rsquo;est de quand même faire du Ruby dans un contexte .NET, alors autant passer en <a href="http://blog.developpez.com/bruno-orsier/p8440/bdd/cucumber-avec-ironruby-ca-marche/">Cucumber sous IronRuby</a> ? En tout cas vous avez le choix, tout fonctionne.</p>
<p>Et sinon, si l&rsquo;on veut se focaliser sur la maîtrise du BDD, ca vaut probablement le coup de travailler directement en Cucumber sous Ruby, au moins le temps de bien maîtriser les concepts.</p>
<p>Et vous, qu&rsquo;en pensez-vous ?</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Cucumber avec IronRuby, ca marche !</title>
		<link>https://blog.developpez.com/bruno-orsier/p8440/developpement-agile/cucumber_avec_ironruby_ca_marche</link>
		<comments>https://blog.developpez.com/bruno-orsier/p8440/developpement-agile/cucumber_avec_ironruby_ca_marche#comments</comments>
		<pubDate>Tue, 08 Dec 2009 09:31:48 +0000</pubDate>
		<dc:creator><![CDATA[Bruno Orsier]]></dc:creator>
				<category><![CDATA[BDD]]></category>
		<category><![CDATA[Développement agile]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Je poursuis mon exploration des différentes possiblités de faire du Behavior Driven Development sur plate-forme .NET. Après avoir examiné l&#8217;approche NBehave, je vais voir comment utiliser plus directement Cucumber (une des principales références en BDD, avec une communauté très active). Cucumber étant programmé en Ruby, on peut donc utiliser IronRuby, l&#8217;implémentation de Ruby pour .NET. Dans ce billet je décris l&#8217;installation de IronRuby, celle de Cucumber sous IronRuby, et je montrerai l&#8217;exécution de mon exemple [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Je poursuis mon exploration des différentes possiblités de faire du Behavior Driven Development sur plate-forme .NET. Après avoir <a href="http://blog.developpez.com/bruno-orsier/p8428/bdd/nbehave-a-la-cucumber/" target="_blank">examiné l&rsquo;approche NBehave</a>, je vais voir comment utiliser plus directement <a href="http://cukes.info/" target="_blank">Cucumber</a> (une des principales références en BDD, avec une communauté très active). Cucumber étant programmé en <a href="http://www.ruby-lang.org/fr/" target="_blank">Ruby</a>, on peut donc utiliser <a href="http://ironruby.net/" target="_blank">IronRuby</a>, l&rsquo;implémentation de Ruby pour .NET. Dans ce billet je décris l&rsquo;installation de IronRuby, celle de Cucumber sous IronRuby, et je montrerai l&rsquo;exécution de mon exemple prédécent dans ce nouvel environnement. Faire tourner Cucumber sous IronRuby a été un peu laborieux pour moi, donc j&rsquo;essaierai très prochainement une autre approche, celle de <a href="http://blog.mattwynne.net/2009/12/07/cuke4nuke-cucumber-for-net/">Cuke4Nuke &#8211; Cucumber for .NET</a> qui promet d&rsquo;être plus directe.</p>
<p>
<span id="more-41"></span></p>
<h1>Installer IronRuby</h1>
<ol>
<li>télécharger IronRuby depuis la page du <a href="http://ironruby.net/" target="_blank">projet</a>. Dans mon cas j&rsquo;ai pris la <a href="http://ironruby.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=35312" target="_blank">version 0.9.3 sur cette page</a>. Attention, <strong>ne pas prendre le fichier .MSI</strong>, cet installateur installe obligatoirement IronRuby dans C:\Program Files, et j&rsquo;ai découvert péniblement que l&rsquo;installation de Cucumber ne tolère pas bien les espaces dans les noms de chemins ! Donc prenez bien le fichier .ZIP, que vous allez extraire dans par exemple C:\ironruby. </li>
<li>insérer C:\ironruby\bin dans la variable d&rsquo;environnement système PATH de Windows. Cela peut être l&rsquo;occasion de télécharger l&rsquo;excellent utilitaire <a href="http://www.rapidee.com" target="_blank">RapidEE</a> qui offre un accès bien plus pratique à ces variables.</li>
<li>lancer une fenêtre de commande DOS (ou mieux PowerShell), taper &laquo;&nbsp;ir&nbsp;&raquo;, et vérifier que l&rsquo;on obtient bien le prompt IronRuby comme ci-dessous </li>
</ol>
<p><a href="http://ftp-developpez.com/bruno-orsier/blog/images/98d2b6d96b5e_9A4C/image.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/98d2b6d96b5e_9A4C/image_thumb.png" width="505" height="130" /></a> </p>
<p>Vous pouvez alors vérifier que vous êtes réellement dans le monde .NET. Voici par exemple le chargement puis l&rsquo;utilisation de la classe Game développée à l&rsquo;occasion des billets précédents :</p>
<p><a href="http://ftp-developpez.com/bruno-orsier/blog/images/98d2b6d96b5e_9A4C/image4.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/98d2b6d96b5e_9A4C/image4_thumb.png" width="501" height="322" /></a> </p>
<p>Magique, non ? J&rsquo;ai trouvé comment faire le chargement de l&rsquo;assembly .NET grâce à cette vidéo <a href="http://www.softdevtube.com/2009/11/25/using-cucumber-to-test-clr-assembly/" target="_blank">Using Cucumber to test CLR assembly</a>.</p>
<h1>Faire tourner Cucumber sous IronRuby</h1>
<p>Cette partie a été la plus laborieuse pour moi. Je me suis inspiré des différents articles cités en référence plus bas. Voici comment j&rsquo;ai procédé.</p>
<p>Dans la fenêtre de commandes, taper &laquo;&nbsp;igem install -bindir c:\ironruby\bin cucumber rspec&nbsp;&raquo;, cela devrait donner quelque chose comme :</p>
<p><a href="http://ftp-developpez.com/bruno-orsier/blog/images/98d2b6d96b5e_9A4C/image_3.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/98d2b6d96b5e_9A4C/image_thumb_3.png" width="554" height="419" /></a> </p>
<p>à chaque fois j&rsquo;ai eu des erreurs relatives à la documentation comme ci-dessus, mais elles ne paraissent pas bloquantes. Pour éviter ces erreurs et gagner du temps sur l&rsquo;installation, on peut éventuellement utilise les options &laquo;&nbsp;&#8211;no-rdoc &#8211;no-ri&nbsp;&raquo; sur la ligne de commandes.</p>
<p>Ensuite il faut créer les fichiers<strong> icucumber.bat</strong> et <strong>icucumber</strong> comme indiqué ci-dessous (image tirée de cette <a href="http://wiki.github.com/aslakhellesoy/cucumber/ironruby-and-net">page</a>) :</p>
<p><a href="http://wiki.github.com/aslakhellesoy/cucumber/ironruby-and-net"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/98d2b6d96b5e_9A4C/image_4.png" width="554" height="309" /></a> </p>
<p>On peut alors vérifier que tout cela fonctionne en tapant &laquo;&nbsp;icucumber -help&nbsp;&raquo;.</p>
<h1>Tester le jeu</h1>
<p>Dans un dossier <strong>pendu\features</strong>, j&rsquo;ai créé trois fichiers textes :</p>
<p><a href="http://ftp-developpez.com/bruno-orsier/blog/images/98d2b6d96b5e_9A4C/image_5.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/98d2b6d96b5e_9A4C/image_thumb_4.png" width="554" height="116" /></a> </p>
<p>qui contiennent mes scénarios (je n&rsquo;ai pas pu garder un seul fichier comme précédemment, cela n&rsquo;a pas l&rsquo;air bien supporté par (i)cucumber contrairement à NBehave).</p>
<p>Le dossier <strong>steps_definitions</strong> contiendra le fichier <strong>pendu_steps.rb</strong> qui me servira à réaliser le pont (en Ruby) vers ma classe C#.</p>
<p>La première exécution de icucumber me propose un modèle pour les fragments de code qui font faire le pont, c&rsquo;est l&rsquo;une des caractéristiques bien sympathiques de Cucumber :</p>
<p><a href="http://ftp-developpez.com/bruno-orsier/blog/images/98d2b6d96b5e_9A4C/image_6.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/98d2b6d96b5e_9A4C/image_thumb_5.png" width="554" height="156" /></a> </p>
<p>On voit que le modèle comporte des expressions régulières, il suffit de les affiner un peu,  d&rsquo;appeler le code C# avec les arguments que l&rsquo;on extrait des expressions régulières, et de faire les vérifications nécessaires dans les parties &laquo;&nbsp;Then&nbsp;&raquo;.</p>
<p>Voici le fichier <strong>pendu_steps.rb</strong>, réalisé à partir des fragments suggérés ci-dessus :</p>
<p><a href="http://ftp-developpez.com/bruno-orsier/blog/images/98d2b6d96b5e_9A4C/image_9.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/98d2b6d96b5e_9A4C/image_thumb_8.png" width="729" height="354" /></a> </p>
<p>Ma principale difficulté a été d&rsquo;arriver à séparer la chaîne letters en caractères individuels. En effet letters.each rend la chaîne elle-même, et curieusement, aucune erreur ne se produit quand on affecte une chaîne à game.ProposedLetter, qui est pourtant définie de la manière suivante :</p>
<pre class="code"><span style="color: blue">private char </span>proposedLetter;<br />
<br />
<span style="color: blue">public char </span>ProposedLetter<br />
{<br />
    <span style="color: blue">set<br />
    </span>{<br />
        proposedLetter = <span style="color: blue">value</span>;<br />
        ComputeResult();<br />
    }<br />
}</pre>
<p>
<a href="http://11011.net/software/vspaste"></a></p>
<p>Le test ci-dessous montre que seule la première lettre de la chaîne est bien prise en compte.</p>
<p><a href="http://ftp-developpez.com/bruno-orsier/blog/images/98d2b6d96b5e_9A4C/image_7.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/98d2b6d96b5e_9A4C/image_thumb_6.png" width="469" height="209" /></a> </p>
<p>Donc voilà sans doute une première subtilité de l&rsquo;interopérabilité de IronRuby et de C#, probablement normale, mais qui m&rsquo;a un peu dérouté.</p>
<p>Cette petite difficulté résolue grâce à la méthode &laquo;&nbsp;split&nbsp;&raquo;, voici le résultat de l&rsquo;exécution de icucumber :</p>
<p><a href="http://ftp-developpez.com/bruno-orsier/blog/images/98d2b6d96b5e_9A4C/image_8.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/98d2b6d96b5e_9A4C/image_thumb_7.png" width="554" height="521" /></a> </p>
<p>Tout fonctionne bien, ca valait le coup de persévérer ! Seul l&rsquo;affichage en couleur n&rsquo;est pas au point, d&rsquo;où l&rsquo;option -no-color.</p>
<p>En conclusion, arriver à faire marcher cet exemple a été un peu laborieuse pour moi, surtout pour faire tourner Cucumber sous IronRuby. Toutefois IronRuby a l&rsquo;air d&rsquo;être un projet très actif, et s&rsquo;approche d&rsquo;une version officielle 1.0. Il est donc probable que les quelques difficultés rencontrées vont bientôt disparaître.</p>
<h1>Références</h1>
<p>- <a href="http://wiki.github.com/aslakhellesoy/cucumber/ironruby-and-net">Installing Cucumber with IronRuby 0.9.2</a></p>
<p>- <a href="http://blog.thomaslundstrom.com/2009/08/on-running-cucumber-under-ironruby-09.html" target="_blank">On running Cucumber under IronRuby 0.9</a>, de Thomas Lundström.</p>
<p>- <a href="http://blog.webintellix.com/2009/10/how-to-use-cucumber-with-net-and-c.html" target="_blank">How-to: Use Cucumber with .NET and C# under IronRuby</a>, de Rupak Ganguly.</p>
<p>- <a href="http://hotgazpacho.org/2009/06/cucumber-and-ironruby-it-runs/" target="_blank">Cucumber and IronRuby: It Runs!</a></p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>NBehave à la Cucumber</title>
		<link>https://blog.developpez.com/bruno-orsier/p8428/developpement-agile/nbehave_a_la_cucumber</link>
		<comments>https://blog.developpez.com/bruno-orsier/p8428/developpement-agile/nbehave_a_la_cucumber#comments</comments>
		<pubDate>Fri, 04 Dec 2009 10:47:36 +0000</pubDate>
		<dc:creator><![CDATA[Bruno Orsier]]></dc:creator>
				<category><![CDATA[BDD]]></category>
		<category><![CDATA[Développement agile]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Un lecteur m&#8217;ayant indiqué qu&#8217;une nouvelle version de NBehave (0.4.5) était disponible depuis une semaine, j&#8217;ai repris l&#8217;exemple du jeu du pendu pour voir comment on écrivait maintenant les tests et le code de &#171;&#160;pontage&#160;&#187; (la façon dont j&#8217;ai procédé jusqu&#8217;à présent étant obsolète). L&#8217;expérience est assez satisfaisante, on procède comme avec Cucumber. J&#8217;ai donc écrit mes scenarios (purement textuels) puis écrit une classe C# pour faire le pont avec le code de &#171;&#160;production&#160;&#187;, ma [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Un lecteur m&rsquo;ayant indiqué qu&rsquo;une nouvelle version de NBehave (0.4.5) était disponible depuis une semaine, j&rsquo;ai repris l&rsquo;exemple du jeu du pendu pour voir comment on écrivait maintenant les tests et le code de &laquo;&nbsp;pontage&nbsp;&raquo; (la façon dont j&rsquo;ai procédé jusqu&rsquo;à présent étant obsolète). L&rsquo;expérience est assez satisfaisante, on procède comme avec Cucumber. J&rsquo;ai donc écrit mes scenarios (purement textuels) puis écrit une classe C# pour faire le pont avec le code de &laquo;&nbsp;production&nbsp;&raquo;, ma classe <em>Game</em>. Ici j&rsquo;ai réutilisé la classe résultant de mes essais précédents pour aller vite, il aurait été préférable de se laisser guider par les tests pour découvrir petit à petit cette classe &#8211; c&rsquo;est ce que vous conseille si vous voulez tenter l&rsquo;expérience. Ci-dessous je présente les scénarios, puis la classe de pontage.</p>
<p><span id="more-38"></span></p>
<p>Tout d&rsquo;abord les scénarios, tous écrits dans un fichier texte appelé <em>pendu.scenario</em> :</p>
<pre class="code">Story: handle one letter

Scenario: scenario1 (one wrong letter)

    Given the secret word SANGLIER and the remaining count 6
    When the user proposes the letter Z
    Then the game displays ******** and the remaing count is 5
    
Scenario: scenario2 (one good letter)

    Given the secret word SANGLIER and the remaining count 6
    When the user proposes the letter A
    Then the game displays *A****** and the remaing count is 6
    
Story: handle two successive letters

Scenario: scenario3 (a good letter followed by a good letter)
    Given the secret word SANGLIER and the remaining count 6
    Given the user has already proposed the letters A
    When the user proposes the letter S
    Then the game displays SA****** and the remaing count is 6
    
Scenario: scenario4 (a wrong letter followed by a good letter)
    Given the secret word SANGLIER and the remaining count 6
    Given the user has already proposed the letters Z
    When the user proposes the letter S
    Then the game displays S******* and the remaing count is 5    
    
Story: handle the end of the game

Scenario: scenario5 (lost game)
    Given the secret word SANGLIER and the remaining count 6
    Given the user has already proposed the letters ZZZZZZ
    Then the game displays ******** and the remaing count is 0    
    
Scenario: scenario6 (winning game)
    Given the secret word SANGLIER and the remaining count 6
    Given the user has already proposed the letters XYZSANGLIER
    Then the game displays SANGLIER and the remaing count is 3    
   </pre>
<p>A ce stage de votre lecture, il serait intéressant de voir ce que vous pensez de cette information. En tant que développeur, avez-vous assez d&rsquo;informations pour programmer un jeu qui fonctionne ? En tant que testeur, avez-vous des idées sur d&rsquo;autres scénarios que vous pourriez ajouter ? Est-ce que tout le monde comprend bien de quel jeu on parle ?</p>
<p><strong>Au fait, testeur, notez bien que vous n&rsquo;avez pas besoin d&rsquo;un autre outil que Notepad si vous voulez modifier ou compléter ces scénarios.</strong></p>
<p>Maintenant, un peu de cuisine informatique, il faut bien interpréter ce fichier texte. Pour cela, dans NBehave il faut programmer une classe portant l&rsquo;attribut <font color="#ff0000">ActionSteps</font>, comme ci-dessous :</p>
<pre class="code">[<span style="color: #2b91af">ActionSteps</span>]
<span style="color: blue">public class </span><span style="color: #2b91af">Scenarios
</span>{
    <span style="color: blue">private </span><span style="color: #2b91af">Game </span>game;

    [<span style="color: #2b91af">Given</span>(<span style="color: #a31515">"the secret word $secret and the remaining count $remaining"</span>)]
    <span style="color: blue">public void </span>InitializeGame(<span style="color: blue">string </span>secret, <span style="color: blue">int </span>remaining)
    {
        game = <span style="color: blue">new </span><span style="color: #2b91af">Game</span>(secret, remaining);    
    }

    [<span style="color: #2b91af">Given</span>(<span style="color: #a31515">"the user has already proposed the letters $letters"</span>)]
    <span style="color: blue">public void </span>ProposeLetters(<span style="color: blue">string </span>letters)
    {
        <span style="color: blue">foreach </span>(<span style="color: blue">char </span>c <span style="color: blue">in </span>letters)
        {
            game.ProposedLetter = c;
        }
    }

    [<span style="color: #2b91af">When</span>(<span style="color: #a31515">"the user proposes the letter $letter"</span>)]
    <span style="color: blue">public void </span>ProposeLetter(<span style="color: blue">char </span>letter)
    {
        game.ProposedLetter = letter;
    }

    [<span style="color: #2b91af">Then</span>(<span style="color: #a31515">"the game displays $display and the remaing count is $remaining"</span>)]
    <span style="color: blue">public void </span>DisplayResult(<span style="color: blue">string </span>display, <span style="color: blue">int </span>remaining)
    {
        game.DisplayedWord.ShouldEqual(display);
        game.Remaining.ShouldEqual(remaining);
    }
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>Oups, il y a un peu de duplication dans ma classe (violation du principe <a href="http://bruno-orsier.developpez.com/principes/dry/" target="_blank">DRY</a>) &#8211; il faudra factoriser le code entre ProposedLetters et ProposeLetter par exemple.</p>
<p>Sinon vous constatez sans doute que le principe de cette classe est facile à comprendre, et découle assez naturellement des tests. Avec NBehave, je n&rsquo;ai pas vu de moyen de générer partiellement ce code comme le fait Cucumber, mais je suppose que ce sera résolu ultérieurement.</p>
<p>Voici la sortie de NBehave:</p>
<p><a href="http://ftp-developpez.com/bruno-orsier/blog/images/bd9c08b0037b_9A29/image.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://ftp-developpez.com/bruno-orsier/blog/images/bd9c08b0037b_9A29/image_thumb.png" width="516" height="525" /></a> </p>
<p>Cette sortie illustre le seul problème que j&rsquo;ai rencontré, <strong>les titres de stories ne sont pas affichés correctement par rapport à leurs scénarios, il y a un décalage</strong>.</p>
<p>En conclusion, une expérience très positive, et je suis content de voir que NBehave est toujours bien vivant !</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
