<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Jaros&#322;aw Zabie&#322;&#322;o - BLOG: Tag metodologia</title>
    <link>http://blog.zabiello.com/articles/tag/metodologia</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>moje notatki, linki, komentarze</description>
    <item>
      <title>Shoulda - pozbycie si&#281; magii RSpec'a</title>
      <description>&lt;p&gt;Od jakiego&#347; czasu w kr&#281;gach Ruby on Rails mo&#380;na zauwa&#380;y&#263; przesuni&#281;cie paradygmatu w zakresie metodologii testowania kodu. Popularyzowane podej&#347;cie &lt;a href="http://en.wikipedia.org/wiki/Test-driven_development"&gt;&lt;span class="caps"&gt;TDD&lt;/span&gt;&lt;/a&gt; (Test Driven Development) zostaje wypierane przez &lt;a href="http://en.wikipedia.org/wiki/Behavior_driven_development"&gt;&lt;span class="caps"&gt;BDD&lt;/span&gt;&lt;/a&gt; (Behaviour Driven Development). Jedn&#261; z bardziej promowanych bibliotek jest RSpec. Mimo &#380;e kusi sk&#322;adni&#261; przypominaj&#261;c&#261; naturalny j&#281;zyk angielski, pr&#243;ba wykorzystania &lt;a href="http://rspec.rubyforge.org/"&gt;RSPec&lt;/a&gt; w rzeczywistym projekcie szybko mo&#380;e sta&#263; si&#281; co najmniej k&#322;opotliwe.&lt;/p&gt;


	&lt;p&gt;RSpec aby wygl&#261;da&#322; tak &#322;adnie jak wygl&#261;da, wykorzystuje dynamik&#281; i specyficzne w&#322;a&#347;ciwo&#347;ci Rubiego. Ruby pozwala opuszcza&#263; nawiasy w metodach, niezauwa&#380;enie otwiera&#263; i modyfikowa&#263; klasy swoich bibliotek (w tym wbudowanych i standardowych) oraz og&#243;lnie dosy&#263; dobrze nadaje si&#281; do tworzenia nowych j&#281;zyk&#243;w do specyficznych zada&#324; (&lt;a href="http://en.wikipedia.org/wiki/Domain-specific_programming_language"&gt;&lt;span class="caps"&gt;DSL&lt;/span&gt;&lt;/a&gt;, Domain Specific Language). Innymi s&#322;owy, cen&#261; za korzystanie ze sk&#322;adni RSpec jest konieczno&#347;&#263; opanowania tego nowego j&#281;zyka. I tu zaczynaj&#261; si&#281; schody&amp;#8230;&lt;/p&gt;


	&lt;p&gt;Dokumentacja do RSpec jest najdelikatniej m&#243;wi&#261;c, niekompletna. Przyk&#322;ad&#243;w u&#380;ycia RSpec trzeba szuka&#263; po ca&#322;ym internecie. Dokumentacja wygenerowana z kodu &#378;r&#243;d&#322;owego &lt;span class="caps"&gt;API&lt;/span&gt; do RSpec jest r&#243;wnie&#380; s&#322;abej jako&#347;ci. Brakuje przyk&#322;ad&#243;w, brakuje nawet wzmianki co do niekt&#243;rych metod, jakie s&#261; u&#380;ywane. Np. we&#378;my taki prosty przyk&#322;ad:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;response&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;have_text&lt;/span&gt;&lt;span class="punct"&gt;(/&lt;/span&gt;&lt;span class="regex"&gt;My String&lt;/span&gt;&lt;span class="punct"&gt;/)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Pr&#243;ba znalezienia czego&#347; sensownego na stronie z &lt;a href="http://rspec.rubyforge.org/rdoc/index.html"&gt;&lt;span class="caps"&gt;API&lt;/span&gt; RSpec&amp;#8217;a&lt;/a&gt; jest beznadziejna. Nie ma nic napisane o metodzie &amp;#8220;response&amp;#8221;, nie ma nic o metodzie &amp;#8220;have_text&amp;#8221; ani w og&#243;le o tym, co mo&#380;na przekaza&#263; do metody should(). Po prostu pojawia si&#281; co&#347; niczym kr&#243;lik z kapelusza magika. I tak jest z wieloma elementami sk&#322;adni RSpec&amp;#8217;a. S&#261; jakie&#347; pojedy&#324;cze elementy, ale nie wiadomo kt&#243;re, i jak je &#322;&#261;czy&#263; ze sob&#261;. &lt;strong&gt;Je&#347;li Ruby ma zbytnie sk&#322;onno&#347;ci do &amp;#8220;magii&amp;#8221;, to RSpec magia do kwadratu.&lt;/strong&gt; Co&#347; si&#281; pojawia i znika nie wiadomo sk&#261;d, ani dlaczego. To jest po prostu chore. Po wielu dniach takiej walki z RSpec doszed&#322;em do wniosku, &#380;e to droga donik&#261;d. Tylko, &#380;e z drugiej strony, cofni&#281;cie si&#281; z &lt;span class="caps"&gt;BDD&lt;/span&gt; do &lt;span class="caps"&gt;TDD&lt;/span&gt; te&#380; nie brzmi atrakcyjnie.&lt;/p&gt;


	&lt;p&gt;Czy jest zatem jakie&#347; wyj&#347;cie po&#347;rednie? Tzn. rozwi&#261;zanie kt&#243;re nie rezygnuj&#261;c z elegancji &lt;span class="caps"&gt;BDD&lt;/span&gt; by&#322;oby oparty na znanych, dobrze opisanych metodach, bez &#380;adnej kolejnej, magicznej sk&#322;adni? Wydaje si&#281;, &#380;e powy&#380;sze za&#322;o&#380;enia spe&#322;nia projekt  &lt;a href="http://thoughtbot.com/projects/shoulda"&gt;Shoulda&lt;/a&gt;. M&#243;j pierwsze wra&#380;enia z kontaktu z t&#261; bibliotek&#261;, jak na razie, s&#261; dosy&#263; dobre. Shoulda wprowadza du&#380;o mniej nowej sk&#322;adni ni&#380; RSpec. Wi&#281;kszo&#347;&#263; test&#243;w wykorzystuje stare, sprawdzone &amp;#8220;asserty&amp;#8221;. I o to chodzi. Nowa metodologia i znana, sprawdzona biblioteka standardowa Rubiego Test::Unit.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;UserTest&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;Test&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Unit&lt;/span&gt; 
  &lt;span class="ident"&gt;context&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;A User instance&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="ident"&gt;setup&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
      &lt;span class="attribute"&gt;@user&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;User&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;find&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:first&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;return its full name&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; 
      &lt;span class="ident"&gt;assert_equal&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;John Doe&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="attribute"&gt;@user&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;full_name&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="ident"&gt;context&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;with a profile&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
      &lt;span class="ident"&gt;setup&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
        &lt;span class="attribute"&gt;@user&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;profile&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Profile&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;find&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:first&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;

      &lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;return true when sent #has_profile?&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; 
        &lt;span class="ident"&gt;assert&lt;/span&gt; &lt;span class="attribute"&gt;@user&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;has_profile?&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Jeszcze jedna uwaga odno&#347;nie implementacji &lt;span class="caps"&gt;BDD&lt;/span&gt; w innych j&#281;zykach. Troch&#281; mia&#322;em problem&#243;w ze znalezieniem biblioteki do Pythona. &lt;a href="http://pycheesecake.org/wiki/PythonTestingToolsTaxonomy"&gt;Znaleziona obszerna lista bibliotek&lt;/a&gt; do Pythona nie ma kategorii &lt;span class="caps"&gt;BDD&lt;/span&gt;. Wygl&#261;da na to, &#380;e &lt;span class="caps"&gt;BDD&lt;/span&gt; i w og&#243;le kwesti&#261; testowania bardziej przejmuj&#261; si&#281; u&#380;ytkownicy Rubiego. Ale na szcz&#281;&#347;cie na stronie na stronie &lt;a href="http://behaviour-driven.org/Implementations"&gt;http://behaviour-driven.org/Implementations&lt;/a&gt; zamieszczono informacje kt&#243;rych mi brakowa&#322;o. Jeden z link&#243;w prowadzi do &lt;a href="http://darcs.idyll.org/~t/projects/pinocchio/doc/"&gt;Pinocchio&lt;/a&gt;, kt&#243;ry jest  rozszerzeniem bibliotek &lt;a href="http://code.google.com/p/python-nose/"&gt;Nose&lt;/a&gt; u&#380;ywanej m.in. przez framework &lt;a href="http://pylonshq.com"&gt;Pylons&lt;/a&gt;. Co ciekawe, jest te&#380; nawet &lt;a href="http://jania.pe.kr/aw/moin.cgi/JSSpec"&gt;JSSpec&lt;/a&gt;, biblioteka &lt;span class="caps"&gt;BDD&lt;/span&gt; dla j&#281;zyka Javascript.&lt;/p&gt;


	&lt;p&gt;Zobacz te&#380;:&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Beyond Test Driven Development: Behaviour Driven Development&lt;/strong&gt;&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;Wyk&#322;adowc&#261; jest Dave Astels, wsp&#243;&#322;autor ksi&#261;&#380;ki &lt;a href="http://www.amazon.com/Practical-Guide-eXtreme-Programming/dp/0130674826"&gt;A Practical Guide to eXtreme Programming&lt;/a&gt; (Google TechTalks)&lt;/p&gt;
	&lt;/blockquote&gt;


&lt;object width="425" height="355"&gt;&lt;param name="movie" value="http://www.youtube.com/v/oOFfHzrIDPk&amp;#38;rel=1"&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/oOFfHzrIDPk&amp;#38;rel=1" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;

	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://thoughtbot.com/projects/shoulda"&gt;Shoulda&lt;/a&gt; &amp;#8211; strona g&#322;&#243;wna&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://chneukirchen.org/blog/archive/2007/01/announcing-test-spec-0-3-a-bdd-interface-for-test-unit.html"&gt;Test/Spec&lt;/a&gt; &amp;#8211; podobny pomys&#322; co Shoulda &amp;#8211; &lt;span class="caps"&gt;BDD&lt;/span&gt; oparte a Unit::Test.&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://behaviour-driven.org/"&gt;Behavour Driven Development&lt;/a&gt; &amp;#8211; strona g&#322;&#243;wna &lt;span class="caps"&gt;BDD&lt;/span&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://behaviour-driven.org/Implementations"&gt;Behaviour Driven Development &amp;#8211; implementations&lt;/a&gt; &amp;#8211; implementacje &lt;span class="caps"&gt;BDD&lt;/span&gt; dla: Boo, C#, .NET, Delphi, Javy, Javascript, Ruby i &lt;strong&gt;Pythona&lt;/strong&gt;.&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://www.stifflog.com/pl/index.php/2006/11/27/behaviour-driven-development/"&gt;Wprowadzenie do RSpec &amp;#8211; &lt;span class="caps"&gt;BDD&lt;/span&gt;&lt;/a&gt; &amp;#8211; polskie wprowadzenie do RSpec i &lt;span class="caps"&gt;BDD&lt;/span&gt;&lt;/li&gt;
	&lt;/ul&gt;</description>
      <pubDate>Sun, 28 Oct 2007 18:45:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:eb7df053-32bf-4755-95ba-e9543b215f6d</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2007/10/28/shoulda-rspec</link>
      <category>bdd</category>
      <category>tdd</category>
      <category>rspec</category>
      <category>rails</category>
      <category>metodologia</category>
      <category>pinnocchio</category>
      <category>ruby</category>
      <category>python</category>
      <category>pylons</category>
    </item>
  </channel>
</rss>
