<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" version="2.0">

<channel>
	<title>Ben Mabey</title>
	
	<link>http://www.benmabey.com</link>
	<description />
	<lastBuildDate>Tue, 22 Dec 2009 04:13:55 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/benmabey" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="benmabey" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Writing Software not Code with Cucumber – slides from Ruby Hoedown</title>
		<link>http://www.benmabey.com/2009/08/28/writing-software-not-code-with-cucumber-slides-from-ruby-hoedown/</link>
		<comments>http://www.benmabey.com/2009/08/28/writing-software-not-code-with-cucumber-slides-from-ruby-hoedown/#comments</comments>
		<pubDate>Fri, 28 Aug 2009 20:46:11 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.benmabey.com/?p=95</guid>
		<description><![CDATA[Hah!  My last blog post was for slides when I presented last&#8230; I need to write more I think.
Anyways, I just finished presenting at the Ruby Hoedown.  It was roughly the same talk I gave at Mountain West Ruby conf but with a lot more advanced material and content in general.  It [...]]]></description>
			<content:encoded><![CDATA[<p>Hah!  My last blog post was for slides when I presented last&#8230; I need to write more I think.</p>
<p>Anyways, I just finished presenting at the <a href="http://rubyhoedown.com/">Ruby Hoedown</a>.  It was roughly the same <a href="http://mwrc2009.confreaks.com/14-mar-2009-15-00-bdd-with-cucumber-ben-mabey.html">talk I gave at Mountain West Ruby conf</a> but with a lot more advanced material and content in general.  It went somewhat okay.  I think I went too fast leaving some people behind when I was racing through the &#8220;basics&#8221;.  I had wanted to cover some of the more advanced topics that don&#8217;t get covered usually, but in the end I feel like the presentation came off as rushed and unfocused. It didn&#8217;t help that I was going off of 3 hours of sleep either. :/  Another issue was the color of my code slides, which looked awesome at MWRC but just didn&#8217;t project well on this projector- so, planning fail on my part.  I apologize for failing to recognizing my audience and the sub-par delivery. Regardless, I&#8217;m glad I did it and I&#8217;d like to thank Jeremy for inviting me to speak.  &lt;/presentation_retrospective&gt;
</p>
<p>
The presentation was a little meta&#8230; I was using a sinatra app I wrote called <a href="http://github.com/bmabey/codenote">CodeNote</a> that allows audience members to follow along but not go ahead.  A presenter is able to define the slides in a variant of Pat Nakajima&#8217;s awesome <a href="http://github.com/patnakajima/slidedown">slidedown</a> format.  I also integrated it with twitter so that I could ask questions and people could respond to them via twitter to win a book.  This explains the spamming of the #cucumber hash tag during my presentation. <img src='http://www.benmabey.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />   The meta part was that I showed how to test the twitter integration during the presentation.  Writing a test for that involved using a webservice (twitter), AJAX, and running background jobs.  I didn&#8217;t get into it nearly as much as I had hoped (which may be a good thing in retrospect) so if you are curious I would suggest checking out the code on github.
</p>
<p>Here are the slides:</p>
<p>
Note: Since SlideShare is lame now and won&#8217;t let you download the slides without an account <a href="http://benmabey.com/downloads/writing_software_not_code_with_cucumber.pdf">here is a PDF copy of the slides</a> if interested.
</p>
<div style="width:600px;text-align:left" id="__ss_1146069"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/bmabey/writing-software-not-code-with-cucumber?type=powerpoint" title="Writing Software not Code with Cucumber">Writing Software not Code with Cucumber</a><object style="margin:0px" width="600" height="490"><param name="movie" value="http://static.slideshare.net/swf/ssplayer2.swf?doc=writingsoftwarenotcodewithcucumber-090828141124-phpapp02&#038;rel=0&#038;stripped_title=writing-software-not-code-with-cucumber" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=writingsoftwarenotcodewithcucumber-090828141124-phpapp02&#038;rel=0&#038;stripped_title=writing-software-not-code-with-cucumber" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="600" height="490"></embed></object>
<div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;">View more <a style="text-decoration:underline;" href="http://www.slideshare.net/">presentations</a> from <a style="text-decoration:underline;" href="http://www.slideshare.net/bmabey">Ben Mabey</a>.</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.benmabey.com/2009/08/28/writing-software-not-code-with-cucumber-slides-from-ruby-hoedown/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Slides from Outside-In Development with Cucumber</title>
		<link>http://www.benmabey.com/2009/03/14/slides-from-outside-in-development-with-cucumber/</link>
		<comments>http://www.benmabey.com/2009/03/14/slides-from-outside-in-development-with-cucumber/#comments</comments>
		<pubDate>Sat, 14 Mar 2009 23:39:37 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[cucumber]]></category>

		<guid isPermaLink="false">http://www.benmabey.com/?p=78</guid>
		<description><![CDATA[I had great time presenting at Mountain West RubyConf.  It was my first time presenting to a larger group and I was pretty happy how it all turned out.  For those present I would love to get some feedback on how I could improve.  I spoke on Cucumber and Outside-In development with [...]]]></description>
			<content:encoded><![CDATA[<p>I had great time presenting at <a href="http://mtnwestrubyconf.org/2009/">Mountain West RubyConf</a>.  It was my first time presenting to a larger group and I was pretty happy how it all turned out.  For those present I would love to get some feedback on how I could improve.  I spoke on <a href="http://cukes.info">Cucumber</a> and Outside-In development with it.  Here is the actual blurb about the presentation:</p>
<p>
<em><br />
Cucumber is a <span class="caps">BDD</span> tool that aids in outside-in development by executing plain-text features/stories as automated acceptance tests. Written in conjunction with the stakeholder, these Cucumber features clearly articulate business value and also serve as a practical guide throughout the development process: by explicitly outlining the expected outcomes of various scenarios developers know both where to begin and when they are finished. I will present the basic usage of Cucumber, primarily in the context of web applications, which will include a survey of the common tools used for simulated and automated browser-testing. Common questions and pitfalls that arise will also be discussed.<br />
</em>
</p>
<p>MountainWest decided to cut the presentation times down to 30 minutes this year.  I think the new format was awesome and I hope they stick to it. However, I did have to cut some topics from my presentation.  Namely, I wasn&#8217;t able to explain Selenium and Celerity so those interested in testing JS with Cucumber should take a look at webrat&#8217;s <a href="http://github.com/brynary/webrat/blob/master/lib/webrat/selenium.rb">selenium adapter</a>, <a href="http://github.com/jarib/celerity/tree/master">Celerity</a>, <a href="http://github.com/langalex/culerity/tree/master">Culerity</a>, and the <a href="http://github.com/kamal/webrat/blob/master/lib/webrat/celerity.rb">Celeriry webrat adapter</a> (work-in-progress). on github.  I should also point out that you can use Watir or any other tool within Cucumber as well.</p>
<fieldset>
<legend style="font-weight:bold;">UPDATE</legend>
<p>You can download <a href="http://mwrc2009.confreaks.com/14-mar-2009-15-00-bdd-with-cucumber-ben-mabey.html">the presentation</a> over at Confreaks!<br />
</fieldset>
<p><embed src='http://mwrc2009.confreaks.com/player.swf' height='380' width='640' allowscriptaccess='always' allowfullscreen='true' flashvars='image=images%2F14-mar-2009-15-00-bdd-with-cucumber-ben-mabey-preview.png&#038;file=http%3A%2F%2Fmwrc2009.confreaks.com%2Fvideos%2F14-mar-2009-15-00-bdd-with-cucumber-ben-mabey-small.mp4&#038;plugins=viral-1'/></p>
<p>Note: Some of the code samples are not properly highlighted when viewing the presentation from slideshare.net so I would suggest <a href="http://www.slideshare.net/bmabey/outsidein-development-with-cucumber/download">downloading the PDF version</a>.</p>
<div style="width:600px;text-align:left" id="__ss_1146069"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/bmabey/outsidein-development-with-cucumber?type=powerpoint" title="Outside-In Development With Cucumber">Outside-In Development With Cucumber</a><object style="margin:0px" width="600" height="490"><param name="movie" value="http://static.slideshare.net/swf/ssplayer2.swf?doc=outside-indevelopmentwithcucumber-090314154342-phpapp02&#038;rel=0&#038;stripped_title=outsidein-development-with-cucumber" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slideshare.net/swf/ssplayer2.swf?doc=outside-indevelopmentwithcucumber-090314154342-phpapp02&#038;rel=0&#038;stripped_title=outsidein-development-with-cucumber" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="600" height="490"></embed></object>
<div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;">View more <a style="text-decoration:underline;" href="http://www.slideshare.net/">presentations</a> from <a style="text-decoration:underline;" href="http://www.slideshare.net/bmabey">Ben Mabey</a>.</div>
</div>
<p>During the presentation I was serving up my slides with a little sinatra app called slide_server. (The app didn&#8217;t allow people to skip ahead in the presentation.) I&#8217;ll be putting that code on github for any of those interested. Many thanks to <a href="http://twitter.com/binary42">Brian Mitchel</a> for helping me out with running the server during the presentation.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.benmabey.com/2009/03/14/slides-from-outside-in-development-with-cucumber/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Using Cucumber to Integrate Distributed Systems and Test Messaging</title>
		<link>http://www.benmabey.com/2009/02/17/using-cucumber-to-integrate-distributed-systems-and-test-messaging/</link>
		<comments>http://www.benmabey.com/2009/02/17/using-cucumber-to-integrate-distributed-systems-and-test-messaging/#comments</comments>
		<pubDate>Tue, 17 Feb 2009 16:46:23 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[cucumber]]></category>
		<category><![CDATA[messaging rosetta_queue cucumber]]></category>

		<guid isPermaLink="false">http://www.benmabey.com/?p=66</guid>
		<description><![CDATA[Cucumber is a fantastic tool that can be used in many ways to accomplish different goals.  One interesting use of Cucumber is to facilitate integration and communication between different systems.  At my last job we had several distributed systems that communicated via a messaging broker.  It was very important that the messages [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://cukes.info">Cucumber</a> is a fantastic tool that can be used in many ways to accomplish different goals.  One interesting use of Cucumber is to facilitate integration and communication between different systems.  At my last job we had several distributed systems that communicated via a messaging broker.  It was very important that the messages sent between the different systems be kept in sync and handled appropriately.  For example, System A needed to know the exact message format and queue that System B was going to be using, and vice versa.  This type of integration between systems is very error prone and when something goes awry the problems can be very hard to track down.  In order to ensure both systems were on the same page we used the exact same Cucumber feature in both systems but had the step definitions verify different things on the respective systems.  In this post I&#8217;ll walk through a quick example illustrating the tools and techniques we used to do this.</p>
<h2>The Feature</h2>
<p>Developers often struggle when writing features that entail systems or are purely technical in nature.  I highly recommend <a href="http://lizkeogh.com/2008/09/10/feature-injection-and-handling-technical-stories/">Liz Keogh&#8217;s post about this subject</a> as it greatly helped me in learning how to phrase such technical stories.  With that said, lets look at the example feature:</p>
<pre name="code" class="cucumber:nogutter">
  In order to enable accurate reporting
  As an analyst I want System A
  to keep it's widget data in sync with System B

  Scenario: widget creation
    Given I am logged in to System A
    When I create a widget
    Then the same widget should exist in System B
</pre>
<p>As you can see there is not much to the actual feature itself.  In real situations more context (more Givens) is usually needed to set up needed data, but outside of that the above is a good representation of what we found to be a good scenario format to stick to.  The key is to be simple and state declaratively the behaviour of the two systems.  This allows you keep the details of the implementations in the step definitions and not clutter the overall intent of the scenario with technical noise.</p>
<h2>Step Definitions</h2>
<p>I said above that both projects use the exact same plain-text feature, but implement the steps differently.  While this is true, we actually ended up having the exact same step definition files as well.  Blocks were then used to distinguish the code for either system within each step.  Continuing the example from above the pertinent step definitions would be:</p>
<pre name="code" class="ruby:nogutter">
When "I create a widget" do
  @expected_message = {"name" =&gt; "Foo", "color" =&gt; "Red"} 

  system_a do
    create_widget(@expected_message)  # this call should then make system_a publish a message
  end

  system_b do
    # when system_b runs the feature it needs to simulate a message from system_a
    publish_message(@expected_message, :to =&gt; :widget_queue)
  end

end

Then "the same widget should exist in System B" do
  system_a do
   # to ensure system_a is working correctly we need to make sure that the message was published
   @expected_message.should be_published_to(:widget_queue)
  end

  system_b do
    consume_once_with WidgetConsumer # have the consumer process the expected message from above
    Widget.count(:conditions =&gt; @expected_message).should == 1
  end

end

end
</pre>
<p>We gravitated to this solution because by keeping the files the same it was easy to keep the two systems in sync.  If one system changed the expected message or queue the step definitions would be updated and then both systems would make the feature pass again.</p>
<p>To be clear, these step definitions do not run both systems simultaneously.  Each system runs the feature independent of the other.  That is why System B in our example simulates what System A is publishing.  At this point we are trusting that the messaging system will do it&#8217;s job and deliver the message. If the systems are publishing and subscribing to the correct queues with an agreed upon message format then the messaging system should take care of the rest.  We did investigate running both systems from the same feature but in our situation the hassle and cost was not justified by the little value we saw that adding.</p>
<p>In order to accommodate this the following helpers were needed:</p>
<p>System A:</p>
<pre name="code" class="ruby:nogutter">
module MessagingHelpers
  def system_a
    yield
  end

  def system_b
    #no-op
  end

end

World(MessagingHelpers)
</pre>
</p>
<p>For System B the opposite was needed:</p>
<pre name="code" class="ruby:nogutter">
module MessagingHelpers
  def system_a
    # no-op
  end

  def system_b
    yield
  end

end

World(MessagingHelpers)
</pre>
</p>
<p>Of course you will need the actual messaging helpers too&#8230;</p>
<h2>Introducing Rosetta Queue</h2>
<p>The above step definitions have some nice messaging helpers (i.e. publish_message, should be_published_to, etc&#8230;).  These are not just imaginary helpers for use in the example, but are helpers in a library Chris Wyckoff and I recently released called <a href="http://github.com/bmabey/rosetta_queue/tree">Rosetta Queue</a>.  Rosetta Queue is named such because it has an adapter layer built-in that allows you to easily swap out which messaging system you are using.  For example, you could start out by using the stomp adapter with ActiveMQ but then later switch to use the <span class="caps">AMQP</span> adapter for use with RabbitMQ.  We used a real messaging system in our Cucumber features but for our RSpec code examples (unit tests) we disconnected the messaging system and used null and fake adapters provided by Rosetta Queue.  You can read more about how to use Rosetta Queue on <a href="http://github.com/bmabey/rosetta_queue/tree/master">github</a>.</p>
<p>As a disclaimer, I should say that Rosetta Queue is still relatively immature.  It is being used in production systems, but we aren&#8217;t happy with the <span class="caps">API</span> for publishing and receiving messages.  We will most likely be moving to an <span class="caps">API</span> that looks like:</p>
<pre name="code" class="ruby:nogutter">
queue(:widgets) &lt;&lt; "some message"
message = queue(:widgets).pop
</pre>
<p>The fake adapter is also really a dummy adapter that I want to replace with an actual in-memory fake adapter.  But overall, it is a nice library that aids in testing asynchronous messaging on the acceptance and unit level.</p>
<h2>Conclusion</h2>
<p>The pattern I&#8217;ve outlined above could be used with any messaging library, not just Rosetta Queue.  We found that using Cucumber in this fashion greatly eased the work required to integrate our systems and reduced our error rate.  By hitting the real messaging systems in our features we gained confidence in our system and helped prevent against regressions.  This also allowed us to disconnect our messaging systems from our unit tests so we could test our objects in isolation and keep them lightning fast.  (Yep, our unit tests were actual unit tests!)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.benmabey.com/2009/02/17/using-cucumber-to-integrate-distributed-systems-and-test-messaging/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Leveraging Test Data Builders in Cucumber Steps</title>
		<link>http://www.benmabey.com/2009/02/05/leveraging-test-data-builders-in-cucumber-steps/</link>
		<comments>http://www.benmabey.com/2009/02/05/leveraging-test-data-builders-in-cucumber-steps/#comments</comments>
		<pubDate>Thu, 05 Feb 2009 22:34:35 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[cucumber]]></category>

		<guid isPermaLink="false">http://www.benmabey.com/?p=52</guid>
		<description><![CDATA[Finding the balance between writing declarative scenarios and step reuse in Cucumber can be tricky at times.  I have found leveraging a Test Data Builder library (often selling itself as an Object Mother library) helps in step reuse and prevents your scenarios from being overloaded with a lot of noise.  There are many [...]]]></description>
			<content:encoded><![CDATA[<p>Finding the balance between writing <a href="http://www.benmabey.com/2008/05/19/imperative-vs-declarative-scenarios-in-user-stories/">declarative</a> scenarios and step reuse in Cucumber can be tricky at times.  I have found leveraging a Test Data Builder library (<a href="http://rubyforge.org/pipermail/rspec-users/2009-February/012122.html">often selling itself as an Object Mother library</a>) helps in step reuse and prevents your scenarios from being overloaded with a lot of noise.  There are many test data builder libraries out there to do this.  Some of the popular ones are: <a href="http://github.com/nakajima/fixjour/tree/master">Fixjour</a>, <a href="http://github.com/smtlaissezfaire/fixturereplacement/tree/master">FixtureReplacement</a>, and <a href="http://github.com/thoughtbot/factory_girl/tree">FactoryGirl</a>.  (There are tons more on github.)</p>
<p>In the context of Cucumber these test builders work well when you need to create some records with default values in Given steps.  Combined with the power of Cucumber step tables you can further leverage the builder pattern by providing the pertinent values to just the attributes that matter in each scenario.  The code below works out of the box for builders that adhere to the &#8220;create_model_name&#8221; <span class="caps">API</span>, but can be easily adapted to any <span class="caps">API</span>.  I have some thoughts on how to further leverage these builders in Cucumber along with Webrat but that is for another post. In the mean time, enjoy and <a href="http://gist.github.com/59007">fork away!</a></p>
<pre name="code" class="ruby:nogutter">
# step_definitions/builder_steps.rb
module BuilderStepHelpers

  def create_model(model_name, attributes={})
    send("create_#{model_name.gsub(' ','_')}",attributes)
  end

end
World do |world|
  world.extend BuilderStepHelpers
end

# Examples:
# Given the following widget exists:
# | Name  | Price |
# | Foo   | 20.00 |
# Given the following pets exist:
# |  Pet Type | Months Old     |
# | Dog       | 23             |
# | Cat       | 34             |
Given /^the following (.+?)(?:s|) exist(?:s|):$/ do |model_name, table|
  table.hashes.each do |hash|
    attributes = {}
    hash.each { |k, v| attributes[k.gsub(' ','').underscore] = v }
    create_model(model_name, attributes)
  end
end

# Example:
# Given widgets named 'Foo', 'Bar', and 'Car' exist
Given /^(.+?)(?:s|) named (.+) exist$/ do |model_name, names|
  names.extract_list.each do |name|
    create_model(model_name, {:name =&gt; name})
  end
end

# Example:
# Given an expensive widget exists  (assumes you have a create_expensive_widget method)
# Given a widget exists
# Given 3 widgets exist
# Given 33 widgets exist
#
# Warning: this one can be a little too greedy at times so YMMV from project to project.
Given /^(a|an|\d+) (.+?)(?:s|) exist(?:s|)$/ do |ammount, model_name|
  how_many = ammount =~ /a|an/ ? 1 : ammount.to_i
  1.upto(how_many) { create_model(model_name) }
end
</pre>
<pre name="code" class="ruby:nogutter">
# support/string.rb
# Examples:
# "'Foo', 'Bar', and 'Jar'".extract_list # =&gt; ["Foo", "Bar", "Jar"]
# '"Dog", "Cat"'.extract_list # =&gt; ["Dog", "Cat"]
class String
  def extract_list
    self.scan((/['"](.*?)["']/)).flatten
  end
end
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.benmabey.com/2009/02/05/leveraging-test-data-builders-in-cucumber-steps/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>GitHub rocks!</title>
		<link>http://www.benmabey.com/2008/12/18/github-rocks/</link>
		<comments>http://www.benmabey.com/2008/12/18/github-rocks/#comments</comments>
		<pubDate>Fri, 19 Dec 2008 04:32:58 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[git]]></category>
		<category><![CDATA[rants git github]]></category>

		<guid isPermaLink="false">http://www.benmabey.com/?p=27</guid>
		<description><![CDATA[I know you have heard this before (and probably already believe it), but I just had to say it.  GitHub has truly, IMO, changed the way open source projects can be started and developed. Let me tell you a little story in form of a timeline:

December 9 2008 &#8211; While hanging out in #cucumber, [...]]]></description>
			<content:encoded><![CDATA[<p>I know you have heard this before (and probably already believe it), but I just had to say it.  <a href="http://GitHub.com">GitHub</a> has truly, <span class="caps">IMO</span>, changed the way open source projects can be started and developed. Let me tell you a little story in form of a timeline:</p>
<ul>
<li><b>December 9 2008</b> &#8211; While hanging out in #<a href="http://GitHub.com/aslakhellesoy/cucumber/wikis">cucumber</a>, on freenode, agib (<a href="http://GitHub.com/agibralter">Aaron Gibralter</a>) asked about testing emails in a rails app.  I had some old RSpec Story Runner steps for such the thing so I quickly extracted them into a plugin and modified them to work in Cucumber. I pushed it to GitHub and <a href="http://GitHub.com/bmabey/email-spec/tree/master">email-spec</a> was born.</li>
</ul>
<ul>
<li><b>December 11</b> &#8211; Aaron sent me a pull request with some <a href="http://GitHub.com/agibralter/email-spec/commit/56b32c4660777fb1dc8008d84dc241b2c762bd7b">additional functionality he had added</a>.</li>
</ul>
<ul>
<li><b>December 17 7:46pm</b> &#8211; <a href="http://GitHub.com/mischa/">Mischa Fierer</a> sent an email to the <a href="http://rubyforge.org/mailman/listinfo/rspec-users">rspec-users mailing list</a> telling about the new plugin and some cool additions he made in his own fork (which he had forked off of Aaron&#8217;s.) He also added a cucumber feature example in the <span class="caps">README</span> on how to use the steps.</li>
</ul>
<ul>
<li><b>December 17 9:37pm</b> &#8211; I see Mischa&#8217;s email and pull in his changes.  I then created a sample rails app to illustrate how to use the plugin and ended up implementing the feature Mischa listed in the <span class="caps">README</span>.  I also did this so we could verify that the plugin still worked after we made further changes. In one of my comments I alluded to making it more accessible to other web frameworks.</li>
</ul>
<ul>
<li><b>December 18 8:00am</b> &#8211; I woke up and found two GitHub pull requests.  Shortly after I had pushed the sample app to GitHub Mischa had taken it, extended it and then used it to improve the error messaging in the plugin.  Then he converted the plugin into a gem (making it more accessible to other web frameworks), rolled the sample app into it with a handy rake task to test it, and improved the documentation! I merged in his changes and then made some minor tweaks.</li>
</ul>
<p>So in less than 10 days code that was sitting around in one of my projects had been extracted, forked twice, and turned into a gem.  Pretty cool, huh?  This is why I believe GitHub has changed the way open source projects are started and developed.  Yes, I could have released my code on RubyForge, or SourceForge, etc.. but the fact is that I never would have.  It takes so much longer, and is more intimidating to start a project on *Forge that I simply never would have done it. The code I was sharing was small, had some rough edges and just wasn&#8217;t &#8220;official&#8221; looking enough to warrant spending the time to do that.</p>
<p>When someone asks for code on a mailing list or in an <span class="caps">IRC</span> room you used to have two options: copy and paste the code into the email/room or use a site like <a href="http://pastie.org/">pastie</a> and send the link. With how easy it is to create repos on GitHub you can now simply &#8220;throw it on GitHub&#8221; (yes. you could also do a <a href="http://gist.GitHub.com">gist</a>.)  Since forking and sending pull requests is just as easy you will likely see more patches and contributors with it on GitHub than you would otherwise.  GitHub also spreads the word of your code/project a lot faster too since it starts showing up in people&#8217;s activity feeds.  I had originally put the code on GitHub for Aaron to look at and other people seemed to just stumble upon it.  In short, the combination of git and GitHub&#8217;s collaboration tools makes one awesome platform to develop open source software on.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.benmabey.com/2008/12/18/github-rocks/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Global Setup In RSpec or How To Add Logging For Specs</title>
		<link>http://www.benmabey.com/2008/07/04/global-setup-in-rspec-or-how-to-add-logging-for-specs/</link>
		<comments>http://www.benmabey.com/2008/07/04/global-setup-in-rspec-or-how-to-add-logging-for-specs/#comments</comments>
		<pubDate>Fri, 04 Jul 2008 08:09:27 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[rspec]]></category>
		<category><![CDATA[story runner]]></category>

		<guid isPermaLink="false">http://www.benmabey.com/?p=21</guid>
		<description><![CDATA[Brian Morearty had an interesting post on how to add additional information to a rails testing log when using Test::Unit.  The benefit of this is that you can quickly scan your log file when a test fails and see clues on why it failed.  If you&#8217;re using RSpec you can add the same [...]]]></description>
			<content:encoded><![CDATA[<p>Brian Morearty had an interesting post on <a href="http://bmorearty.wordpress.com/2008/06/18/find-tests-more-easily-in-your-testlog/">how to add additional information to a rails testing log</a> when using Test::Unit.  The benefit of this is that you can quickly scan your log file when a test fails and see clues on why it failed.  If you&#8217;re using RSpec you can add the same functionality all within the confines of the RSpec API for both specs (examples) and the story runner.</p>
<h2>Global Setup for Specs</h2>
<p>In order to announce the running of a spec in rail&#8217;s test log for all of the specs you need to take advantage of RSpec&#8217;s global setup capabilities.  To recreate the same type of logging message that <a href="http://bmorearty.wordpress.com/2008/06/18/find-tests-more-easily-in-your-testlog/">Brian did for Test::Unit</a> in RSpec you would simply need to add this in your spec_helper.rb:</p>
<pre name="code" class="ruby:nogutter">
    Spec::Runner.configure do |config|
      ...
      config.before(:each) do
          full_example_description = "Starting #{self.class.description} #{@method_name}"
          RAILS_DEFAULT_LOGGER.info("\n\n#{full_example_description}\n#{'-' * (full_example_description.length)}")
      end

    end
</pre>
<p>Note, that I am using the RAILS_DEFAULT_LOGGER constant instead of Rails::logger which was just introduced in Rails 2.1.  If you are using Rails 2.1 then I would suggest using the prettier and newer way.  I personally don&#8217;t feel the need to have &#8220;Starting&#8221; preface each description in the log file and prefer just to use the example description:</p>
<pre name="code" class="ruby:nogutter">
    Spec::Runner.configure do |config|

      ...
      config.before(:each) do
          full_example_description = "#{self.class.description} #{@method_name}"
          RAILS_DEFAULT_LOGGER.info("\n\n#{full_example_description}\n#{'-' * (full_example_description.length)}")
      end
    end
</pre>
<h2>Global Setup for Stories</h2>
<p>When using the RSpec Story Runner you often want to do some standard setup and teardown for each story and/or scenario.  (Such as cleaning up the database, or resetting ActionMailer::Base.deliveries.)  While the Story language does not provide a way to express this sort of setup and teardown (which is a good thing IMO) you can achieve the same effect by registering Listeners with the correct hooks.  The useful available hooks you can use are as follows:</p>
<pre name="code" class="ruby:nogutter">
    class MyStoryListener
       def run_started(number_of_scenarios); end
       def story_started(story, narrative); end
       def story_ended(story, narrative); end
       def scenario_started(story, scenario); end
       def scenario_succeeded(story, scenario); end
       def scenario_pending(story, scenario, error); end
       def scenario_failed(story, scenario, error); end
       def run_ended; end
    end
</pre>
<p>For example, if you wanted to add similar logging capabilities to your stories as we did with our specs above you would need to create a custom Listener and register it.  The code to do that is as follows:  (this should live in your stories/helper.rb file)</p>
<pre name="code" class="ruby:nogutter">
    class StoryLoggerListener

       def scenario_started(story, scenario)
        story_description    = "Story: #{story}"
        scenario_description = "  Scenario: #{scenario}"
        line_width = (story_description.length > scenario_description.length) ? story_description.length : scenario_description.length
        # yes, I know I could do [story_description.length, scenario_description.length].max
        RAILS_DEFAULT_LOGGER.info("\n\n#{story_description}\n#{scenario_description}\n#{"-"*line_width}")
       end

       def method_missing(method, *args)
          # no-op
        end
    end

    # This is how you register your listener
    Spec::Story::Runner.register_listener(StoryLoggerListener.new)
</pre>
<p>The trick is to have method_missing handle all of your unimplemented hooks and just implement the ones you care about.  The last line is what lets the Story Runner know about your listener so that the hooks are actually called.</p>
<p>Since scenarios tend to take a lot more space in a log file than an individual spec I don&#8217;t find this logging as useful.  The use of Listeners within the Story framework, in general, can be extremely useful though and is a nice feature to know about.</p>
<p>I hope this post helps in shedding some light on some lesser known features of RSpec and results in more useful log files. <img src='http://www.benmabey.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  </p>
]]></content:encoded>
			<wfw:commentRss>http://www.benmabey.com/2008/07/04/global-setup-in-rspec-or-how-to-add-logging-for-specs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Writing Macros in RSpec</title>
		<link>http://www.benmabey.com/2008/06/08/writing-macros-in-rspec/</link>
		<comments>http://www.benmabey.com/2008/06/08/writing-macros-in-rspec/#comments</comments>
		<pubDate>Mon, 09 Jun 2008 03:51:23 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[rspec]]></category>

		<guid isPermaLink="false">http://www.benmabey.com/?p=20</guid>
		<description><![CDATA[Thoughtbot put up a good post about creating &#8220;macro&#8221;s with Shoulda .  Shoulda has some very nice built-in macros which help a lot in keeping tests DRY without sacrificing the documentation aspect of tests.  (In fact I think these improve the readability of most tests because it removes some of the noise.)  [...]]]></description>
			<content:encoded><![CDATA[<p>Thoughtbot put up a good post about <a href="http://giantrobots.thoughtbot.com/2008/6/3/testing-paperclip-with-shoulda">creating &#8220;macro&#8221;s with Shoulda</a> .  Shoulda has some very nice built-in macros which help a lot in keeping tests DRY without sacrificing the documentation aspect of tests.  (In fact I think these improve the readability of most tests because it removes some of the noise.)  As Tammer Saleh said in the post these &#8220;macros&#8221; are nothing more than normal class methods, and so you can have the same sort of macros in any testing framework.  I have been creating and using my own custom macros in RSpec for some time now.  RSpec&#8217;s awesome DSL adds a little more complexity when creating such macros, but it is still easy to do once you understand some of RSpec&#8217;s DSL internals.  In this article I explain RSpec&#8217;s DSL enough to provide insight on how to write macros.  I will then show an example of writing a macro and illustrate how to extract it for reuse.</p>
<p>I should preface this explanation by saying that RSpec&#8217;s built in <a href="http://rspec.info/documentation/">Shared Behaviour</a> capabilities are very powerful and are usually the appropriate solution when abstracting common behaviour.  <a href="http://evang.eli.st/blog/2008/5/14/refactoring-with-shared-example-groups">Pat Maddox recently outlined some best practices of using shared behaviours in a refactoring</a> .  I generally use macros when I want to pass in an argument so that I can either a) use them multiple times in a given describe context, or b) customize the example and/or the description for specdoc output.</p>
<h2>Macro Example: it_should_assign</h2>
<p>A useful macro I use in my Rails controller specs is &#8220;it_should_assign&#8221;.  For example, say we have this simple show action on a nested resource controller:</p>
<pre name="code" class="ruby:nogutter">
class UserPhotosController
  def show
    @user = User.find(params['user_id'])
    @photo = @user.photos.find(params['id'])
    @page_title = "Best photo evar."
  end
end
</pre>
<p>And the specs dealing with assignment:</p>
<pre name="code" class="ruby:nogutter">
describe UserPhotosController do

  describe "GET 'users/1/photos/2'" do

    before(:each) do
      User.stub!(:find).and_return( @user = mock_user )
      @user.stub_association!(:photos, :find =&gt; (@users_photo = mock_model(Photo)) )
    end

    def do_get
      get :show, :user_id =&gt; @user.id, :id =&gt; @users_photo.id
    end

    ...

    it "should assign the user to the view" do
      do_get
      assigns[:user].should == @user
    end

    it "should assign the photo to the view" do
      do_get
      assigns[:photo].should == @users_photo
    end

    it "should assign the page title to the view" do
      do_get
      assigns[:page_title].should == "Best photo evar."
    end

  end

end
</pre>
<p>As you can see, the three specs are very similar and have some duplication between them.  I should point out that duplication in tests is expected and is usually not a bad thing since documentation and readability are primary goals of having a test/spec suite.  When extracting duplication from your specs you need to be very careful that these two aspects of the specs are not diminished.  A lot of this will depend on the situation and the skill level of your team.  In this example I would argue that this is such a common pattern that an abstraction wouldn&#8217;t hurt readability and in fact would help reduce some of the implementation noise (such as &#8216;do_get&#8217;.)</p>
<p>How do we want the &#8220;it_should_assign&#8221; macro to work?  This example illustrates the different ways I use it in my specs:</p>
<pre name="code" class="ruby:nogutter">
describe UserPhotosController do

  describe "GET 'users/1/photos/2'" do

    before(:each) do
      User.stub!(:find).and_return( @user = mock_user)
      @user.stub_association!(:photos, :find =&gt; (@users_photo = mock_model(Photo, :caption =&gt; "Best photo evar.")) )
    end

    def do_get
      get :show, :user_id =&gt; @user.id, :id =&gt; @users_photo.id
    end

    it_should_assign :user # Here, the macro assumes assigns[:user].should == @user
    it_should_assign :photo, "@users_photo" # Have flexibility when the name differs in the spec
    it_should_assign :page_title, "Best photo evar." # Ability to check literals

  end

end
</pre>
<h3>Dissecting part of RSpec&#8217;s DSL</h3>
<p>Before I show the implementation, it is important to realize what the &#8220;describe&#8221; keyword really does.  The &#8220;describe&#8221; keyword in rspec is actually a factory method (that in turn delegates to a factory object) that creates ExampleGroup sub-classes.  In rspec source terminology your &#8220;describe&#8221; blocks are example groups and your &#8220;it&#8221; blocks are the examples. So, you can think of &#8220;describe&#8221; as being a sort of wrapper for &#8220;class.&#8221; To make this point more clear, we can forgo the use of the describe keyword and subclass the ExampleGroup class ourselves:</p>
<pre name="code" class="ruby:nogutter">
class UserPhotosControllerSpec &lt; Spec::Rails::Example::ControllerExampleGroup
  describe UserPhotosController, "GET 'users/1/photos/2'"

    before(:each) do
      User.stub!(:find).and_return( @user = mock_user)
      @user.stub_association!(:photos, :find =&gt; (@users_photo = mock_model(Photo, :caption =&gt; "Best photo evar.")) )
    end

    def do_get
      get :show, :user_id =&gt; @user.id, :id =&gt; @users_photo.id
    end

    it_should_assign :user
    it_should_assign :photo, "@users_photo"
    it_should_assign :page_title, "Best photo evar."

  end

end
</pre>
<h3>Inline the macro implementation into the current example group</h3>
<p>Alright, so &#8220;describe&#8221; just subclasses the correct example group class for us and the block that gets passed in becomes our class definition.  With that knowledge we can create our macro as a regular class method inside our example group:</p>
<pre name="code" class="ruby:nogutter">
describe UserPhotosController do

  describe "GET 'users/1/photos/2'" do

    before(:each) do
      User.stub!(:find).and_return( @user = mock_user)
      @user.stub_association!(:photos, :find =&gt; (@users_photo = mock_model(Photo)) )
    end

    def do_get
      get :show, :user_id =&gt; @user.id, :id =&gt; @users_photo.id
    end

    def self.it_should_assign(variable_name, value=nil)
      it "should assign #{variable_name} to the view" do
        raise "Variable '@#{variable_name}' was not defined in the spec" if value.nil? &#038;&#038; !instance_variables.include?("@#{variable_name}")
        value ||= instance_variable_get("@#{variable_name}")
        if value.kind_of?(String) &amp;&amp; value.starts_with?("@")
          value = instance_variable_get(value)
        end
        do_get
        assigns[variable_name].should == value
      end
    end

    it_should_assign :user
    it_should_assign :photo, "@users_photo"
    it_should_assign :page_title, "Best photo evar."

  end

end
</pre>
<p>Pretty simple, huh?  At this point the macro is only available to that example group.  There are several ways you can extract it so that it can be used elsewhere.  Before we extract the macro we need to address the problem with the &#8220;do_get&#8221; call.</p>
<p>In my controller specs I follow the convention of defining a &#8220;do_get&#8221;, &#8220;do_put&#8221;, etc. based on the HTTP verb the action responds to.  In order for the assigns macro to work across specs for different actions it needs to be able to call the correct do_verb method.  We can accomplish this by defining a &#8220;do_action&#8221; method which calls the correct method:</p>
<pre name="code" class="ruby:nogutter">
describe UserPhotosController do

  describe "GET 'users/1/photos/2'" do

    ...

    def do_action
      verb = [:get, :post, :put, :delete].find{|verb| respond_to? :"do_#{verb}"}
      raise "No do_get, do_post_ do_put, or do_delete has been defined!" unless verb
      send("do_#{verb}")
    end

    def do_get
      get :show, :user_id =&gt; @user.id, :id =&gt; @users_photo.id
    end

    def self.it_should_assign(variable_name, value=nil)
      it "should assign #{variable_name} to the view" do
        ...
        do_action
        assigns[variable_name].should == value
      end
    end
    ...

  end

end
</pre>
<h3>Extracting the macro</h3>
<p>With the do_verb calls abstracted into the do_action method we can now extract the macro.  The most flexible option is to turn it into a module. The following is a standard ruby module taking advantage of the Module#included hook so both instance and class methods are mixed in:</p>
<pre name="code" class="ruby:nogutter">
module AssignMacro
  module ExampleMethods
    def do_action
      verb = [:get, :post, :put, :delete].find{|verb| respond_to? :"do_#{verb}"}
      raise "No do_get, do_post_ do_put, or do_delete has been defined!" unless verb
      send("do_#{verb}")
    end
  end

  module ExampleGroupMethods
    def it_should_assign(variable_name, value=nil)
      it "should assign #{variable_name} to the view" do
        raise "Variable '@#{variable_name}' was not defined in the spec" if value.nil? &#038;&#038; !instance_variables.include?("@#{variable_name}")
        value ||= instance_variable_get("@#{variable_name}")
        if value.kind_of?(String) &amp;&amp; value.starts_with?("@")
          value = instance_variable_get(value)
        end
        do_action
        assigns[variable_name].should == value
      end
    end
  end

  def self.included(receiver)
    receiver.extend         ExampleGroupMethods
    receiver.send :include, ExampleMethods
  end
end

# Now, we can just include it wherever we need it...
describe UserPhotosController do

  describe "GET 'users/1/photos/2'" do
    include AssignMacro
    ...
  end

end
</pre>
<p>Extracting the macros out into modules allows you to mix them only into example groups that you want them to be in.  In the case of this macro it would be nice to have it available for all controller specs.  This is possible by monkey patching the ControllerExampleGroup in your spec_helper.rb:</p>
<pre name="code" class="ruby:nogutter">
module Spec::Rails::Example

  class ControllerExampleGroup
    include AssignMacro
  end

end
</pre>
<fieldset>
<legend style="font-weight:bold;">UPDATE</legend>
<p>Please see David&#8217;s comment at the bottom of the post.  It turns out that RSpec&#8217;s API provides a safer way to mix in modules into certain example groups.  Monkey patching can be brittle and subject to breaks if RSpec&#8217;s underlying structure/implementation changes.<br />
</fieldset>
<p>For controller macros I usually don&#8217;t take the extra step of extracting it into a standalone module.  Instead, I just monkey patch my class and instance methods directly into ControllerExampleGroup.  If you have a macro that you want available for all of your example groups rspec already has a place where you can put them:</p>
<pre name="code" class="ruby:nogutter">
    module Spec::Example

      module ExampleGroupMethods
        # place example group methods (class methods) here
      end

      module ExampleMethods
        # place your example helper methods (instance methods) like do_action here
      end

  end
</pre>
<h2>Summary</h2>
<p>Macros are useful when extracting granular facets of behaviour which you want to customize by passing in arguments.  They are similar to shared behaviours but live at a different level (the class level) which allows for the additional flexibility.  Shared behaviours are usually a better fit when a refactoring causes you to consolidate behaviour in a module or a class higher up in the inheritance chain.  Macros tend to evolve out of common usage patterns within your specs and should be created when you want to dynamically create these slightly different specs.  Documentation and readability are paramount when using both methods.  If a macro saves you a couple of lines of duplicated code, but ends up hurting those two aspects of the spec, don&#8217;t use it!</p>
<p>I hope this article is helpful to people new to RSpec and to those who haven&#8217;t yet discovered this pattern.  If anything is unclear just ask. <img src='http://www.benmabey.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />   Several people have asked me to release some of my macros and other rspec extensions that I use in all of my rails and merb projects.  When I get the time I will clean them up and put them onto my <a href="http://github.com/bmabey">github account</a> .  Until then, happy spec’ing!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.benmabey.com/2008/06/08/writing-macros-in-rspec/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Imperative vs Declarative Scenarios in User Stories</title>
		<link>http://www.benmabey.com/2008/05/19/imperative-vs-declarative-scenarios-in-user-stories/</link>
		<comments>http://www.benmabey.com/2008/05/19/imperative-vs-declarative-scenarios-in-user-stories/#comments</comments>
		<pubDate>Mon, 19 May 2008 19:03:39 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[story runner]]></category>

		<guid isPermaLink="false">http://www.benmabey.com/?p=19</guid>
		<description><![CDATA[Last week I was looking at some of the presentations from GoRuCo that Confreaks recently posted.  One of them was a presentation on rspec&#8217;s story runner given by Bryan Helmkamp&#8217;s (of webrat fame.)  It is a great presentation which I highly recommend for anyone looking into incorporating the story runner into their development [...]]]></description>
			<content:encoded><![CDATA[<p>Last week I was looking at some of the <a href="http://goruco2008.confreaks.com/">presentations from GoRuCo that Confreaks recently posted</a>.  One of them was a presentation on rspec&#8217;s story runner given by <a href="http://www.brynary.com/2008/4/26/story-driven-development-slides-posted">Bryan</a> <a href="http://goruco2008.confreaks.com/01_helmkamp.html">Helmkamp</a>&#8217;s (of webrat fame.)  It is a great presentation which I highly recommend for anyone looking into incorporating the story runner into their development process.  In the presentation Bryan talked about the differences between imperative and declarative scenarios.  In my opinion, both styles have benefits and should be used appropriately based on the situation.  The majority of examples on rspec&#8217;s story runner currently on the web, including <a href="http://www.benmabey.com/2008/02/04/rspec-plain-text-stories-webrat-chunky-bacon/">mine</a>, are of the imperative type.  Since the declarative type has many advantages I thought it would be worth while to present some examples and contrast the differences between the two styles.</p>
<h2>Imperative Style</h2>
<p>Lets look at the example I gave in my previous post (slightly modified):</p>
<pre name="code" class="cucumber:nogutter">
Story: Animal Submission

  As a Zoologist
  I want to add a new animal to the site
  So that I can share my animal knowledge with the community

  Scenario: successful submission
  Given I'm on the animal creation page

  When I fill in Name with 'Alligator'
  And select Phylum as 'Chordata'
  And fill in Animal Class with 'Sauropsida'
  And fill in Order with 'Crocodilia'
  And fill in Family with 'Alligatoridae'
  And fill in Genus with 'Alligator'
  And check Lay Eggs
  And click the Create button

  Then I should see the notice 'Thank you for your animal submission!'
  And the page should include the animal's name, phylum, animal class, order, family, and genus
</pre>
<p>The imperative style uses highly reusable granular steps which outlines much of the user interface.  This binds the scenario to that interface and requires more design decisions made up front.  The step matchers for these granular steps are very easy to write as I demonstrated in my <a href="http://www.benmabey.com/2008/02/04/rspec-plain-text-stories-webrat-chunky-bacon/">webrat post</a>.  Once these steps are in place you can write the majority of your scenarios in this fashion without having to write custom step matchers.  Due to the granularity of the scenarios however they become very brittle as they are subject to requirement changes from the customer.  If a new field is added, for example, you must update the scenario to reflect this even though the underlying goal of the scenario has not changed.</p>
<h2>Declarative Style</h2>
<p>Lets rewrite the above example in a more declarative fashion.  The story narrative and scenario title will remain the same.</p>
<pre name="code" class="cucumber:nogutter">
Story: Animal Submission

  As a Zoologist
  I want to add a new animal to the site
  So that I can share my animal knowledge with the community

  Scenario: successful submission
  Given I'm on the animal creation page

  When I add a new animal

  Then I should see the page for my newly created animal
  And the notice 'Thank you for your animal submission!'
</pre>
<p>This style is more aligned with User Stories in the agile sense having more of the &#8220;token for conversation&#8221; feel to it.  The first thing that you should observe about this style is how much smaller it is than the imperative one.  This is a good thing.  The imperative style tends to produce noisy scenarios that drown out the signal.  With the declarative style the goal of the scenario remains clear.  When a new field is added to the form the scenario does not have to be modified.  Yes, you will have to modify the underlying step matcher but the scenario does not have to suffer dilution due to the change.  The trade off is, of course, that you will now be writing step matchers for all of your scenarios.  Looking at our example, the implementation for the When step is very similar to the imperative scenario steps:</p>
<pre name="code" class="ruby:nogutter">
# animal_steps.rb
When "I add a new animal" do
  fills_in 'Name', :with => 'Alligator'
  selects 'Chordata', :from => 'Phylum'
  fills_in 'Animal Class', :with => 'Sauropsida'
  fills_in 'Order', :with => 'Crocodilia'
  fills_in 'Family', :with => 'Alligatoridae'
  fills_in 'Genus', :with => 'Alligator'
  checks 'Lay Eggs'
  clicks_button 'Create'
end
</pre>
<p>The majority of the imperative step matchers were merely wrappers for webrat so creating custom steps for each scenario is not much of a deterrent.  Additionally, the reuse of steps will only take you so far before your stories start to feel unnatural as you try to force each scenario to use the same phrasing.  Creating custom steps for each scenario actually turns out to be better for reducing duplication in most cases.  That is because you can now extract duplicate code from the step matchers into helper methods.  The place to put these helpers is in the Spec::Story::World module (monkey patch it.)  </p>
<p>Another way to reduce duplication in step matchers that I learned recently is to call other steps directly within another one.  For example, if you have this step:</p>
<pre name="code" class="ruby:nogutter">
Given "a user named $user_name" do |user_name|
  User.create!(:name => user_name, ....)
end
</pre>
<p>and you now want to have a step that matches &#8216;Given a user named Jim with a photo album&#8217; you can reuse the above step directly in the new one like so:</p>
<pre name="code" class="ruby:nogutter">
Given "a user named $user_name with a photo album" do |user_name|
  Given "a user named #{user_name}"
  ....
end
</pre>
<p>I haven&#8217;t experimented with this approach too much so I&#8217;m not sure how much I like it, but I can see occasions where it would prove useful.</p>
<h2>Choosing which style to use</h2>
<p>I have made a strong case for the declarative style of writing scenarios.  It would seem that one should never write a scenario imperatively based solely on the merits of maintenance and communicating story intent.  While I think the declarative style has many strengths it is not the best choice for all situations.  The imperative style should not be discounted entirely because when used judiciously in the right scenario it can highlight certain aspects of the functionality and improve communication.  It is also important to realize that the two types are not mutually exclusive.  The styles can be mixed throughout an app, a story, and even an individual scenario to provide the appropriate level of granularity as the situation demands.</p>
<p>One of the most important factors in deciding which type of style to adopt however has nothing to do with maintenance or code duplication; that factor is the customer.  While these stories may be acting as integration tests for the developer that is not the original purpose.  The stories are meant to facilitate communication between developer and stakeholder about business value and functionality.  If your stakeholder needs each form field outlined in the scenario in order to have confidence in the system then the imperative style is a better route to go.  Specs (unit tests) are just for the developer but stories need to appease the wider audience of developer and stakeholder so an appropriate balance needs to be reached.  As in most areas of software development there is no right answer and in the end it just depends on the situation.</p>
<h2>References</h2>
<p>Aside from the materials already linked to in this post another great resource (actually, it is the best that I have found) on the various ways to approach story runner is <a href="http://www.chariotsolutions.com/slides/pdfs/ete2008-IntegrationTestingWithRSpec.pdf">David Chelimsky&#8217;s ETEC slides</a>.  In the slides he refers to the imperative style as detailed scenarios.  He will be giving <a href="http://en.oreilly.com/rails2008/public/schedule/detail/2055">a similar talk at at RailsConf</a>, so be sure to catch it if your able to make it to RailsConf this year.</p>
<p><i>I&#8217;d like to thank David Chelimsky, Kyle Hargraves, and Zach Dennis for their discussion on this topic on the rspec-users mailing list.</i></p>
]]></content:encoded>
			<wfw:commentRss>http://www.benmabey.com/2008/05/19/imperative-vs-declarative-scenarios-in-user-stories/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Slides and code from my BDD/rspec presentation</title>
		<link>http://www.benmabey.com/2008/05/10/slides-and-code-from-my-bddrspec-presentation/</link>
		<comments>http://www.benmabey.com/2008/05/10/slides-and-code-from-my-bddrspec-presentation/#comments</comments>
		<pubDate>Sun, 11 May 2008 03:55:56 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[story runner]]></category>

		<guid isPermaLink="false">http://www.benmabey.com/?p=18</guid>
		<description><![CDATA[Here are the slides from my URUG (Utah Ruby User Group) presentation on 5/7/2008:

 &#124; View &#124; Upload your own

During the presentation I attempted to show some actual code.  Using git I had previously walked through the different ways of using the rspec story runner (ruby with inlined steps, with steps libraries, and plain [...]]]></description>
			<content:encoded><![CDATA[<p>Here are the slides from my <a href="http://urug.org">URUG (Utah Ruby User Group)</a> presentation on 5/7/2008:</p>
<div style="width:425px;text-align:left" id="__ss_398309"><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slideshare.net/swf/ssplayer2.swf?doc=bdd-and-the-how-with-rspec-1210474916409535-9"/><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slideshare.net/swf/ssplayer2.swf?doc=bdd-and-the-how-with-rspec-1210474916409535-9" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object>
<div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;"><a href="http://www.slideshare.net/?src=embed"><img src="http://static.slideshare.net/swf/logo_embd.png" style="border:0px none;margin-bottom:-5px" alt="SlideShare"/></a> | <a href="http://www.slideshare.net/bmabey/the-why-behind-tddbdd-and-the-how-with-rspec?src=embed" title="View 'The WHY behind TDD/BDD and the HOW with RSpec' on SlideShare">View</a> | <a href="http://www.slideshare.net/upload?src=embed">Upload your own</a></div>
</div>
<p>During the presentation I attempted to show some actual code.  Using git I had previously walked through the different ways of using the rspec story runner (ruby with inlined steps, with steps libraries, and plain text with steps) and tagged the progress as I went.  You can download the git repo and look at the different ways of using the story runner by checking out the different tags.</p>
<p>To list the tags simply type &#8216;git tag&#8217; and to checkout a tag into a new branch type &#8216;git checkout -b tag_name tag_name&#8217;.</p>
<div class="download-link">
	<a href="http://www.benmabey.com/wp-content/uploads/2008/05/story_runner_demo.tar.gz"><img src="http://www.benmabey.com/wp-content/icons/downloads.png" alt="Download" class="leftalign" /></a></p>
<h4>
		<a href="http://www.benmabey.com/wp-content/uploads/2008/05/story_runner_demo.tar.gz">story_runner_demo.tar.gz </a><br />
	</h4>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.benmabey.com/2008/05/10/slides-and-code-from-my-bddrspec-presentation/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>git bash completion + git aliases</title>
		<link>http://www.benmabey.com/2008/05/07/git-bash-completion-git-aliases/</link>
		<comments>http://www.benmabey.com/2008/05/07/git-bash-completion-git-aliases/#comments</comments>
		<pubDate>Thu, 08 May 2008 03:54:46 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[bash]]></category>
		<category><![CDATA[git]]></category>

		<guid isPermaLink="false">http://www.benmabey.com/?p=17</guid>
		<description><![CDATA[If you haven&#8217;t added bash completion for git you should do so now.  As with all bash completion it just makes you feel happy  . I&#8217;ll wait while you do that&#8230;.
Now, if you&#8217;re like me you have tons of git aliases setup.  Shortly after setting up bash completion you will notice that [...]]]></description>
			<content:encoded><![CDATA[<p>If you haven&#8217;t added <a href='http://blog.bitfluent.com/post/27983389'>bash completion for git</a> you should do so now.  As with all bash completion it just makes you feel happy <img src='http://www.benmabey.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . I&#8217;ll wait while you do that&#8230;.</p>
<p>Now, if you&#8217;re like me you have tons of git aliases setup.  Shortly after setting up bash completion you will notice that your aliases don&#8217;t work with the new found goodness.  What is a poor developer to do?  Can&#8217;t I have bash completion with my aliases thus reducing the actual typing I have to do to close to zero?  Well, not knowing too much about how bash completion works this was the best solution I came up with:</p>
<pre>
	<code>
		## in my .bash_profile

		#Git aliases
		alias gco='git co'
		.....

		source ~/bin/git-completion.bash
		complete -o default -o nospace -F _git_checkout gco
		.....
	</code>
</pre>
<p>If you look in git-completion.bash at the bottom you will see where it declares which bash functions are suppose to handle which git commands (via the built-in &#8216;complete&#8217; command.)  What I did was just find the correct function and assigned it to my corresponding git alias after the git bash completion file was sourced. I can now type &#8216;gco &#8216;, hit tab, and see all of my branches.  Pretty cool, huh?  I don&#8217;t think I can get any lazier.</p>
<p>I know that my bash-fu is still weak and I have much to learn&#8230; Is there a simpler way to do this so that bash completion expands your aliases?  If not, I hope this helps other lazy git users.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.benmabey.com/2008/05/07/git-bash-completion-git-aliases/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss><!-- Dynamic Page Served (once) in 0.387 seconds --><!-- Cached page generated by WP-Super-Cache on 2010-02-24 10:57:43 -->
