<?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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Musings of a Software Development Manager</title>
	
	<link>http://edgibbs.com</link>
	<description>Lessons from managing developers</description>
	<lastBuildDate>Mon, 14 May 2012 13:49:59 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/MusingsOfASoftwareDevelopmentManager" /><feedburner:info uri="musingsofasoftwaredevelopmentmanager" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>6 Months with Vim</title>
		<link>http://feedproxy.google.com/~r/MusingsOfASoftwareDevelopmentManager/~3/c9oVMswTrKE/</link>
		<comments>http://edgibbs.com/2012/05/14/6-months-with-vim/#comments</comments>
		<pubDate>Mon, 14 May 2012 13:49:58 +0000</pubDate>
		<dc:creator>Ed Gibbs</dc:creator>
				<category><![CDATA[ruby]]></category>
		<category><![CDATA[software development]]></category>

		<guid isPermaLink="false">http://edgibbs.com/?p=940</guid>
		<description><![CDATA[ College Roomate: So you know vi? Me: Of course, that would be command shift-Z-Z <p>This is a conversation I had about twenty years ago. For most of my Unix editing I got by with pico and I found the modal nature of vi downright frustrating. Hence the importance of knowing the command to escape [...]]]></description>
			<content:encoded><![CDATA[<div align="center">
	<img src="http://edgibbs.com/images/vim_posse.jpg"/><br />
<!-- http://www.flickr.com/photos/termie/2922917167/ -->
</div>
<pre>
<b>College Roomate</b>: So you know vi?
<b>Me</b>: Of course, that would be command shift-Z-Z
</pre>
<p>This is a conversation I had about twenty years ago.  For most of my Unix editing I got by with pico and I found the modal nature of vi downright frustrating.  Hence the importance of knowing the command to escape from modal hell.</p>
<p>At my current company vim was the default text editor, I even paired in the interview on vim.  Over the years I&#8217;ve bounced between text editors and IDEs depending on the languages and environments.  One key point though was that when I reached for a text editor it was always one with a GUI front end like BBEdit or TextMate.  Despite working in vim most of the day I still default to MarsEdit for writing blog posts.</p>
<p>I jumped into vim with some lingering fear remembering my dislike of its modal nature and the lack of any mouse support.  I tried out <a href="http://vimgolf.com/">VimGolf</a> and spent some time trying to memorize basic navigation and selection commands.  It came pretty slowly at first.  I bogged down my pair quite a bit fumbling around with arrow keys or splitting the screen the wrong way.  About two months in I had developed some basic proficiency, but I found myself wondering if RubyMine or TextMate wouldn&#8217;t be a better option.</p>
<p>At about the 6 month mark I looked back and realized I was finally comfortable in vim as I found myself defaulting to it for most of my text editing even when I wasn&#8217;t working on code.  I still have a few cases where I prefer using a visual editor or IDE for tasks like:</p>
<ul>
<li>blogging</li>
<li>email</li>
<li>exploring large projects</li>
<li>larger refactorings</li>
</ul>
<p>Looking back there were several items that accelerated my vim mastery.  One was our switch to sharing a single base .vimrc so when you pairing with anyone you had the same configuration of the editor.  It also included several features like macros for commenting, formatting, auto-complete, and running inline RSpec.  After setting up that .vimrc I saw how vim could be a more powerful tool.  </p>
<p>Another big step was learning to love &#8216;hjkl&#8217; over the arrow keys.  That took about a week or so to break the habit and it was painful, but the speed difference was worth it.  The mouse is already gone, so might as well toss the throwback to the arrow keys.  (I found the <a href="http://stackoverflow.com/questions/127591/using-caps-lock-as-esc-in-mac-os-x">hack</a> here on Stack Overflow.)</p>
<p>A critical change that I arrived at fairly late was remapping my caps lock.  Normally you rarely touch caps lock, but it is in a very convent position especially compared to the escape key.  I remapped my caps lock to tap it to get an escape and holding it down yields a control which are the two most commonly used modifier keys in vim.  That made my fingers very happy.</p>
<p>Finally, the biggest learning expeditor was pairing with a number of developers who had more expertise than myself.  Since the team had standardized on vim before I arrived they had all gone far past where I was on the learning curve and were able to quickly demonstrate how to use vim or which keystroke to use as I fumbled along.  I greatly appreciated their patience and willingness to let me bang something out that they could have typed in half the time.</p>
<p>I still don&#8217;t feel anything like a vim expert, but I do feel comfortable in a modal editor.  Never thought I would be typing those words all these years later.</p>
<img src="http://feeds.feedburner.com/~r/MusingsOfASoftwareDevelopmentManager/~4/c9oVMswTrKE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://edgibbs.com/2012/05/14/6-months-with-vim/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://edgibbs.com/2012/05/14/6-months-with-vim/</feedburner:origLink></item>
		<item>
		<title>Jenkins: My Personal Bodyguard</title>
		<link>http://feedproxy.google.com/~r/MusingsOfASoftwareDevelopmentManager/~3/h6KoGlFt5dY/</link>
		<comments>http://edgibbs.com/2012/05/09/jenkins-my-personal-bodyguard/#comments</comments>
		<pubDate>Wed, 09 May 2012 13:29:45 +0000</pubDate>
		<dc:creator>Ed Gibbs</dc:creator>
				<category><![CDATA[automated builds]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[software development]]></category>
		<category><![CDATA[test driven development]]></category>

		<guid isPermaLink="false">http://edgibbs.com/?p=934</guid>
		<description><![CDATA[<p>I&#8217;ve been running Jenkins as my CI solution for years now, but for the first 6 months at my new job I used it in an entirely new way. The typical CI pattern is you setup to run against checkins to your master branch run all the unit tests, and depending on how sophisticated you [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been running Jenkins as my CI solution for years now, but for the first 6 months at my new job I used it in an entirely new way.  The typical CI pattern is you setup to run against checkins to your master branch run all the unit tests, and depending on how sophisticated you are integration tests, static analysis, or even performance tests.  </p>
<p>In my current shop we had a standard CI build using CC.rb against checkins to our master branch.  It ran about 5000+ specs sequentially and if everything&#8217;s green master is available for production pushes.  That fulfills the standard case for CI just fine, but I quickly found that it a little light for my needs.  The issue is we relied on feature branches for rolling out all of our stories and while those stories are being worked there&#8217;s no CI job at all.  Another pain point is even with parallel specs and a nice 4-8 core processor the full test run takes 5-10 minutes so it doesn&#8217;t get run nearly as often as one might like.</p>
<p>I&#8217;d let Jenkins be my default choice for CI in Javaland, but I was really open to switching it out for a more Ruby style CI server.  I figured the first place to look was our already running CC.rb implementation.  I tried out CC.rb long ago and remembered liking it a lot better than the original cruise control, but with years of development on it I figured it had evolved.  Turns out CC.rb is a pretty basic solution for CI and it hasn&#8217;t had much love over the years.  It runs a build showing the console output and a very basic web console.  Coming from Jenkins the lack of features and plugins was pretty shocking.</p>
<p>Given the Ruby community&#8217;s love for XP practices there must be a better option available.  I looked at numerous CI servers for Ruby including CI Joe, Integrity, and Travis.  All of them followed the lines of providing a very simple CI server much like CC.rb.  Travis CI appeared to be a bit more with its use of a hosted open source solution, but it is completely tied to hosting your project on Github.  None of these projects showed the depth of a solution like Jenkins.</p>
<p>So the solution was to run Jenkins as my own personal bodyguard.  We were looking at swapping out the CC.rb implementation, but it wasn&#8217;t a priority right away.  So I dived in and setup Jenkins to run a build on my laptop.  Instead of just building master I added whatever git feature branch I was working on and hooked up an audible trigger to play James Brown &#8220;I feel good!&#8221; for successes and &#8220;Houston I think we have a problem&#8221; for failures.  I expected to use the rake plugin to launch the build, but it turned out it was much easier with using things like rvm and bundler to simply execute a script.  My final scripts for the build looked something like the following:</p>
<div class="codecolorer-container text vibrant overflow-off" style="overflow: auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">bash -l -c &quot;rvm use 1.8.7-p330@acme&quot;<br />
bash -l -c &quot;bundle install&quot;<br />
bash -l -c &quot;rake db:migrate&quot;<br />
bash -l -c &quot;rake parallel: prepare&quot;<br />
bash -l -c &quot;rake parallel: spec&quot;</div></td></tr></tbody></table></div>
<p>So finishing up a bit of functionality, I&#8217;d commit and about 10 minutes later my laptop would exclaim &#8220;I feel good&#8221;, or occasionally &#8220;Houston I think we have a problem&#8221; to let me know I missed something.  So I had my own personal bodyguard build and I could happily let it run in the background.  </p>
<p>This year we replaced CC.rb with Jenkins and dropped feature branches so I&#8217;ve retired my laptop Jenkins, but I recommend the practice if you find yourself in a similar spot.</p>
<img src="http://feeds.feedburner.com/~r/MusingsOfASoftwareDevelopmentManager/~4/h6KoGlFt5dY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://edgibbs.com/2012/05/09/jenkins-my-personal-bodyguard/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://edgibbs.com/2012/05/09/jenkins-my-personal-bodyguard/</feedburner:origLink></item>
		<item>
		<title>Stubbing Partials with RSpec in Rails View Tests</title>
		<link>http://feedproxy.google.com/~r/MusingsOfASoftwareDevelopmentManager/~3/KOoL9DTu01U/</link>
		<comments>http://edgibbs.com/2011/11/19/stubbing-partials-with-rspec-in-rails-view-tests/#comments</comments>
		<pubDate>Sat, 19 Nov 2011 22:59:51 +0000</pubDate>
		<dc:creator>Ed Gibbs</dc:creator>
				<category><![CDATA[ruby]]></category>
		<category><![CDATA[software development]]></category>
		<category><![CDATA[test driven development]]></category>

		<guid isPermaLink="false">http://edgibbs.com/?p=928</guid>
		<description><![CDATA[<p>Working with my pair yesterday we ran into an issue testing a view that pulled in several partials. In the interest of making progress we punted after about half an hour of trying to setup expectations on the partials and just tested the negative cases where we didn&#8217;t have to worry about the partials being [...]]]></description>
			<content:encoded><![CDATA[<p>Working with my pair yesterday we ran into an issue testing a view that pulled in several partials.  In the interest of making progress we punted after about half an hour of trying to setup expectations on the partials and just tested the negative cases where we didn&#8217;t have to worry about the partials being called.  Intellectual curiosity and not wanting to leave the views lightly tested I dived into seeing how we could effectively test that the partials were called as expected.</p>
<p>Say you have a view like the following:</p>
<div class="codecolorer-container ruby vibrant overflow-off" style="overflow: auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#006600; font-weight:bold;">&lt;</span>div id=<span style="color:#996600;">&quot;content&quot;</span><span style="color:#006600; font-weight:bold;">&gt;</span><br />
&nbsp; <span style="color:#006600; font-weight:bold;">&lt;</span>div id=<span style="color:#996600;">&quot;page_title&quot;</span> style=<span style="color:#996600;">&quot;padding-bottom: 20px&quot;</span><span style="color:#006600; font-weight:bold;">&gt;</span><br />
&nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&lt;</span>h2<span style="color:#006600; font-weight:bold;">&gt;</span>Books<span style="color:#006600; font-weight:bold;">&lt;/</span>h2<span style="color:#006600; font-weight:bold;">&gt;</span><br />
&nbsp; <span style="color:#006600; font-weight:bold;">&lt;/</span>div<span style="color:#006600; font-weight:bold;">&gt;</span><br />
&nbsp; <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#006600; font-weight:bold;">%</span>= render <span style="color:#ff3333; font-weight:bold;">:partial</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'tabs'</span> <span style="color:#006600; font-weight:bold;">%&gt;</span><br />
<br />
&nbsp; <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#006600; font-weight:bold;">%</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@books</span>.<span style="color:#9900CC;">empty</span>? <span style="color:#006600; font-weight:bold;">-%&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&lt;</span>em<span style="color:#006600; font-weight:bold;">&gt;</span>No Books<span style="color:#006600; font-weight:bold;">&lt;/</span>em<span style="color:#006600; font-weight:bold;">&gt;&lt;</span>em<span style="color:#006600; font-weight:bold;">&gt;</span><br />
&nbsp; <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#006600; font-weight:bold;">%</span> <span style="color:#9966CC; font-weight:bold;">else</span> <span style="color:#006600; font-weight:bold;">%&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#006600; font-weight:bold;">%</span>= pagination_links = render <span style="color:#ff3333; font-weight:bold;">:partial</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'shared/pagination'</span>, <span style="color:#ff3333; font-weight:bold;">:object</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@books</span> <span style="color:#006600; font-weight:bold;">%&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#006600; font-weight:bold;">%</span>= render <span style="color:#ff3333; font-weight:bold;">:partial</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;book_rows&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:locals</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span>:books <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@books</span><span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#006600; font-weight:bold;">%&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#006600; font-weight:bold;">%</span>= pagination_links <span style="color:#006600; font-weight:bold;">%&gt;</span><br />
&nbsp; <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#006600; font-weight:bold;">%</span> <span style="color:#9966CC; font-weight:bold;">end</span> <span style="color:#006600; font-weight:bold;">%&gt;</span><br />
<span style="color:#006600; font-weight:bold;">&lt;/</span>em<span style="color:#006600; font-weight:bold;">&gt;&lt;/</span>div<span style="color:#006600; font-weight:bold;">&gt;</span></div></td></tr></tbody></table></div>
<p>You want to test the conditional to see that the partials to display the list of books work correctly.  You don&#8217;t want to worry about concerns like setting up the books collection, and you might even want to stub out the call to the partial that displays the tabs a the top of the page.</p>
<p>The Rspec example group for this looks like the following:</p>
<div class="codecolorer-container ruby vibrant overflow-off" style="overflow: auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'spec_helper'</span><br />
<br />
describe <span style="color:#996600;">&quot;books.rhtml&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; before<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:each</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; assigns<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:books</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; describe <span style="color:#996600;">&quot;with no books&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; it <span style="color:#996600;">&quot;should display 'No Books' message&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; &nbsp; render<br />
&nbsp; &nbsp; &nbsp; response.<span style="color:#9900CC;">should</span> have_text<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">/</span>No Books<span style="color:#006600; font-weight:bold;">/</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; describe <span style="color:#996600;">&quot;with books&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; before<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:each</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; &nbsp; assigns<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:books</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#006600; font-weight:bold;">&#91;</span>Factory.<span style="color:#9900CC;">build</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:book</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; template.<span style="color:#9900CC;">stub</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:render</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">with</span><span style="color:#006600; font-weight:bold;">&#40;</span>hash_including<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:partial</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;tabs&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; template.<span style="color:#9900CC;">stub</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:render</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">with</span><span style="color:#006600; font-weight:bold;">&#40;</span>hash_including<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:partial</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;shared/pagination&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; &nbsp; it <span style="color:#996600;">&quot;should render book rows&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; &nbsp; template.<span style="color:#9900CC;">should_receive</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:render</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">with</span><span style="color:#006600; font-weight:bold;">&#40;</span>hash_including<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:partial</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;book_rows&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; render<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>The key find was to use with(:hash_including()) which I found from a helpful link at <a href="http://stackoverflow.com/questions/1893544/rspec-partials-problem">Stack Overflow</a>.</p>
<img src="http://feeds.feedburner.com/~r/MusingsOfASoftwareDevelopmentManager/~4/KOoL9DTu01U" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://edgibbs.com/2011/11/19/stubbing-partials-with-rspec-in-rails-view-tests/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://edgibbs.com/2011/11/19/stubbing-partials-with-rspec-in-rails-view-tests/</feedburner:origLink></item>
		<item>
		<title>Breaking the Build at the New Job</title>
		<link>http://feedproxy.google.com/~r/MusingsOfASoftwareDevelopmentManager/~3/YGDDOCF8WmM/</link>
		<comments>http://edgibbs.com/2011/09/17/breaking-the-build-at-the-new-job/#comments</comments>
		<pubDate>Sun, 18 Sep 2011 03:43:55 +0000</pubDate>
		<dc:creator>Ed Gibbs</dc:creator>
				<category><![CDATA[automated builds]]></category>
		<category><![CDATA[software development]]></category>
		<category><![CDATA[test driven development]]></category>

		<guid isPermaLink="false">http://edgibbs.com/?p=926</guid>
		<description><![CDATA[ <p>My first break of the CI build on a new team came about two weeks into starting the new job. We had made a small change to a dynamically created URL on a single page of the application. Normally this would fall into the category of &#8220;too simple to test&#8221; for me. My pairing [...]]]></description>
			<content:encoded><![CDATA[<div align="center">
	<img src="http://edgibbs.com/images/i_broke_the_build.jpg" alt="I broke the build"/><br />
<!-- Picture taken by http://www.flickr.com/photos/dhaun/5626938236/in/photostream/ -->
</div>
<p>My first break of the CI build on a new team came about two weeks into starting the new job.  We had made a small change to a dynamically created URL on a single page of the application.  Normally this would fall into the category of &#8220;too simple to test&#8221; for me.  My pairing partner pointed out when we started the story that we should put a test in for the change.  I argued that changing a URL was too simple a change to bother writing a test for.  He disagreed, but let me go ahead after some further discussion.  After checking in the feature, about an hour later a developer on the other side of the room piped up with &#8220;Someone broke the build.&#8221;  My pairing partner smiled and said,  &#8220;I guess we didn&#8217;t need to test that.&#8221;  </p>
<p>It turned out there was another test I didn&#8217;t realize had a dependency on that same link and by changing it we had broken an assertion on the specific URL.  A bit embarrassed I learned an important lesson.  My assumptions about &#8220;too simple to break&#8221; needed some adjusting.  </p>
<p>Over the course of several weeks I came to appreciate that many things were worth testing.  A particularly revealing example was testing a new javascript dialog.  Javascript is always a pain point when it comes to unit testing, and I&#8217;ve often let that coverage of javascript functionality be covered by functional tests usually with Selenium.  My pairing partner walked me through a complete TDD approach asserting every part of the function we created and the various DOM elements we used to create it.  I did ask a few questions about whether we really needed to test that we had created a DOM element in some exact order at points, but he was firm about testing in every piece.  By the end of the feature I had a new appreciation for doing very low level unit testing.</p>
<p>I love that I&#8217;m being challenged on not writing enough tests.  For so long in past shops I was the hardcore TDD advocate constantly questioned about the real need for testing some component.  Now I&#8217;m learning to test in even very small changes.</p>
<img src="http://feeds.feedburner.com/~r/MusingsOfASoftwareDevelopmentManager/~4/YGDDOCF8WmM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://edgibbs.com/2011/09/17/breaking-the-build-at-the-new-job/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://edgibbs.com/2011/09/17/breaking-the-build-at-the-new-job/</feedburner:origLink></item>
		<item>
		<title>Cardboard Boxes and Modern Web Frameworks</title>
		<link>http://feedproxy.google.com/~r/MusingsOfASoftwareDevelopmentManager/~3/5Mv9TPnXZiI/</link>
		<comments>http://edgibbs.com/2011/08/07/cardboard-boxes-and-modern-web-frameworks/#comments</comments>
		<pubDate>Sun, 07 Aug 2011 14:29:24 +0000</pubDate>
		<dc:creator>Ed Gibbs</dc:creator>
				<category><![CDATA[groovy]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[software development]]></category>

		<guid isPermaLink="false">http://edgibbs.com/?p=918</guid>
		<description><![CDATA[<p>My daughter spent an hour the other day cutting holes, drawing red bricks, and pasting grass along the bottom of a simple cardboard box. It&#8217;s a common story among parents, especially of small children that despite spending a lot of money on a gift, the kid ends up enjoying the box and ignoring the toy.</p> [...]]]></description>
			<content:encoded><![CDATA[<p>My daughter spent an hour the other day cutting holes, drawing red bricks, and pasting grass along the bottom of a simple cardboard box.  It&#8217;s a common story among parents, especially of small children that despite spending a lot of money on a gift, the kid ends up enjoying the box and ignoring the toy.</p>
<p>I&#8217;ve noticed a common quality of many newer web frameworks is that they provide you with a nice box to build from.  Typically:</p>
<ul>
<li>A default structure so you know where to find the models, views, controllers, extra libraries, etc.</li>
<li>A command line for generating stubs, running tests, and deploying.</li>
<li>A plugin system for easily adding functionality from swapping out javascript libraries to adding a security system.</li>
</ul>
<p>Though there are probably others I&#8217;m aware of this model being used by Spring Roo, the Play Framework, Gryphon, Grails, and Rails.  I don&#8217;t claim to be a historian on this, but Rails was my first experience with this style and I assume to be the originator of the approach.  </p>
<p>The benefits of this approach are obvious from the first time you start off with a Hello World tutorial.  For one you generally have a single download for the framework.  After unpacking you&#8217;re able to use the command line to generate your Hello World controller, find the view in a predefined location, add the Hello World line, and fire up the application from the command line.  Passing the 5 minute test is pretty important if you expect developers to give your framework a chance.  </p>
<p>As a consultant working on numerous legacy code projects, there&#8217;s always the groan moment when you start looking into the code and you realize its non-obvious where to find things.  I&#8217;ve seen libraries sprinkled about at random, key configuration files that were supposed to be moved into the users home directory, model classes mixed in with controllers, and a host of other inconsistencies.  With a framework that reinforces the default structures it becomes easy to find things and much easier for plugin-authors to write plug-ins that make the framework much more valuable.</p>
<p>Finally, the plugin system is a critical part of new frameworks.  Being able to add security framework on the fly, swap out your testing framework, or simply add in a nicer date library really starts to make things feel like magic.  Indeed among these frameworks they are starting to push more and more modularity into the plugin systems to allow for the framework to evolve better over time.</p>
<p>I hope this trend continues in the world of web frameworks, as I really like a nice box to start a project from.</p>
<img src="http://feeds.feedburner.com/~r/MusingsOfASoftwareDevelopmentManager/~4/5Mv9TPnXZiI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://edgibbs.com/2011/08/07/cardboard-boxes-and-modern-web-frameworks/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://edgibbs.com/2011/08/07/cardboard-boxes-and-modern-web-frameworks/</feedburner:origLink></item>
		<item>
		<title>Mock With Spock</title>
		<link>http://feedproxy.google.com/~r/MusingsOfASoftwareDevelopmentManager/~3/pp3FtQ9Vnr0/</link>
		<comments>http://edgibbs.com/2011/06/06/mock-with-spock/#comments</comments>
		<pubDate>Tue, 07 Jun 2011 03:38:16 +0000</pubDate>
		<dc:creator>Ed Gibbs</dc:creator>
				<category><![CDATA[groovy]]></category>
		<category><![CDATA[software development]]></category>
		<category><![CDATA[test driven development]]></category>

		<guid isPermaLink="false">http://edgibbs.com/?p=903</guid>
		<description><![CDATA[<p>My default rule with mocking is to try to stick to stubs where possible. I don&#8217;t enjoy having to setup and verify interactions with mocks, but sometimes you have some code where that&#8217;s exactly what you need to do. I&#8217;ve used many frameworks in Java over the years from EasyMock to Mockito, but I was [...]]]></description>
			<content:encoded><![CDATA[<p>My default rule with mocking is to try to stick to stubs where possible.  I don&#8217;t enjoy having to setup and verify interactions with mocks, but sometimes you have some code where that&#8217;s exactly what you need to do.  I&#8217;ve used many frameworks in Java over the years from EasyMock to Mockito, but I was quite happy with how easy it was to do in Spock.  I recently found myself having to build a test harness around some legacy code.  The real world code was more involved, but it looked something like this:</p>
<div class="codecolorer-container java vibrant overflow-off" style="overflow: auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> addDefaultQuestions<span style="color: #009900;">&#40;</span>Category category<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>categoryDao.<span style="color: #006633;">getCategory</span><span style="color: #009900;">&#40;</span>category.<span style="color: #006633;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">getQuestions</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">isEmpty</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span>Question question <span style="color: #339933;">:</span> category.<span style="color: #006633;">getQuestions</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>question.<span style="color: #006633;">isDefaultQuestion</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; categoryDao.<span style="color: #006633;">addQuestion</span><span style="color: #009900;">&#40;</span>question, <span style="color: #000066; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; categoryDao.<span style="color: #006633;">addQuestion</span><span style="color: #009900;">&#40;</span>question, <span style="color: #000066; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>The method is taking a category, checking if any questions related to the category exist in the database and then saving all the questions with a valid flag set to true or false.  Not unusual in a typical corporate application, but I want to test two things:</p>
<ul>
<li>I can add new questions to the database with the proper valid flag.</li>
<li>If the database category already has some questions then do nothing.</li>
</ul>
<p>After walking through the Spock <a href="http://code.google.com/p/spock/wiki/Interactions">mocking documentation</a> I had a pretty good sense of the approach.  In Spock it&#8217;s referred to as interactions, but it doesn&#8217;t follow the typical expect-run-verify pattern.  You just verify what you need to if you need to.  And given a choice I prefer not to have to verify the mock at all.  </p>
<p>With this code I needed to mock the categoryDao which used straight JDBC and made calls to the real database.  That meant I needed a way to verify that the questions were added correctly with calls to the categoryDao.  Hence I needed the power of an actual mock and not just a stub class.</p>
<p>The first test would show that I could save new questions in a category to the database:</p>
<div class="codecolorer-container groovy vibrant overflow-off" style="overflow: auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br /></div></td><td><div class="groovy codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp;<a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20def"><span style="color: #000000; font-weight: bold;">def</span></a> <span style="color: #ff0000;">&quot;should only insert new default questions&quot;</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; given:<br />
&nbsp; &nbsp; <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20def"><span style="color: #000000; font-weight: bold;">def</span></a> question1 <span style="color: #66cc66;">=</span> <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20new"><span style="color: #000000; font-weight: bold;">new</span></a> Question<span style="color: #66cc66;">&#40;</span>defaultQuestion: <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20true"><span style="color: #000000; font-weight: bold;">true</span></a><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20def"><span style="color: #000000; font-weight: bold;">def</span></a> question2 <span style="color: #66cc66;">=</span> <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20new"><span style="color: #000000; font-weight: bold;">new</span></a> Question<span style="color: #66cc66;">&#40;</span>defaultQuestion: <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20false"><span style="color: #000000; font-weight: bold;">false</span></a><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20def"><span style="color: #000000; font-weight: bold;">def</span></a> category <span style="color: #66cc66;">=</span> <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20new"><span style="color: #000000; font-weight: bold;">new</span></a> Category<span style="color: #66cc66;">&#40;</span>questions: <span style="color: #66cc66;">&#91;</span>question1, question2<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span><br />
<br />
&nbsp; &nbsp; CategoryDao dao <span style="color: #66cc66;">=</span> Mock<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; dao.<span style="color: #006600;">getCategory</span><span style="color: #66cc66;">&#40;</span>_<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&gt;&gt;</span> <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20new"><span style="color: #000000; font-weight: bold;">new</span></a> Category<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><br />
<br />
&nbsp; &nbsp; CategoryService service <span style="color: #66cc66;">=</span> <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20new"><span style="color: #000000; font-weight: bold;">new</span></a> CategoryService<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; service.<span style="color: #006600;">setCategoryDao</span><span style="color: #66cc66;">&#40;</span>dao<span style="color: #66cc66;">&#41;</span><br />
<br />
&nbsp; &nbsp; when:<br />
&nbsp; &nbsp; service.<span style="color: #006600;">addDefaultQuestions</span><span style="color: #66cc66;">&#40;</span>category<span style="color: #66cc66;">&#41;</span><br />
<br />
&nbsp; &nbsp; then:<br />
&nbsp; &nbsp; <span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">*</span> dao.<span style="color: #006600;">addQuestion</span><span style="color: #66cc66;">&#40;</span>_, <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20true"><span style="color: #000000; font-weight: bold;">true</span></a><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">*</span> dao.<span style="color: #006600;">addQuestion</span><span style="color: #66cc66;">&#40;</span>_, <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20false"><span style="color: #000000; font-weight: bold;">false</span></a><span style="color: #66cc66;">&#41;</span><br />
<br />
&nbsp; <span style="color: #66cc66;">&#125;</span></div></td></tr></tbody></table></div>
<p>So the steps are:</p>
<ol>
<li>Setup a Category object with two questions.</li>
<li>Create a mock dao.</li>
<li>Define a method and its default return value on the mock DAO.
<ol>
<li>We define arguments to getCategory() with a wildcard operator the underscore standing in for an id.</li>
<li>Then with the right shift operator (&gt;&gt;) we define that we will return a newly created Category object.</li>
</ol>
</li>
<li>Inject the mock into the service class we&#8217;re testing.</li>
<li>Finally, we make verifications on the addQuestion() method by just stating the number of times we expect the method to be called with a given set of arguments, again reusing the wildcard underscore character.</li>
</ol>
<p>You can even specify the particular order you expect by breaking the verifications into separate <b>then:</b> blocks.  For this example it wouldn&#8217;t matter on the order, but in case it did the last when then block would change to:</p>
<div class="codecolorer-container groovy vibrant overflow-off" style="overflow: auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="groovy codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; when:<br />
&nbsp; &nbsp; service.<span style="color: #006600;">addDefaultQuestions</span><span style="color: #66cc66;">&#40;</span>category<span style="color: #66cc66;">&#41;</span><br />
<br />
&nbsp; &nbsp; then:<br />
&nbsp; &nbsp; <span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">*</span> dao.<span style="color: #006600;">addQuestion</span><span style="color: #66cc66;">&#40;</span>_, <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20true"><span style="color: #000000; font-weight: bold;">true</span></a><span style="color: #66cc66;">&#41;</span><br />
<br />
&nbsp; &nbsp; then:<br />
&nbsp; &nbsp; <span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">*</span> dao.<span style="color: #006600;">addQuestion</span><span style="color: #66cc66;">&#40;</span>_, <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20false"><span style="color: #000000; font-weight: bold;">false</span></a><span style="color: #66cc66;">&#41;</span></div></td></tr></tbody></table></div>
<p>And to round out testing the legacy Java code we need to test the negative example where it should do nothing if there are already questions in the database for the given category.</p>
<div class="codecolorer-container groovy vibrant overflow-off" style="overflow: auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br /></div></td><td><div class="groovy codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20def"><span style="color: #000000; font-weight: bold;">def</span></a> <span style="color: #ff0000;">&quot;should add no questions if questions are already in database&quot;</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; given:<br />
&nbsp; &nbsp; <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20def"><span style="color: #000000; font-weight: bold;">def</span></a> question1 <span style="color: #66cc66;">=</span> <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20new"><span style="color: #000000; font-weight: bold;">new</span></a> Question<span style="color: #66cc66;">&#40;</span>defaultQuestion: <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20true"><span style="color: #000000; font-weight: bold;">true</span></a><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20def"><span style="color: #000000; font-weight: bold;">def</span></a> question2 <span style="color: #66cc66;">=</span> <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20new"><span style="color: #000000; font-weight: bold;">new</span></a> Question<span style="color: #66cc66;">&#40;</span>defaultQuestion: <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20false"><span style="color: #000000; font-weight: bold;">false</span></a><span style="color: #66cc66;">&#41;</span><br />
<br />
&nbsp; &nbsp; CategoryDao dao <span style="color: #66cc66;">=</span> Mock<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; dao.<span style="color: #006600;">getCategory</span><span style="color: #66cc66;">&#40;</span>_<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&gt;&gt;</span> <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20new"><span style="color: #000000; font-weight: bold;">new</span></a> Category<span style="color: #66cc66;">&#40;</span>questions: <span style="color: #66cc66;">&#91;</span>question1<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span><br />
<br />
&nbsp; &nbsp; CategoryService service <span style="color: #66cc66;">=</span> <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20new"><span style="color: #000000; font-weight: bold;">new</span></a> CategoryService<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; service.<span style="color: #006600;">setCategoryDao</span><span style="color: #66cc66;">&#40;</span>dao<span style="color: #66cc66;">&#41;</span><br />
<br />
&nbsp; &nbsp; when:<br />
&nbsp; &nbsp; service.<span style="color: #006600;">addDefaultQuestions</span><span style="color: #66cc66;">&#40;</span><a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20new"><span style="color: #000000; font-weight: bold;">new</span></a> Category<span style="color: #66cc66;">&#40;</span>questions: <span style="color: #66cc66;">&#91;</span>question2<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><br />
<br />
&nbsp; &nbsp; then:<br />
&nbsp; &nbsp; <span style="color: #cc66cc;">0</span> <span style="color: #66cc66;">*</span> dao.<span style="color: #006600;">addQuestion</span><span style="color: #66cc66;">&#40;</span>_,_<span style="color: #66cc66;">&#41;</span><br />
<br />
&nbsp; <span style="color: #66cc66;">&#125;</span></div></td></tr></tbody></table></div>
<p>So we can test for the negative case by just verifying that addQuestion was called zero times.</p>
<img src="http://feeds.feedburner.com/~r/MusingsOfASoftwareDevelopmentManager/~4/pp3FtQ9Vnr0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://edgibbs.com/2011/06/06/mock-with-spock/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://edgibbs.com/2011/06/06/mock-with-spock/</feedburner:origLink></item>
		<item>
		<title>Grails Unit Testing: Mocking With MetaClass Stubs</title>
		<link>http://feedproxy.google.com/~r/MusingsOfASoftwareDevelopmentManager/~3/UzkGygDp2x4/</link>
		<comments>http://edgibbs.com/2011/04/17/grails-unit-testing-mocking-with-metaclass-stubs/#comments</comments>
		<pubDate>Sun, 17 Apr 2011 21:06:21 +0000</pubDate>
		<dc:creator>Ed Gibbs</dc:creator>
				<category><![CDATA[groovy]]></category>
		<category><![CDATA[software development]]></category>
		<category><![CDATA[test driven development]]></category>

		<guid isPermaLink="false">http://edgibbs.com/?p=893</guid>
		<description><![CDATA[<p>On a recent project I ran into issues with testing controllers in Grails. Starting test first, I spent some early time figuring out how much support there was out of the box for unit testing Grails domain classes and controllers. I setup Spock as a plugin and plunged in. I was dealing with a legacy [...]]]></description>
			<content:encoded><![CDATA[<p>On a recent project I ran into issues with testing controllers in Grails.  Starting test first, I spent some early time figuring out how much support there was out of the box for unit testing Grails domain classes and controllers.  I setup <a href="http://code.google.com/p/spock/">Spock</a> as a plugin and plunged in.  I was dealing with a legacy database which had 100% compound primary keys so many of the findBy type operations that are well supported for controller testing are of no help.  Often I found I needed to mock a call to a find or findAll with HQL syntax or a criteria call.  I knew metaClass mocking could work here, but I wanted to understand better how that would impact the rest of the code after I started replacing methods on the fly.  Turns out Grails unit testing has built in support for cleaning up metaClass hacking after every test with the registerMetaClass() method in GrailsUnitTestCase.  <a href="http://mrhaki.blogspot.com/">Mrhaki</a> has a good <a href="http://mrhaki.blogspot.com/2010/03/grails-goodness-using-metaclass-with.html">post</a> on this.  Here&#8217;s an Spock example:</p>
<div class="codecolorer-container groovy vibrant overflow-off" style="overflow: auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br /></div></td><td><div class="groovy codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20import"><span style="color: #000000; font-weight: bold;">import</span></a> <span style="color: #a1a100;">grails.plugin.spock.ControllerSpec</span><br />
<br />
<br />
<a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20class"><span style="color: #000000; font-weight: bold;">class</span></a> ContractControllerSpec <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20extends"><span style="color: #000000; font-weight: bold;">extends</span></a> ControllerSpec <span style="color: #66cc66;">&#123;</span><br />
<br />
&nbsp; <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20def"><span style="color: #000000; font-weight: bold;">def</span></a> setup<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; registerMetaClass Contract<br />
&nbsp; <span style="color: #66cc66;">&#125;</span><br />
<br />
&nbsp;<a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20def"><span style="color: #000000; font-weight: bold;">def</span></a> <span style="color: #ff0000;">&quot;validateContract() returns true for an existing contract&quot;</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; given:<br />
&nbsp; &nbsp; mockDomain<span style="color: #66cc66;">&#40;</span>Contract<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20def"><span style="color: #000000; font-weight: bold;">def</span></a> contract <span style="color: #66cc66;">=</span> <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20new"><span style="color: #000000; font-weight: bold;">new</span></a> Contract<span style="color: #66cc66;">&#40;</span>division: <span style="color: #ff0000;">'33'</span>, unit: <span style="color: #ff0000;">'99'</span>, contractNumber: <span style="color: #ff0000;">'C7777777'</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">save</span><span style="color: #66cc66;">&#40;</span>flush: <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20true"><span style="color: #000000; font-weight: bold;">true</span></a><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; controller.<span style="color: #006600;">params</span>.<span style="color: #006600;">division</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'33'</span><br />
&nbsp; &nbsp; controller.<span style="color: #006600;">params</span>.<span style="color: #006600;">unit</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'99'</span><br />
&nbsp; &nbsp; controller.<span style="color: #006600;">params</span>.<span style="color: #006600;">contractNumber</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'C7777777'</span><br />
&nbsp; &nbsp; Contract.<span style="color: #006600;">metaClass</span>.<a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20static"><span style="color: #000000; font-weight: bold;">static</span></a>.<a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20find"><span style="color: #663399;">find</span></a> <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#123;</span> <a href="http://www.google.de/search?as_q=String&amp;num=100&amp;hl=en&amp;as_occt=url&amp;as_sitesearch=java.sun.com%2Fj2se%2F1%2E5%2E0%2Fdocs%2Fapi%2F"><span style="color: #aaaadd; font-weight: bold;">String</span></a> query, <a href="http://www.google.de/search?as_q=Map&amp;num=100&amp;hl=en&amp;as_occt=url&amp;as_sitesearch=java.sun.com%2Fj2se%2F1%2E5%2E0%2Fdocs%2Fapi%2F"><span style="color: #aaaadd; font-weight: bold;">Map</span></a> namedArgs <span style="color: #66cc66;">-&gt;</span> contract <span style="color: #66cc66;">&#125;</span><br />
<br />
&nbsp; &nbsp; when:<br />
&nbsp; &nbsp; controller.<span style="color: #006600;">validateContract</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><br />
<br />
&nbsp; &nbsp; then:<br />
&nbsp; &nbsp; <span style="color: #ff0000;">&quot;TRUE&quot;</span> <span style="color: #66cc66;">==</span> controller.<span style="color: #006600;">response</span>.<span style="color: #006600;">contentAsString</span><br />
&nbsp; <span style="color: #66cc66;">&#125;</span><br />
<br />
<span style="color: #66cc66;">&#125;</span></div></td></tr></tbody></table></div>
<p>Grails has support for the same idea using mockFor(), but the syntax is much like EasyMock.  The same test would look like:</p>
<div class="codecolorer-container groovy vibrant overflow-off" style="overflow: auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br /></div></td><td><div class="groovy codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20import"><span style="color: #000000; font-weight: bold;">import</span></a> <span style="color: #a1a100;">grails.plugin.spock.ControllerSpec</span><br />
<br />
<br />
<a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20class"><span style="color: #000000; font-weight: bold;">class</span></a> ContractControllerSpec <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20extends"><span style="color: #000000; font-weight: bold;">extends</span></a> ControllerSpec <span style="color: #66cc66;">&#123;</span><br />
<br />
&nbsp;<a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20def"><span style="color: #000000; font-weight: bold;">def</span></a> <span style="color: #ff0000;">&quot;validateContract() returns true for an existing contract&quot;</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; given:<br />
&nbsp; &nbsp; mockDomain<span style="color: #66cc66;">&#40;</span>Contract<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20def"><span style="color: #000000; font-weight: bold;">def</span></a> contract <span style="color: #66cc66;">=</span> <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20new"><span style="color: #000000; font-weight: bold;">new</span></a> Contract<span style="color: #66cc66;">&#40;</span>division: <span style="color: #ff0000;">'33'</span>, unit: <span style="color: #ff0000;">'99'</span>, contractNumber: <span style="color: #ff0000;">'C7777777'</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">save</span><span style="color: #66cc66;">&#40;</span>flush: <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20true"><span style="color: #000000; font-weight: bold;">true</span></a><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; controller.<span style="color: #006600;">params</span>.<span style="color: #006600;">division</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'33'</span><br />
&nbsp; &nbsp; controller.<span style="color: #006600;">params</span>.<span style="color: #006600;">unit</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'99'</span><br />
&nbsp; &nbsp; controller.<span style="color: #006600;">params</span>.<span style="color: #006600;">contractNumber</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'C7777777'</span><br />
<br />
&nbsp; <span style="color: #808080; font-style: italic;">// EasyMock like syntax</span><br />
&nbsp; <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20def"><span style="color: #000000; font-weight: bold;">def</span></a> mockContract <span style="color: #66cc66;">=</span> mockFor<span style="color: #66cc66;">&#40;</span>Contract<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; mockContract.<span style="color: #006600;">demand</span>.<a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20static"><span style="color: #000000; font-weight: bold;">static</span></a>.<a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20find"><span style="color: #663399;">find</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">0</span>..<span style="color: #cc66cc;">5</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <a href="http://www.google.de/search?as_q=String&amp;num=100&amp;hl=en&amp;as_occt=url&amp;as_sitesearch=java.sun.com%2Fj2se%2F1%2E5%2E0%2Fdocs%2Fapi%2F"><span style="color: #aaaadd; font-weight: bold;">String</span></a> query, <a href="http://www.google.de/search?as_q=Map&amp;num=100&amp;hl=en&amp;as_occt=url&amp;as_sitesearch=java.sun.com%2Fj2se%2F1%2E5%2E0%2Fdocs%2Fapi%2F"><span style="color: #aaaadd; font-weight: bold;">Map</span></a> namedArgs <span style="color: #66cc66;">-&gt;</span> <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20null"><span style="color: #000000; font-weight: bold;">null</span></a> <span style="color: #66cc66;">&#125;</span><br />
<br />
&nbsp; &nbsp; when:<br />
&nbsp; &nbsp; controller.<span style="color: #006600;">validateContract</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><br />
<br />
&nbsp; &nbsp; then:<br />
&nbsp; &nbsp; <span style="color: #ff0000;">&quot;TRUE&quot;</span> <span style="color: #66cc66;">==</span> controller.<span style="color: #006600;">response</span>.<span style="color: #006600;">contentAsString</span><br />
&nbsp; <span style="color: #66cc66;">&#125;</span><br />
<br />
<span style="color: #66cc66;">&#125;</span></div></td></tr></tbody></table></div>
<p>For pure stubs I prefer the syntax of just using MetaClass.  I often don&#8217;t care about validating the exact calls to the dependent class so I don&#8217;t really want a full mock.  You don&#8217;t need a call to registerMetaClass() because mockFor() does this for you.</p>
<img src="http://feeds.feedburner.com/~r/MusingsOfASoftwareDevelopmentManager/~4/UzkGygDp2x4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://edgibbs.com/2011/04/17/grails-unit-testing-mocking-with-metaclass-stubs/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://edgibbs.com/2011/04/17/grails-unit-testing-mocking-with-metaclass-stubs/</feedburner:origLink></item>
		<item>
		<title>Developers and Desktop Databases</title>
		<link>http://feedproxy.google.com/~r/MusingsOfASoftwareDevelopmentManager/~3/DfWB6vidNoY/</link>
		<comments>http://edgibbs.com/2011/03/08/developers-and-desktop-databases/#comments</comments>
		<pubDate>Tue, 08 Mar 2011 14:26:07 +0000</pubDate>
		<dc:creator>Ed Gibbs</dc:creator>
				<category><![CDATA[software development]]></category>

		<guid isPermaLink="false">http://edgibbs.com/?p=891</guid>
		<description><![CDATA[<p>Typically development groups fall into one of two patterns:</p> Shared development database &#8211; every developer shares a single centralized development database often managed by a DBA group. Desktop databases &#8211; every developer has an individual instance of the database. <p>The practice has evolved over time and developers tend to follow precedence on it. Historically, developers [...]]]></description>
			<content:encoded><![CDATA[<p>Typically development groups fall into one of two patterns:</p>
<ul>
<li>Shared development database &#8211; every developer shares a single centralized development database often managed by a DBA group.</li>
<li>Desktop databases &#8211; every developer has an individual instance of the database.</li>
</ul>
<p>The practice has evolved over time and developers tend to follow precedence on it.  Historically, developers didn&#8217;t think of running a local database, primarily because of the resources involved.  Installing and running something like Oracle locally used to be a significant drag on a development machine.  You were already trying to run some sort of IDE that sucked up most of your machines resources so running the database locally wasn&#8217;t a great option.  If you were lucky enough to be running a pretty light weight database you might think about running a local copy, but otherwise you just setup a connection and shared the dev instance.</p>
<p>As machines have gotten quite capable of running databases, IDEs, and even virtual machines all at the same time the option to run a local copy of the database became very real.  In this case a number of developers began to install and run local copies of the database.  Running your own local copy quickly makes some development issues stand out:</p>
<ul>
<li>You have to learn a bit more about how your target database software is setup.  Suddenly it&#8217;s just not just a set of connection parameters.</li>
<li>You have to think about the best way to coordinate changes to the database model.  Making a lot of changes locally to apply later to the central dev integration instance is going to end in a lot of angry emails with how you broke the build.</li>
<li>You can quickly experiment with local changes to the database model without impacting the rest of the team.</li>
<li>You have a truly complete development environment, so if you take your laptop home at night, work remotely for the day, or get called for troubleshooting in the evening you can be effective without having to VPN into the dev database or drive into the office.</li>
</ul>
<p>I think the long term trend is most developers will run local instances of their target database.  This is almost standard in startups and newer organizations.  As a consultant I love having a complete development environment since I can run and demo the project at a moment&#8217;s notice.  The issues with integration are being addressed with approaches like database migrations in Rails and maintenance of DDL in source control, treating it like an equal member of the code.  I&#8217;ve also seen partial steps towards this model with the idea of in-memory local databases used for unit/integration testing where you use an ORM like Hibernate to build the database model on the fly whenever you need to run tests.</p>
<img src="http://feeds.feedburner.com/~r/MusingsOfASoftwareDevelopmentManager/~4/DfWB6vidNoY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://edgibbs.com/2011/03/08/developers-and-desktop-databases/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://edgibbs.com/2011/03/08/developers-and-desktop-databases/</feedburner:origLink></item>
		<item>
		<title>Spock Intro Tutorial</title>
		<link>http://feedproxy.google.com/~r/MusingsOfASoftwareDevelopmentManager/~3/tllctikRPkM/</link>
		<comments>http://edgibbs.com/2011/03/03/spock-intro-tutorial/#comments</comments>
		<pubDate>Thu, 03 Mar 2011 14:21:05 +0000</pubDate>
		<dc:creator>Ed Gibbs</dc:creator>
				<category><![CDATA[acceptence testing]]></category>
		<category><![CDATA[groovy]]></category>
		<category><![CDATA[software development]]></category>
		<category><![CDATA[test driven development]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://edgibbs.com/?p=887</guid>
		<description><![CDATA[ <p>I gave a presentation on Spock a very nice BDD framework in Groovy a few months back to our Groovy Users Group in Sacramento. After using it on a real world Grails project the last few months it has grown on me to become my go to testing framework for Groovy/Grails or Java projects. [...]]]></description>
			<content:encoded><![CDATA[<div align="center">
<img src="http://edgibbs.com/images/spock.jpg" />
</div>
<p>I gave a presentation on Spock a very nice BDD framework in Groovy a few months back to our Groovy Users Group in Sacramento.  After using it on a real world Grails project the last few months it has grown on me to become my go to testing framework for Groovy/Grails or Java projects.  A typical specification looks something like this:</p>
<div class="codecolorer-container groovy vibrant overflow-off" style="overflow: auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br /></div></td><td><div class="groovy codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20def"><span style="color: #000000; font-weight: bold;">def</span></a> <span style="color: #ff0000;">&quot;a pager should calculate total pages, current page, and offset&quot;</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; when: <span style="color: #ff0000;">&quot;count, rows and page number&quot;</span><br />
&nbsp; &nbsp; <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20def"><span style="color: #000000; font-weight: bold;">def</span></a> pager <span style="color: #66cc66;">=</span> <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20new"><span style="color: #000000; font-weight: bold;">new</span></a> Pager<span style="color: #66cc66;">&#40;</span><a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20count"><span style="color: #663399;">count</span></a>, rows, page<span style="color: #66cc66;">&#41;</span><br />
<br />
&nbsp; &nbsp; then: <span style="color: #ff0000;">&quot;should return correct total pages, the current page, and the offset&quot;</span><br />
&nbsp; &nbsp; pager.<span style="color: #006600;">totalPages</span> <span style="color: #66cc66;">==</span> totalPages<br />
&nbsp; &nbsp; pager.<span style="color: #006600;">currentPage</span> <span style="color: #66cc66;">==</span> currentPage<br />
&nbsp; &nbsp; pager.<span style="color: #006600;">offset</span> <span style="color: #66cc66;">==</span> offset<br />
<br />
&nbsp; &nbsp; where: <span style="color: #ff0000;">&quot;you have a number of different scenarios&quot;</span><br />
&nbsp; &nbsp; <a href="http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20count"><span style="color: #663399;">count</span></a> <span style="color: #66cc66;">|</span> rows <span style="color: #66cc66;">|</span> page <span style="color: #66cc66;">|</span> totalPages <span style="color: #66cc66;">|</span> currentPage <span style="color: #66cc66;">|</span> offset<br />
&nbsp; &nbsp; <span style="color: #cc66cc;">100</span> &nbsp; <span style="color: #66cc66;">|</span> <span style="color: #cc66cc;">10</span> &nbsp; <span style="color: #66cc66;">|</span> &nbsp; <span style="color: #cc66cc;">1</span> &nbsp;<span style="color: #66cc66;">|</span> &nbsp; &nbsp;<span style="color: #cc66cc;">10</span> &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">|</span> &nbsp; &nbsp; <span style="color: #cc66cc;">1</span> &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">|</span> &nbsp; <span style="color: #cc66cc;">0</span><br />
&nbsp; &nbsp; <span style="color: #cc66cc;">950</span> &nbsp; <span style="color: #66cc66;">|</span> <span style="color: #cc66cc;">100</span> &nbsp;<span style="color: #66cc66;">|</span> &nbsp; <span style="color: #cc66cc;">5</span> &nbsp;<span style="color: #66cc66;">|</span> &nbsp; &nbsp;<span style="color: #cc66cc;">10</span> &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">|</span> &nbsp; &nbsp; <span style="color: #cc66cc;">5</span> &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">|</span> &nbsp; <span style="color: #cc66cc;">400</span><br />
&nbsp; &nbsp; <span style="color: #cc66cc;">72</span> &nbsp; &nbsp;<span style="color: #66cc66;">|</span> <span style="color: #cc66cc;">20</span> &nbsp; <span style="color: #66cc66;">|</span> &nbsp; <span style="color: #cc66cc;">3</span> &nbsp;<span style="color: #66cc66;">|</span> &nbsp; &nbsp;<span style="color: #cc66cc;">4</span> &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">|</span> &nbsp; &nbsp; <span style="color: #cc66cc;">3</span> &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">|</span> &nbsp; <span style="color: #cc66cc;">40</span><br />
&nbsp; <span style="color: #66cc66;">&#125;</span></div></td></tr></tbody></table></div>
<p>If that passed your 5 second test take a look at a fuller introductory tutorial I put together.</p>
<p><a href="http://edgibbs.com/spock-intro-a-bdd-testing-framework-in-groovy/">A Gentle Introduction to Spock</a></p>
<p>And if you want to try out executing real code the project has a nice browser based environment at <a href="http://meetspock.appspot.com/">Meet Spock</a>.</p>
<img src="http://feeds.feedburner.com/~r/MusingsOfASoftwareDevelopmentManager/~4/tllctikRPkM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://edgibbs.com/2011/03/03/spock-intro-tutorial/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://edgibbs.com/2011/03/03/spock-intro-tutorial/</feedburner:origLink></item>
		<item>
		<title>AgileZen for Solo Remote Development</title>
		<link>http://feedproxy.google.com/~r/MusingsOfASoftwareDevelopmentManager/~3/UKrr6QgYb3w/</link>
		<comments>http://edgibbs.com/2011/01/23/agilezen-for-solo-remote-development/#comments</comments>
		<pubDate>Mon, 24 Jan 2011 04:55:33 +0000</pubDate>
		<dc:creator>Ed Gibbs</dc:creator>
				<category><![CDATA[project management]]></category>
		<category><![CDATA[scrum]]></category>
		<category><![CDATA[software development]]></category>

		<guid isPermaLink="false">http://edgibbs.com/?p=868</guid>
		<description><![CDATA[<p>Over the past few months I&#8217;ve been working on some remote projects as a solo developer. Knowing I wanted a light weight tracking tool I took some time to experiment with a few tools and I&#8217;ve recently come to appreciate the lightweight character of AgileZen.</p> <p>Despite many warnings to use the simplest thing that could [...]]]></description>
			<content:encoded><![CDATA[<p>Over the past few months I&#8217;ve been working on some remote projects as a solo developer.  Knowing I wanted a light weight tracking tool I took some time to experiment with a few tools and I&#8217;ve recently come to appreciate the lightweight character of <a href="http://agilezen.com/">AgileZen</a>.</p>
<p>Despite many warnings to use the simplest thing that could possibly work, often stickies on the wall or simple index cards, there have always been a number of options to translate these planning/tracking tools to software applications.  Despite settling on the power of physical wallboards for collocated teams throughout my career I have looked into using a number of tools for feasibility ultimately deciding none of them worked as well as a cork board and some stickies or index cards.  Tactile and visual cards rock.</p>
<p>Some of the tools I&#8217;ve looked at in the past include:</p>
<ul>
<li><a href="http://edgibbs.com/2005/08/22/pain-with-xplanner-part-ii/">XPlanner</a> (an very old tool in the space)</li>
<li><a href="http://edgibbs.com/2006/02/27/trying-out-basecamp/">Basecamp</a></li>
<li><a href="http://edgibbs.com/2007/06/15/sprint-backlog-task-boards-versus-spreadsheets/">Excel</a></li>
<li><a href="http://www.rallydev.com/">Rally</a></li>
<li><a href="http://edgibbs.com/2006/05/08/finally-tried-out-scrumworks/">Scrumworks</a></li>
<li><a href="https://www.pivotaltracker.com/">Pivotal Tracker</a></li>
<li><a href="http://trac.edgewall.org/">Trac</a></li>
<li><a href="http://www.mantisbt.org/">Mantis</a> (a bug tracking tool used for planning)</li>
</ul>
<p>I never felt any of them where worth the effort to maintain in the end despite many high hopes.  I&#8217;m not immune to tool fascination, but I tried to honestly evaluate the worthiness of the given tool.   As a manager much of my focus on this was to please stakeholders and other managers with a nice visual report that could be shared via email and web browsers.  In my Agile rollouts it turned out that I was ultimately more successful showing off my cork boards and cards.  We did maintain an Excel spreadsheet with backlogs as well to meet some documentation standards for PM groups.  It was a small compromise I was willing to live with.</p>
<p>My most recent projects presented me with a different challenge.  As a solo developer I&#8217;m largely on my own and not sharing the project tasks with anyone else, but I like to have an organized workflow at all times.  My home office doesn&#8217;t have much in the way of space for a nice corkboard, and again I wanted to fiddle with tools so I tried a few to see how they might work for me.</p>
<p>A first attempt was with <a href="http://www.pivotaltracker.com/">Pivotal Tracker</a>.  I love the things <a href="http://pivotallabs.com/">Pivotal</a> is doing out there with a focus on TDD/BDD, pair programming and producing high quality code.  Pivotal Tracker is a nicely polished tracking tool that largely simulates the idea of a wall board with an emphasis on iterations that contain a set number of story points.  It&#8217;s an opinionated piece of software with this and assumes that you are very concerned with ordering of stories based on points and how you pull them into the backlog.  After a lot of work trying to understand how it wants me to work I found it not a great fit as a solo developer.  It assumes you want to have tracker plan your iterations automatically based on your velocity.  In fact they admit that you can change some settings for the current iteration to allow you to drag stories in or out, but it will still automatically plan all the other iterations in the backlog.  In the end I might be up for trying it with a non-collocated team, but for a solo developer the overhead was a bit higher than I prefer.</p>
<p><a href="http://agilezen.com/">AgileZen</a> was my second attempt.  I remember from some old twitter and blog posts that several people had said it was a really nice lightweight tool.  I realized arriving at the site they had been acquired by Rally.  I&#8217;ve used Rally&#8217;s tools, but for collocated teams I didn&#8217;t really think the overhead of using Rally was worth it.  It appears that AgileZen is their attempt to provide a lighter more Kanban style tool.  I liked the little bonsai tree on the login and found more to like when I went in and attempted to setup my current project.  I watched the short series of screen casts showing how it worked, maybe 5-10 minutes in all.  After that I&#8217;ve been very productive without having to dig into any help.  The central metaphor is just a digital task board:</p>
<div align="center">
<img src="http://edgibbs.com/images/zen_board.gif" />
</div>
<p>Agile Zen focuses on the concept of cards and a board with very lightweight workflow.  You create a feature or user story and &#8216;hang the card on the wall&#8217;.  You then just move the card to progress it from the backlog to started.  You can do some customization, but the default workflow was perfect for me as a single developer.  It also looks like it works quite well for remote teams and appears to support more options like marking cards as ready or blocked.  I&#8217;ve even used the blocked status for a card once where I wanted to run a design idea by a colleague before I continued further on that particular story.  And I&#8217;m a sucker for some auto-generated stats, but it has a nice page where it calculates your throughput with a pretty graph.  It will take more time to see if the stats actually give me useful feedback, but did I mention they look nice:</p>
<div align="center">
<img src="http://edgibbs.com/images/zen_performance.gif" />
</div>
<p>Overall the tool feels closer to a digital taskboard than anything else I&#8217;ve experimented with.  I&#8217;d still use a physical task board for a collocated team, but for a team working in remote locations or a single developer I think it makes a very good electronic substitute.  Now if only it had an iPad version.  If you&#8217;re a solo developer feel free to try it yourself as it&#8217;s 1 project is free for a single developer.</p>
<img src="http://feeds.feedburner.com/~r/MusingsOfASoftwareDevelopmentManager/~4/UKrr6QgYb3w" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://edgibbs.com/2011/01/23/agilezen-for-solo-remote-development/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		<feedburner:origLink>http://edgibbs.com/2011/01/23/agilezen-for-solo-remote-development/</feedburner:origLink></item>
	</channel>
</rss>

