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

<channel>
	<title>Kerry Buckley &#187; Agile</title>
	<atom:link href="http://www.kerrybuckley.org/category/software/agile/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.kerrybuckley.org</link>
	<description>What's the simplest thing that could possibly go wrong?</description>
	<lastBuildDate>Wed, 30 Nov 2011 11:26:56 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Design by Example or Test-Driven Development?</title>
		<link>http://www.kerrybuckley.org/2009/04/28/design-by-example-or-test-driven-development/</link>
		<comments>http://www.kerrybuckley.org/2009/04/28/design-by-example-or-test-driven-development/#comments</comments>
		<pubDate>Tue, 28 Apr 2009 19:39:16 +0000</pubDate>
		<dc:creator>Kerry</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[tdd bdd dbe]]></category>

		<guid isPermaLink="false">http://www.kerrybuckley.org/?p=274</guid>
		<description><![CDATA[Brad Wilson argues the case for renaming TDD to &#8216;Design by Example&#8217; (or DbE), to emphasise the fact that TDD (and BDD, which is really just TDD done well) are about design rather than testing. I agree with the intention, but I&#8217;m not sure I agree. I&#8217;m happy to lose the &#8216;test&#8217; &#038;ndash it&#8217;s losing [...]]]></description>
			<content:encoded><![CDATA[<p>Brad Wilson <a href="http://bradwilson.typepad.com/blog/2009/04/its-not-tdd-its-design-by-example.html">argues the case</a> for renaming TDD to &#8216;Design by Example&#8217; (or DbE), to emphasise the fact that TDD (and BDD, which is really just TDD done well) are about design rather than testing.</p>
<p>I agree with the intention, but I&#8217;m not sure I agree. I&#8217;m happy to lose the &#8216;test&#8217; &#038;ndash it&#8217;s losing the &#8216;development&#8217; that bothers me. I&#8217;ve encountered far too many &#8216;designers&#8217; who haven&#8217;t written a line of code in years, and I worry that they&#8217;d read &#8216;design by example&#8217; as simply starting their design document with a few test cases. I&#8217;ve already seen TDD redefined as test-driven <strong>design</strong> and interpreted that way.</p>
<p>Of course for people who already grok TDD this isn&#8217;t an issue, but it&#8217;s not them that a name change is aimed at. Test-driven development might not be the perfect name, but at least there are already plenty of people who <em>do</em> understand what it really means to correct any misapprehension. The term BDD (which I use myself from time to time) has already started sowing confusion, without adding yet another.</p>
<p>On the other hand, anything that gets people discussing how to get the most from the practice has to be a good thing.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrybuckley.org/2009/04/28/design-by-example-or-test-driven-development/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Agile in 25 Words</title>
		<link>http://www.kerrybuckley.org/2008/07/22/agile-in-25-words/</link>
		<comments>http://www.kerrybuckley.org/2008/07/22/agile-in-25-words/#comments</comments>
		<pubDate>Tue, 22 Jul 2008 08:03:13 +0000</pubDate>
		<dc:creator>Kerry</dc:creator>
				<category><![CDATA[Agile]]></category>

		<guid isPermaLink="false">http://www.kerrybuckley.org/2008/07/22/agile-in-25-words/</guid>
		<description><![CDATA[I realise I&#8217;m a bit late to the party, but following the example of JP, psd, Eastmad and Casablanca, I thought I&#8217;d have a stab at the 25 words challenge. Not feeling sufficiently inspired to come up with anyhing original and profound, here&#8217;s my attempt at boiling the principles of agile software development down into [...]]]></description>
			<content:encoded><![CDATA[<p>I realise I&#8217;m a bit late to the party, but following the example of <a href="http://confusedofcalcutta.com/2008/07/19/25-words/">JP</a>, <a href="http://blog.whatfettle.com/2008/07/20/25-words/">psd</a>, <a href="http://eastman1.blogspot.com/2008/07/25-words.html">Eastmad</a> and <a href="http://philwhitehouse.blogspot.com/2008/07/25-words.html">Casablanca</a>, I thought I&#8217;d have a stab at the <a href="http://www.successful-blog.com/1/writing-project-25-words-of-work-life-wisdom/">25 words</a> challenge. Not feeling sufficiently inspired to come up with anyhing original and profound, here&#8217;s my attempt at boiling the <a href="http://agilemanifesto.org/principles.html">principles of agile software development</a> down into 25 words:</p>
<div style="border: 1px solid #88c; background-color: #ccf; padding: 10px; margin: 10px; font-weight: bold">With customers, deliver valuable software early and often. Welcome change. Talk. Trust people to self-organise. Maintain pace, quality, simplicity and good design. Iterate; reflect; improve.</div>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrybuckley.org/2008/07/22/agile-in-25-words/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>On being beaten with carrots</title>
		<link>http://www.kerrybuckley.org/2008/04/22/on-being-beaten-with-carrots/</link>
		<comments>http://www.kerrybuckley.org/2008/04/22/on-being-beaten-with-carrots/#comments</comments>
		<pubDate>Tue, 22 Apr 2008 13:11:23 +0000</pubDate>
		<dc:creator>Kerry</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Enterprise]]></category>
		<category><![CDATA[Rants]]></category>

		<guid isPermaLink="false">http://www.kerrybuckley.org/2008/04/22/on-being-beaten-with-carrots/</guid>
		<description><![CDATA[Traditional approaches to motivation tend to fall into one of two camps: the carrot ("do this and you'll be rewarded") or the stick ("do this or you'll suffer the consequences"). I guess I'm fortunate to work for a company (and in a country) where by and large there isn't a culture of firing people who [...]]]></description>
			<content:encoded><![CDATA[<p><img src='http://www.kerrybuckley.org/wp-content/uploads/2008/04/carrots.jpg' alt='Carrots' style="float: left; margin:0 10px 10px 0" />Traditional approaches to motivation tend to fall into one of two camps: the carrot ("do this and you'll be rewarded") or the stick ("do this or you'll suffer the consequences").</p>
<p>I guess I'm fortunate to work for a company (and in a country) where by and large there isn't a culture of firing people who don't meet performance targets &ndash; instead we have a system where an ever-increasing proportion of people's pay packet is made up of a performance-related bonus, rather than a fixed salary.</p>
<p>So, how do you go about getting your bonus each quarter? Simple: just meet your agreed targets.</p>
<p>Of course, nothing in a large corporation can ever be that simple, so in practice there's a complex tiered system of company, business unit, programme, project, team and individual targets, which are combined in a magic spreadsheet to generate how much bonus everyone gets. Each of these targets, and the performance against them, has to be agreed, monitored, quantified, audited and levelled. At each stage politics comes into play. Those that enjoy playing systems try to set targets they know they can achieve. People concentrate on meeting the letter of the objectives, possibly to the detriment of other activities, like helping colleagues or making process improvements.</p>
<p>Now step away from this corporate dystopia for a moment, into the world of Agile Software Development. A world where we <a href="http://agilemanifesto.org/">value</a> <em>Individuals and interactions over processes and tools</em>, and <em>Responding to change over following a plan</em>. A world where we <a href="http://agilemanifesto.org/principles.html">strive to</a> <em>build projects around motivated individuals, give them the environment and support they need, and trust them to get the job done</em>. Where <em>working software is the primary measure of progress</em>. Where <em>at regular intervals, the team reflects on how to become more effective, then tunes and adjusts its behavior accordingly</em>. Where the self-organising team, accountable directly to it customer or product owner, is responsible for its own delivery and processes.</p>
<p>Now, when agile teams in large organisations are forced to jump through the externally-imposed hoops of objectives, development action plans and post-implementation reviews (which add little visible benefit and take up time that could be spent delivering business value), is it any wonder that the carrot of performance-related pay feels like it's more of a punishment than an incentive?</p>
<p>Technorati Tags: <a href="http://technorati.com/tag/agile" rel="tag">agile</a>, <a href="http://technorati.com/tag/performance+management" rel="tag">performance management</a>, <a href="http://technorati.com/tag/enterprise" rel="tag">enterprise</a>, <a href="http://technorati.com/tag/corporate" rel="tag">corporate</a>, <a href="http://technorati.com/tag/hr" rel="tag">hr</a></p>
<p><span style="font-size: 0.7em;font-style: italic">Public domain photo from <a href="http://commons.wikimedia.org/wiki/Image:Carrots_of_many_colors_cutout.jpg">Wikimedia Commons</a>.</span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrybuckley.org/2008/04/22/on-being-beaten-with-carrots/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>InfoWorld Article on BT and Agile</title>
		<link>http://www.kerrybuckley.org/2008/03/12/infoworld-article-on-bt-and-agile/</link>
		<comments>http://www.kerrybuckley.org/2008/03/12/infoworld-article-on-bt-and-agile/#comments</comments>
		<pubDate>Wed, 12 Mar 2008 09:52:49 +0000</pubDate>
		<dc:creator>Kerry</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[BT]]></category>

		<guid isPermaLink="false">http://kerry.ontoa.st/2008/03/12/infoworld-article-on-bt-and-agile/</guid>
		<description><![CDATA[Some time last year I was interviewed by Tom Hoffman for Infoworld, as part of a piece he was writing on BT's (ongoing) transition to an agile software development model. Here's the article: BT: A case study in agile programming]]></description>
			<content:encoded><![CDATA[<p>Some time last year I was interviewed by Tom Hoffman for Infoworld, as part of a piece he was writing on BT's (ongoing) transition to an agile software development model. Here's the article:</p>
<p><a href="http://www.infoworld.com/article/08/03/11/BT-a-case-study-in-agile-programming_1.html">BT: A case study in agile programming</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrybuckley.org/2008/03/12/infoworld-article-on-bt-and-agile/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Government IT waste</title>
		<link>http://www.kerrybuckley.org/2008/01/05/government-it-waste/</link>
		<comments>http://www.kerrybuckley.org/2008/01/05/government-it-waste/#comments</comments>
		<pubDate>Sat, 05 Jan 2008 14:43:25 +0000</pubDate>
		<dc:creator>Kerry</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Rants]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.kerrybuckley.com/2008/01/05/government-it-waste/</guid>
		<description><![CDATA[There's an article in today's Guardian called Not fit for purpose: £2bn cost of government's IT blunders, with the following summary: The cost to the taxpayer of abandoned Whitehall computer projects since 2000 has reached almost £2bn - not including the bill for an online crime reporting site that was cancelled this week, a survey [...]]]></description>
			<content:encoded><![CDATA[<p><img src='/wp-content/uploads/2008/01/money_down_drain.jpg' alt='Money down the drain' style='float:left;margin:0 10px 10px 0' />There's an article in today's Guardian called <em><a href="http://www.guardian.co.uk/technology/2008/jan/05/computing.egovernment">Not fit for purpose: £2bn cost of government's IT blunders</a></em>, with the following summary:</p>
<blockquote><p>The cost to the taxpayer of abandoned Whitehall computer projects since 2000 has reached almost £2bn - not including the bill for an online crime reporting site that was cancelled this week, a survey by the Guardian reveals.</p></blockquote>
<p>I have no doubt whatsoever that the government wastes a vast amount on IT contracts, but I think that, by concentrating on the cost of cancelled projects, the article misses the point slightly.</p>
<p>If a project is clearly never going to deliver, it's far better to cancel it than to fall into the trap of the <a href="http://en.wikipedia.org/wiki/Sunk_cost#Loss_aversion_and_the_sunk_cost_fallacy">sunk cost fallacy</a>, and keep pouring money in in the hope that eventually everything will turn out OK in the end.</p>
<p>The real questions for me are 'are the government's IT needs being met at the most cost-effective manner?' and 'why does it take so long to realise that a project is doomed?'</p>
<p>I don't know anything about the projects discussed in the article, or about how government IT contracts are handled in general, but I'd be willing to bet that the following guesses aren't too wide of the mark:</p>
<ul>
<li>Someone decides that a new system is required, and produces a huge list of everything they think it needs to do. This goes out to tender, and the job goes to whoever manages to produce the lowest quote while still giving a reasonably credible impression that they can actually complete the work in the specified time.</li>
<li>The contractor goes off and starts work. They talk to the civil servants who are responsible for specifying the system, but probably not to the people who will actually have to use it. They then go off and produce a design, get it signed off, and set up teams to work on all the identified subsystems.</li>
<li>Every few months they deliver a progress report, assuring the client that everything's progressing according to plan. After a year or so the schedule probably slips a bit, but they assure everyone that it's jsut a blip, and the final delivery won't be significantly affected (we can always trim the testing phase a little, right?)</li>
<li>Because the contract fixed time, cost and scope, there's only one thing that can be adjusted to keep the project profitable when the estimates turn out to have been optimistic: quality. Of course this ripples forward, with more and more time spent chasing problems caused by poor quality work in existing parts of the system.</li>
<li>When (eventually) the first version of the system is delivered, there are integration problems, it doesn't quite do what the people specifying it actually wanted, and it turns out that large parts of the specification weren't that important, but some vital features have been missed out altogether. Depending on just how big a disaster it all was, one of two things happens:</li>
<ul>
<li>The project gets cancelled. The contractor moves on to the next lucrative contract, and an enquiry's set up to investigate the specific reasons for the project failure, completely missing the big picture.</li>
<li>The problems are slowly ironed out, and the missing features are added to the requirements for the next release. The contractor rubs its collective hands at the thought of the massive fees they can charge for the change requests, and a huge amount of time is wasted arguing about whether each change is a new feature or a bug request.</li>
</ul>
</ul>
<p>I'm not (quite) naive enough to suggest that all these problems could be solved by wholesale adoption of <a href="http://en.wikipedia.org/wiki/Extreme_Programming">XP</a>, but I get the impression that the government (and the media reporting on these fiascos) isn't even aware that there is a better way. With major companies adopting an agile approach now (or at least <a href="http://www.think-box.co.uk/blog/2007/11/xpday7-have-you-compromised-your.html">pretending to</a>), how long before the people responsible for spending our taxes wake up?</p>
<p>Technorati Tags: <a href="http://technorati.com/tag/government" rel="tag">government</a>, <a href="http://technorati.com/tag/it" rel="tag">it</a>, <a href="http://technorati.com/tag/waste" rel="tag">waste</a>, <a href="http://technorati.com/tag/agile" rel="tag">agile</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrybuckley.org/2008/01/05/government-it-waste/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>The Neglected Practice of Iteration</title>
		<link>http://www.kerrybuckley.org/2007/12/19/the-neglected-practice-of-iteration/</link>
		<comments>http://www.kerrybuckley.org/2007/12/19/the-neglected-practice-of-iteration/#comments</comments>
		<pubDate>Wed, 19 Dec 2007 09:40:20 +0000</pubDate>
		<dc:creator>Kerry</dc:creator>
				<category><![CDATA[Agile]]></category>

		<guid isPermaLink="false">http://www.kerrybuckley.com/2007/12/19/the-neglected-practice-of-iteration/</guid>
		<description><![CDATA["It's not iteration if you only do it once." I've already mentioned Jeff Patton's XPDay keynote, where he talked about the importance of working in iterations (as opposed to increments). Jeff has now written a column, The Neglected Practice of Iteration, on StickyMinds, making the same point (but without the music!) Excellent stuff, and well [...]]]></description>
			<content:encoded><![CDATA[<p><em>"It's not iteration if you only do it once."</em></p>
<p>I've already mentioned <a href="/2007/11/21/xpday-7-jeff-patton-keynote-embrace-uncertainty/">Jeff Patton's XPDay keynote</a>, where he talked about the importance of working in iterations (as opposed to increments). Jeff has now written a column, <em><a href="http://www.stickyminds.com/sitewide.asp?Function=edetail&#038;ObjectType=COL&#038;ObjectId=13178&#038;tth=DYN&#038;tt=siteemail&#038;iDyn=37">The Neglected Practice of Iteration</a></em>, on StickyMinds, making the same point (but without the music!)</p>
<p>Excellent stuff, and well worth a read. I suspect most people who claim to follow an iterative development process are prone to lapsing into an incremental mentality &ndash; I know I am.</p>
<p>Technorati Tags: <a href="http://technorati.com/tag/Jeff+Patton" rel="tag">Jeff Patton</a>, <a href="http://technorati.com/tag/iteration" rel="tag"> iteration</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrybuckley.org/2007/12/19/the-neglected-practice-of-iteration/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[XPday 7] The Informed Coding Dojo</title>
		<link>http://www.kerrybuckley.org/2007/11/21/xpday-7-the-informed-coding-dojo/</link>
		<comments>http://www.kerrybuckley.org/2007/11/21/xpday-7-the-informed-coding-dojo/#comments</comments>
		<pubDate>Wed, 21 Nov 2007 10:47:20 +0000</pubDate>
		<dc:creator>Kerry</dc:creator>
				<category><![CDATA[Agile]]></category>

		<guid isPermaLink="false">http://www.kerrybuckley.com/2007/11/21/xpday-7-the-informed-coding-dojo/</guid>
		<description><![CDATA[This session was run by Karl Scotland &#038; Johanna Hunt. I helped run a coding dojo at work for a while, until it just kind of fizzled out, so I was interested to see how someone else approached it. The twist was that the dojo was run using Inform 6, which is a domain-specific language [...]]]></description>
			<content:encoded><![CDATA[<p>This <a href="http://www.xpday.org/node/122">session</a> was run by Karl Scotland &#038; Johanna Hunt. I helped run a <a href="http://codingdojo.org/cgi-bin/wiki.pl?WhatIsCodingDojo">coding dojo</a> at work for a while, until it just kind of fizzled out, so I was interested to see how someone else approached it.</p>
<p>The twist was that the dojo was run using <a href="http://www.inform-fiction.org/inform6.html">Inform 6</a>, which is a domain-specific language for writing text-based adventure games ("You are in a maze of twisty little passages, all alike..."). this meant that none of the participants were familiar with the language, which forced us to take very small steps rather than quickly hacking together large chunks of code based on experience.</p>
<p>The baby steps thing seemed to work quite well, helped by the strict five minute pair rotations (driver back to audience, navigator to driver, audience member to navigator). Those rotations weren't quite like the way we used to do it (we never really settled on a fixed policy, and experimented with <a href="http://www.stickyminds.com/sitewide.asp?Function=WEEKLYCOLUMN&#038;ObjectId=9101&#038;ObjectType=ARTCOL&#038;btntopic=artcol">ping-pong pairing</a>, swapping both people out of the pair at once and increasing timeslots to ten minutes). We also weren't as strict about banning suggestions and comments from the floor &ndash; stopping that seemed to help avoid circular conversations and let the pair get on with coding, although the unusual language may have helped here too. It was very frustrating though when you could see an mistake that was causing compilation errors, but the pair hadn't seen it yet.</p>
<p>As it turned out we only got about halfway through the tasks we'd been set. It was quite an enjoyable hour and a half, but I'm not sure how much I learned.</p>
<p>Technorati Tags: <a href="http://technorati.com/tag/xpday" rel="tag">xpday</a>, <a href="http://technorati.com/tag/coding+dojo" rel="tag"> coding dojo</a>, <a href="http://technorati.com/tag/pair+programming" rel="tag"> pair programming</a>, <a href="http://technorati.com/tag/inform6" rel="tag"> inform6</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrybuckley.org/2007/11/21/xpday-7-the-informed-coding-dojo/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[XPday 7] Jeff Patton Keynote: &#8220;Embrace Uncertainty&#8221;</title>
		<link>http://www.kerrybuckley.org/2007/11/21/xpday-7-jeff-patton-keynote-embrace-uncertainty/</link>
		<comments>http://www.kerrybuckley.org/2007/11/21/xpday-7-jeff-patton-keynote-embrace-uncertainty/#comments</comments>
		<pubDate>Wed, 21 Nov 2007 10:01:16 +0000</pubDate>
		<dc:creator>Kerry</dc:creator>
				<category><![CDATA[Agile]]></category>

		<guid isPermaLink="false">http://www.kerrybuckley.com/2007/11/21/xpday-7-jeff-patton-keynote-embrace-uncertainty/</guid>
		<description><![CDATA[Jeff gave an entertaining presentation on strategies for coping with the inevitable changes that take place during a project release. The talk was punctuated with blasts of music from various artists filling in as personas, from Mel B as a developer capturing user stories ("So tell me what you want, what you really really want") [...]]]></description>
			<content:encoded><![CDATA[<p>Jeff gave <a href="http://www.xpday.org/keynotes">an entertaining presentation</a> on strategies for coping with the inevitable changes that take place during a project release. The talk was punctuated with blasts of music from various artists filling in as personas, from Mel B as a developer capturing user stories ("So tell me what you want, what you really really want") to Johnny Rotten as an experienced agile practitioner ("Don't know what I want, but I know how to get it").</p>
<p>Many companies are now adopting agile methodologies such as Scrum to jump on the agile bandwagon, and are looking for consultants to provide training, and to come in and tell them all the answers to their problems. Because they are looking for prescriptive processes that they can put in place for people to follow, we are starting to see ever-more complex systems for things that were previously considered simple tasks (such as prioritising user stories). This is what Fred Brooks referred to in <em>No Silver Bullet</em> as 'accidental complexity' &ndash; complexity in the activities around writing software, rather than in the domain of the business problem you're supposed to be solving.</p>
<p><strong>Is this process rigor, or rigor mortis?</strong></p>
<p>We have forgotten the meaning of iteration, and are working in increments instead. We are expecting an 'iteration' to contain a number of fully-completed stories, which we can then forget about and move on to new features. The problem with this is that when we deliver those stories, the customer is not entirely satisfied, and we have to introduce new stories to refine the design. This in turn affects our velocity, because we find ourselves spending more and more of our time enhancing features that we thought were done.</p>
<p><strong>It's not iteration if you only do it once.</strong></p>
<p>Alastair Cockburn has suggested a 'three story' approach, where you make the iteration explicit by putting two additional cards behind each user story &ndash; one to fix the original story, and another to fix the second attempt. Jeff's only concern with this was that people might take it too literally, doind a seond rework even if the customer was already happy, or stopping after the third story when the feature clearly wasn't really done.</p>
<p>Along with YAGNI, Jeff suggested adding YAGRI (you ain't gonna release it). This was to remind us that it's OK to present non-production features to the customer, in the knowledge that they won't be released until they've been iterated into a deliverable state. To me that seems OK for shrink-wrapped software and other things where iterations aren't released, but I wonder how it applies to web applications, where it is becoming the norm to release small changes frequently (perhaps multiple times per iteration). In that case, we're used to making the assumption that everything is always releasable. Maybe the answer is to separate new, 'beta-quality' features from the main body of functionality.</p>
<p>Three strategies for coping with the inevitable uncertainties in building a release were described:</p>
<h5>Follow the Money</h5>
<p>Prioritise the business goals. By focussing on the things with the highest value to the business you restrict the user constituencies which you should target first, and hence identify the highest priority user stories.</p>
<h5>Don't Choose the Solution Too Early</h5>
<p>Focus on the user goals rather than the perceived requirements on the application, and consider and discuss alternative ways of meeting those goals. It may be that a simpler or cheaper implementation than the immediately-obvious one may be sufficient.</p>
<h5>Build up Quality in Iterations</h5>
<p>Sometimes the customer really does need everything to be implemented before the product can be released. In this situation, you can start by implementing stories to a very basic, almost prototype, level. You then build up the quality iteratively, using feedback from the rough-cut implementations to guide you. One way of doing this is to grade each story (eg A+ down to F, plus I for incomplete), then have a 'passing grade' at which the feature is considered fit for release.</p>
<p>One consequence of actually iterating, rather than using 'iteration' as a label for an incrementl chunk of functionality, is that there's a lot more work for the customer (or product owner, or whatever you want to call them). They need to work frequently with the developers to evaluate each version of a story's implementation and describe the changes necessary to make it fit their needs.</p>
<p>The summary of the talk was to <strong>question common practice</strong> and to <strong>trust your instincts</strong>. As an aside, that leads into a rant I keep meaning to get round to, on the subject of people who say that a particular behaviour "isn't agile", because it doesn't fit the letter of their particular methodology of choice. Watch this space.</p>
<p>Technorati Tags: <a href="http://technorati.com/tag/xpday" rel="tag">xpday</a>, <a href="http://technorati.com/tag/iteration" rel="tag"> iteration</a>, <a href="http://technorati.com/tag/agile" rel="tag"> agile</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrybuckley.org/2007/11/21/xpday-7-jeff-patton-keynote-embrace-uncertainty/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Driving Selenium from the RSpec Story Runner (RBehave)</title>
		<link>http://www.kerrybuckley.org/2007/11/07/driving-selenium-from-the-rspec-story-runner-rbehave/</link>
		<comments>http://www.kerrybuckley.org/2007/11/07/driving-selenium-from-the-rspec-story-runner-rbehave/#comments</comments>
		<pubDate>Wed, 07 Nov 2007 11:57:27 +0000</pubDate>
		<dc:creator>Kerry</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.kerrybuckley.com/2007/11/07/driving-selenium-from-the-rspec-story-runner-rbehave/</guid>
		<description><![CDATA[[Update] The story runner is now included in the 1.1 release of RSpec, so a lot of the hackery mentioned below is no longer required. See http://rspec.info/ for details. Background A while ago I cobbled together some code to drive Selenium from Exactor (which was the acceptance testing framework we were using at the time). [...]]]></description>
			<content:encoded><![CDATA[<p><strong>[Update] The story runner is now included in the 1.1 release of RSpec, so a lot of the hackery mentioned below is no longer required. See <a href="http://rspec.info/">http://rspec.info/</a> for details.</strong></p>
<h3>Background</h3>
<p>A while ago I cobbled together some code to <a href="/2006/11/16/integrating-selenium-with-exactor/">drive Selenium from Exactor</a> (which was the acceptance testing framework we were using at the time). That project was offshored shortly afterwards, and I'm pretty sure Selenium never actually got integrated into the build (sneaking a peek at the continuous integration server reveals that even the pre-Selenium acceptance test build hasn't run successfully for months), but I was convinced of the value of Selenium for testing non-trivial web applications.</p>
<p>On my next project (the <a href="http://web21c.bt.com/">Web21C SDK portal</a>) we used <a href="http://www.openqa.org/selenium-on-rails/">Selenium on Rails</a> heavily for automated acceptance testing. This worked well, although the fact that the tests are deployed with the application limits what you can do &ndash; you can't interrogate the database after a test, for example, or dynamically set up stubs for systems you interface with (unless you also deploy the stubs as part of the application, and drive them from the browser).</p>
<p>With <a href="http://mojo.bt.com/about">Mojo</a> there's an additional complication: as well as being accessible through a browser, most functionality is also available as a RESTful API, using digest-based authentication. To keep our acceptance tests in one place, we wanted to be able to drive a browser using Selenium, alongside other tests which talked to the server directly. The obvious answer was to use <a href="http://www.openqa.org/selenium-rc/">Selenium Remote Control</a>, and I also liked the look of RBehave, which has now been incorporated into RSpec (but not released yet).</p>
<h3>The RSpec story runner</h3>
<p>The story runner in the upcoming release of <a href="http://rspec.rubyforge.org/">RSpec</a> is an evolution of Dan North's <a href="http://rubyforge.org/projects/rbehave/">RBehave</a>, which in turn is based on <a href="http://jbehave.org/">JBehave</a> (from the same author). In the past couple of weeks, David Chelimsky has done some excellent work on extracting the text of stories from the code, leading to the <a href="http://blog.davidchelimsky.net/articles/2007/10/25/plain-text-stories-part-iii">plain text story runner</a>.</p>
<p>Read on for the gory details of my solution to running Selenium tests from the story runner.<br />
<span id="more-181"></span></p>
<h3>Putting it all together</h3>
<p>Here's what I did to get Selenium working from the story runner (you need to check out RSpec <a href="http://rspec.rubyforge.org/svn/trunk/">trunk</a> &ndash; I'm currently using r2791 of rspec and r2814 or rspec_on_rails).</p>
<p>I'm sure when the next release of RSpec comes out a lot of this will be unnecessary, and there will probably be standard places for the stories and ways of running them, but for now I've just hacked something together that's simple and works. Apologies for any pieces of string or duct tape that are still showing!</p>
<p>The files described below are laid out as follows, relative to the root of the Rails project:</p>
<pre>
+-- lib
| +-- rspec/
| +-- rspec_on_rails/
| +-- selenium-ruby-client-driver/
| | +-- selenium.rb
| +-- selenium-server/
| | +-- selenium-server.jar
| +-- tasks/
|   +-- acceptance.rake
+-- stories/
| +-- all.rb
| +-- helper.rb
| +-- steps/
| | +-- login.rb
| | +-- selenium.rb
| +-- stories/
| | +-- login.rb
| | +-- login.txt
</pre>
<p>Here's an example story:</p>
<h4>stories/stories/login.txt</h4>
<div class="igBar"><span id="lruby-8"><a href="#" onclick="javascript:showCodeTxt('ruby-8'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">RUBY:</span>
<div id="ruby-8">
<div class="ruby">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">Story: Login</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; The front page should contain a login form</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; Scenario: Loading the home page <span style="color:#9966CC; font-weight:bold;">when</span> <span style="color:#9966CC; font-weight:bold;">not</span> logged <span style="color:#9966CC; font-weight:bold;">in</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">When</span> the user goes to /</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">Then</span> the title should be 'mojo'</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">And</span> the page should contain the text 'Welcome to mojo'</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">And</span> the page should contain the text 'Sign <span style="color:#9966CC; font-weight:bold;">in</span> using your OpenID'</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">And</span> there should be a field named 'openid_url'</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">And</span> there should be a submit button named 'login', with the label 'Sign <span style="color:#9966CC; font-weight:bold;">In</span>'</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; </div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; Scenario: Logging <span style="color:#9966CC; font-weight:bold;">in</span> with an unregistered OpenID URL</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">When</span> the user goes to /</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">And</span> the user types 'some.<span style="color:#9900CC;">openid</span>.<span style="color:#9900CC;">provider</span>' into the openid_url field</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">And</span> the user clicks the login button</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">Then</span> the page should contain the text 'Could <span style="color:#9966CC; font-weight:bold;">not</span> find OpenID server'</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">And</span> the page should contain the text 'Sign <span style="color:#9966CC; font-weight:bold;">in</span> using your OpenID'</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; </div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; Scenario: Logging <span style="color:#9966CC; font-weight:bold;">in</span> successfully</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; Given a <span style="color:#CC0066; font-weight:bold;">test</span> user</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">When</span> the user goes to /</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">And</span> the user types 'http://dummy.<span style="color:#9900CC;">openid</span>/' into the openid_url field</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">And</span> the user clicks the login button</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">Then</span> the page should contain the text 'Hi <span style="color:#CC0066; font-weight:bold;">test</span>' </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Each 'Given', 'When' and 'Then' corresponds to a step (an 'And' is just syntactic sugar for a repeat of the same type of step). The steps are defined in separate files, which can be included as required (see below). This story uses two sets of steps:</p>
<h4>stories/steps/login.rb</h4>
<div class="igBar"><span id="lruby-9"><a href="#" onclick="javascript:showCodeTxt('ruby-9'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">RUBY:</span>
<div id="ruby-9">
<div class="ruby">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">steps_for<span style="color:#006600; font-weight:bold;">&#40;</span>:login<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; Given <span style="color:#996600;">"a test user"</span> <span style="color:#9966CC; font-weight:bold;">do</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; User.<span style="color:#9900CC;">delete_all</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; User.<span style="color:#9900CC;">create</span>!<span style="color:#006600; font-weight:bold;">&#40;</span>:username =&gt; '<span style="color:#CC0066; font-weight:bold;">test</span>', :openid_url =&gt; 'http://dummy.<span style="color:#9900CC;">openid</span>/',</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; :fullname =&gt; '<span style="color:#CC0066; font-weight:bold;">Test</span> User', :email =&gt; '<span style="color:#CC0066; font-weight:bold;">test</span>@example.<span style="color:#9900CC;">com</span>',</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; :mobile =&gt; '<span style="color:#006666;color:#800000;">0123456789</span>'<span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># ActiveRecord::Base.connection.commit_db_transaction</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#9966CC; font-weight:bold;">end</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<h4>stories/steps/selenium.rb</h4>
<div class="igBar"><span id="lruby-10"><a href="#" onclick="javascript:showCodeTxt('ruby-10'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">RUBY:</span>
<div id="ruby-10">
<div class="ruby">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">steps_for<span style="color:#006600; font-weight:bold;">&#40;</span>:selenium<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color:#9966CC; font-weight:bold;">When</span> <span style="color:#996600;">"the user goes to $path"</span> <span style="color:#9966CC; font-weight:bold;">do</span> |path|</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; $selenium.<span style="color:#CC0066; font-weight:bold;">open</span> path</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color:#9966CC; font-weight:bold;">When</span> <span style="color:#996600;">"the user types '$text' into the $field field"</span> <span style="color:#9966CC; font-weight:bold;">do</span> |text, field|</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; $selenium.<span style="color:#9900CC;">type</span> field, text</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color:#9966CC; font-weight:bold;">When</span> <span style="color:#996600;">"the user clicks the $button button"</span> <span style="color:#9966CC; font-weight:bold;">do</span> |button|</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; $selenium.<span style="color:#9900CC;">click</span> button</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; $selenium.<span style="color:#9900CC;">wait_for_page_to_load</span> <span style="color:#006666;color:#800000;">5000</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color:#9966CC; font-weight:bold;">Then</span> <span style="color:#996600;">"the title should be '$title'"</span> <span style="color:#9966CC; font-weight:bold;">do</span> |title|</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; $selenium.<span style="color:#9900CC;">title</span>.<span style="color:#9900CC;">should</span> == title</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color:#9966CC; font-weight:bold;">Then</span> <span style="color:#996600;">"the page should contain the text '$text'"</span> <span style="color:#9966CC; font-weight:bold;">do</span> |text|</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; $selenium.<span style="color:#9900CC;">should</span> have_text_present<span style="color:#006600; font-weight:bold;">&#40;</span>text<span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color:#9966CC; font-weight:bold;">Then</span> <span style="color:#996600;">"there should be a field named '$field'"</span> <span style="color:#9966CC; font-weight:bold;">do</span> |field|</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; $selenium.<span style="color:#9900CC;">should</span> have_element_present<span style="color:#006600; font-weight:bold;">&#40;</span>field<span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color:#9966CC; font-weight:bold;">Then</span> <span style="color:#996600;">"there should be a submit button named '$name', with the label '$label'"</span> <span style="color:#9966CC; font-weight:bold;">do</span> |name, label|</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; $selenium.<span style="color:#9900CC;">should</span> have_element_present<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">"//input[@type='submit'][@name='#{name}'][@value='#{label}']"</span><span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#9966CC; font-weight:bold;">end</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Note the use of placeholder parameters, which are parsed out of the lines in the story. The Selenium steps use a global instance of <code>Selenium::SeleniumDriver</code>, which is created in the helper (again, see below). I originally created this in a "Given a browser" step, but it seemed simpler to just create it up front, before running the stories.</p>
<h4>stories/stories/login.rb</h4>
<div class="igBar"><span id="lruby-11"><a href="#" onclick="javascript:showCodeTxt('ruby-11'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">RUBY:</span>
<div id="ruby-11">
<div class="ruby">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#CC0066; font-weight:bold;">require</span> File.<span style="color:#9900CC;">expand_path</span><span style="color:#006600; font-weight:bold;">&#40;</span>File.<span style="color:#9900CC;">dirname</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">__FILE__</span><span style="color:#006600; font-weight:bold;">&#41;</span> + '/../helper'<span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">run_story_with_steps_for :selenium, :login </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>This is just a wrapper for the textual story, which specifies which steps are required.</p>
<h4>stories/all.rb</h4>
<div class="igBar"><span id="lruby-12"><a href="#" onclick="javascript:showCodeTxt('ruby-12'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">RUBY:</span>
<div id="ruby-12">
<div class="ruby">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">dir = File.<span style="color:#9900CC;">expand_path</span><span style="color:#006600; font-weight:bold;">&#40;</span>File.<span style="color:#9900CC;">dirname</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">__FILE__</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">"#{dir}/helper"</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">Dir<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">"#{dir}/stories/**/*.rb"</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">uniq</span>.<span style="color:#9900CC;">each</span> <span style="color:#006600; font-weight:bold;">&#123;</span> |file| <span style="color:#CC0066; font-weight:bold;">require</span> file <span style="color:#006600; font-weight:bold;">&#125;</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Another simple wrapper, this time to run all stories.</p>
<h4>stories/helper.rb</h4>
<p><strong>Warning:</strong> This file is where all the ugly code's hiding!</p>
<div class="igBar"><span id="lruby-13"><a href="#" onclick="javascript:showCodeTxt('ruby-13'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">RUBY:</span>
<div id="ruby-13">
<div class="ruby">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">ENV<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">"RAILS_ENV"</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">"test"</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#CC0066; font-weight:bold;">require</span> File.<span style="color:#9900CC;">expand_path</span><span style="color:#006600; font-weight:bold;">&#40;</span>File.<span style="color:#9900CC;">dirname</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">__FILE__</span><span style="color:#006600; font-weight:bold;">&#41;</span> + <span style="color:#996600;">"/../config/environment"</span><span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#008000; font-style:italic;"># Hack to use trunk rspec without affecting the rest of the project</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">$:.<span style="color:#9900CC;">delete_if</span> <span style="color:#006600; font-weight:bold;">&#123;</span>|dir| dir =~ /rspec/<span style="color:#006600; font-weight:bold;">&#125;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">$: &lt;&lt;File.<span style="color:#9900CC;">dirname</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">__FILE__</span><span style="color:#006600; font-weight:bold;">&#41;</span> + '/../lib/rspec/lib'</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">$: &lt;&lt;File.<span style="color:#9900CC;">dirname</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">__FILE__</span><span style="color:#006600; font-weight:bold;">&#41;</span> + '/../lib/rspec_on_rails/lib'</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#008000; font-style:italic;"># Not sure why, but this is required when rspec_on_rails not running as plugin</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#CC0066; font-weight:bold;">require</span> 'spec/rails/matchers'</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#CC0066; font-weight:bold;">require</span> 'spec/rails/story_adapter'</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#CC0066; font-weight:bold;">require</span> File.<span style="color:#9900CC;">dirname</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">__FILE__</span><span style="color:#006600; font-weight:bold;">&#41;</span> + '/../lib/selenium-ruby-client-driver/selenium'</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">Dir<span style="color:#006600; font-weight:bold;">&#91;</span>File.<span style="color:#9900CC;">dirname</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">__FILE__</span><span style="color:#006600; font-weight:bold;">&#41;</span> + <span style="color:#996600;">"/steps/*.rb"</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">uniq</span>.<span style="color:#9900CC;">each</span> <span style="color:#006600; font-weight:bold;">&#123;</span> |file| <span style="color:#CC0066; font-weight:bold;">require</span> file <span style="color:#006600; font-weight:bold;">&#125;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#9966CC; font-weight:bold;">unless</span> $selenium</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; $selenium = Selenium::SeleniumDriver.<span style="color:#9900CC;">new</span> 'localhost', <span style="color:#006666;color:#800000;">4444</span>,</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; '*firefox', 'http://localhost:<span style="color:#006666;color:#800000;">3000</span>/', <span style="color:#006666;color:#800000;">10</span>_000</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; $selenium.<span style="color:#9900CC;">start</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#9966CC; font-weight:bold;">end</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#008000; font-style:italic;"># Don't add an ActiveRecordSafetyListener, or it'll roll stuff back</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#9966CC; font-weight:bold;">class</span> Spec::Story::Runner::ScenarioRunner</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> initialize</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; @listeners = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#9966CC; font-weight:bold;">end</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#008000; font-style:italic;"># Runs the story in the file with the same name as the calling ruby file,</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#008000; font-style:italic;"># but with a .txt extension instead of .rb, using the specified steps.</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#9966CC; font-weight:bold;">def</span> run_story_with_steps_for *steps</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; with_steps_for *steps <span style="color:#9966CC; font-weight:bold;">do</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># Pull the filename of the caller out of the stack. Must be a better way.</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; run <span style="color:#CC0066; font-weight:bold;">caller</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;color:#800000;">3</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#CC0066; font-weight:bold;">sub</span><span style="color:#006600; font-weight:bold;">&#40;</span>/\.<span style="color:#9900CC;">rb</span>:.*/, '.<span style="color:#9900CC;">txt</span>'<span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#9966CC; font-weight:bold;">end</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#008000; font-style:italic;"># Alias some more ruby-like methods on SeleniumDriver, to make it play</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#008000; font-style:italic;"># better with rspec matchers.</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#9966CC; font-weight:bold;">module</span> Selenium</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color:#9966CC; font-weight:bold;">class</span> SeleniumDriver</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; alias_method :original_method_missing, :method_missing</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> method_missing method_name, *args</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">if</span> method_name.<span style="color:#9900CC;">to_s</span> =~ /^has_.*\?$/</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; real_method = method_name.<span style="color:#9900CC;">to_s</span>.<span style="color:#CC0066; font-weight:bold;">sub</span> /has_<span style="color:#006600; font-weight:bold;">&#40;</span>.*<span style="color:#006600; font-weight:bold;">&#41;</span>\?$/, 'is_\<span style="color:#006666;color:#800000;">1</span>'</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">if</span> respond_to? real_method</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#0000FF; font-weight:bold;">return</span> send<span style="color:#006600; font-weight:bold;">&#40;</span>real_method, args<span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">elsif</span> respond_to?<span style="color:#006600; font-weight:bold;">&#40;</span>real_method = <span style="color:#996600;">"get_"</span> + method_name.<span style="color:#9900CC;">to_s</span><span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#0000FF; font-weight:bold;">return</span> send<span style="color:#006600; font-weight:bold;">&#40;</span>real_method<span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; <span style="color:#0000FF; font-weight:bold;">return</span> original_method_missing<span style="color:#006600; font-weight:bold;">&#40;</span>method_name, args<span style="color:#006600; font-weight:bold;">&#41;</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#9966CC; font-weight:bold;">end</span> </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<p>Most of this code doesn't really belong 'loose' in a helper file, but I didn't want to expend too much effort on getting everything working tidily with a pre-release version of RSpec.Hopefully there are enough comments to give a vague idea what's going on, but here are some more notes:</p>
<ul>
<li><strong>Lines 5&ndash;10:</strong> There still seem to be some bugs in trunk RSpec which cause existing specs to fail (or possibly bugs in our specs that don't show up in 1.0.8). I've installed the trunk versions of the plugins under lib, and here I pull the real plugins out of the load path and insert the trunk versions instead.</li>
<li><strong>Lines 17&ndash;21:</strong> Create a selenium driver, and open a browser session.</li>
<li><strong>Lines 23&ndash;28:</strong> By default, RSpec adds an <code>ActiveRecordSafetyListener</code> to the story runner. This rolls back database changes between scenarios, which is great if your calling your code directly, but obviously means that if you write to the database, the server that Selenium's talking to can't see them. There's probably a cleaner way of disabling it.</li>
<li><strong>Lines 30&ndash;37:</strong> A convenience method to remove some code from the story wrappers. Basically just replaces '.rb' with '.txt' and runs that file with the specified steps. However, I can't find a clean way of finding the file name of the code that called a method, so I'm pulling it out of the call stack. Ugh.</li>
<li><strong>Lines 39&ndash;56:</strong> The method names in the ruby interface to Selenium RC are rather java-like (eg <code>get_title</code> and <code>is_text_present</code>). I've used a bit of <em>method_missing</em> hackery to wrap these methods with more ruby-like names (<code>title</code> and <code>has_text_present?</code> for those specific cases), which allows us to use rspec matchers like <code>$selenium.title.should == foo</code> and <code>$selenium.should have_title bar</code>.</li>
</ul>
<h4>lib/tasks/acceptance.rake</h4>
<p>Finally, I've created some rake tasks to wrap everything up, and also to start and stop the selenium server.</p>
<div class="igBar"><span id="lruby-14"><a href="#" onclick="javascript:showCodeTxt('ruby-14'); return false;">PLAIN TEXT</a></span></div>
<div class="syntax_hilite"><span class="langName">RUBY:</span>
<div id="ruby-14">
<div class="ruby">
<ol>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">desc <span style="color:#996600;">"Run the acceptance tests, starting/stopping the selenium server."</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">task :acceptance =&gt; <span style="color:#006600; font-weight:bold;">&#91;</span>'selenium:start'<span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#9966CC; font-weight:bold;">do</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color:#9966CC; font-weight:bold;">begin</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; Rake::Task<span style="color:#006600; font-weight:bold;">&#91;</span>'acceptance:run'<span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">invoke</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color:#9966CC; font-weight:bold;">ensure</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; Rake::Task<span style="color:#006600; font-weight:bold;">&#91;</span>'selenium:stop'<span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">invoke</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#9966CC; font-weight:bold;">end</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">namespace :acceptance <span style="color:#9966CC; font-weight:bold;">do</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; desc <span style="color:#996600;">"Run the acceptance tests, assuming the selenium server is running."</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; task :run <span style="color:#9966CC; font-weight:bold;">do</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">system</span> 'ruby stories/all.<span style="color:#9900CC;">rb</span>'</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; namespace :selenium <span style="color:#9966CC; font-weight:bold;">do</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; desc <span style="color:#996600;">"Start the selenium server"</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; task :start <span style="color:#9966CC; font-weight:bold;">do</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; pid = <span style="color:#CC0066; font-weight:bold;">fork</span> <span style="color:#9966CC; font-weight:bold;">do</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">exec</span> 'java -jar lib/selenium-server/selenium-server.<span style="color:#9900CC;">jar</span>'</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">exit</span>! <span style="color:#006666;color:#800000;">127</span> </div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; File.<span style="color:#CC0066; font-weight:bold;">open</span> SELENIUM_SERVER_PID_FILE, 'w' <span style="color:#9966CC; font-weight:bold;">do</span> |f|</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; f.<span style="color:#CC0066; font-weight:bold;">puts</span> pid</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># wait a few seconds to make sure it's finished starting</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">sleep</span> <span style="color:#006666;color:#800000;">3</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; desc <span style="color:#996600;">"Stop the selenium server"</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; task :stop <span style="color:#9966CC; font-weight:bold;">do</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">if</span> File.<span style="color:#9900CC;">exist</span>? SELENIUM_SERVER_PID_FILE</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; pid = File.<span style="color:#9900CC;">read</span><span style="color:#006600; font-weight:bold;">&#40;</span>SELENIUM_SERVER_PID_FILE<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">to_i</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; Process.<span style="color:#9900CC;">kill</span> 'TERM', pid</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; FileUtils.<span style="color:#9900CC;">rm</span> SELENIUM_SERVER_PID_FILE</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">else</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">"#{SELENIUM_SERVER_PID_FILE} not found"</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#9966CC; font-weight:bold;">end</span></div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">private</div>
</li>
<li style="font-weight: bold;color:#26536A;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">SELENIUM_SERVER_PID_FILE = 'tmp/pids/selenium_server.<span style="color:#9900CC;">pid</span>' </div>
</li>
</ol>
</div>
</div>
</div>
<p></p>
<h3>Still to do</h3>
<p>There's plenty of scope for improvement here. For a start, I haven't figured out how to generate a report for the test run, apart from the plain text output from the console (which is only usable if you start the selenium server in a separate shell). Also, I can't see an obvious way of returning a success/fail status at the end of the run, which makes it difficult to use in a continuous integration process.</p>
<p>The story runner looks like a very promising tool though, and I can't wait for the stable release.</p>
<p>Technorati Tags: <a href="http://technorati.com/tag/bdd" rel="tag">bdd</a>, <a href="http://technorati.com/tag/rspec" rel="tag"> rspec</a>, <a href="http://technorati.com/tag/rbehave" rel="tag"> rbehave</a>, <a href="http://technorati.com/tag/selenium" rel="tag"> selenium</a>, <a href="http://technorati.com/tag/acceptance+testing" rel="tag"> acceptance testing</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrybuckley.org/2007/11/07/driving-selenium-from-the-rspec-story-runner-rbehave/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Concurrent design and development &#8211; a better spin?</title>
		<link>http://www.kerrybuckley.org/2007/09/26/concurrent-design-and-development-a-better-spin/</link>
		<comments>http://www.kerrybuckley.org/2007/09/26/concurrent-design-and-development-a-better-spin/#comments</comments>
		<pubDate>Wed, 26 Sep 2007 21:24:35 +0000</pubDate>
		<dc:creator>Kerry</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[BT]]></category>

		<guid isPermaLink="false">http://www.kerrybuckley.com/2007/09/26/concurrent-design-and-development-a-better-spin/</guid>
		<description><![CDATA[Another day, another argument discussion with a colleague over the common misapprehension that you can have a process with discrete requirements capture, design, development and test phases, yet somehow still claim to be agile. Once again, I tried (with limited success) to explain that you don't need to do all your designing up front before [...]]]></description>
			<content:encoded><![CDATA[<p>Another day, another <del datetime="2007-09-26T16:53:31+00:00">argument</del> discussion with a colleague over the common misapprehension that you can have a process with discrete requirements capture, design, development and test phases, yet somehow still claim to be agile. Once again, I tried (with limited success) to explain that you don't need to do all your designing up front before you start writing code, and that starting to write code almost immediately isn't 'hacking', provided that you are continuously paying attention to good design as you go.</p>
<p>In other words, agile developers do just as much designing as those still following waterfall methods, but we do it at the same time as writing the code.</p>
<p>Reflecting afterwards, I realised that I've been phrasing the message the wrong way. As anyone who really 'gets' test-driven (and particularly behaviour-driven) development knows, it's not really about the testing, but about the design process. A waterfall 'designer' starts from an understanding of the problem and builds up some kind of model for a solution, which they then pass on to the implementors An agile developer does exactly the same, but the language they use for the model happens to be executable source code rather than documents or UML. This choice of modeling language has the rather large benefit of being testable, and once your design is finished, you're done. No need for someone to try to interpret and implement it. No scope for misunderstandings between designer and developer. No danger that the design is incomplete, or that part of it turns out to be unworkable.</p>
<p>It's not that we start writing code and design as we go along.</p>
<p><strong>We are always designing &ndash; we just write the code as we go along.</strong></p>
<p>Technorati Tags: <a href="http://technorati.com/tag/agile" rel="tag">agile</a>, <a href="http://technorati.com/tag/tdd" rel="tag"> tdd</a>, <a href="http://technorati.com/tag/bdd" rel="tag"> bdd</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrybuckley.org/2007/09/26/concurrent-design-and-development-a-better-spin/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 0.449 seconds -->

