<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="wordpress/2.1.2" -->
<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/"
	>

<channel>
	<title>Exploration Through Example</title>
	<link>http://www.exampler.com/blog</link>
	<description>Example-driven development, Agile software development, testing, Ruby, and other things of interest to Brian Marick</description>
	<pubDate>Fri, 26 Feb 2010 14:01:13 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.1.2</generator>
	<language>en</language>
			<item>
		<title>Changing basic assumptions in apps</title>
		<link>http://www.exampler.com/blog/2010/02/25/changing-basic-assumptions-in-apps/</link>
		<comments>http://www.exampler.com/blog/2010/02/25/changing-basic-assumptions-in-apps/#comments</comments>
		<pubDate>Thu, 25 Feb 2010 17:08:24 +0000</pubDate>
		<dc:creator>Brian Marick</dc:creator>
		
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.exampler.com/blog/2010/02/25/changing-basic-assumptions-in-apps/</guid>
		<description><![CDATA[One of the hardest things for me as an app developer is changing basic assumptions in a safe, gradual way. Here&#8217;s an example.
Critter4Us is an app that reserves animals for demonstrations and student practice in a veterinary college. There are business rules like &#8220;an animal can be used to practice injections no more than twice [...]]]></description>
			<content:encoded><![CDATA[<p>One of the hardest things for me as an app developer is changing basic assumptions in a safe, gradual way. Here&#8217;s an example.</p>
<p>Critter4Us is an app that reserves animals for demonstrations and student practice in a veterinary college. There are business rules like &#8220;an animal can be used to practice injections no more than twice a week&#8221;. </p>
<p>In its original form, Critter4Us only made reservations for one point in time (the morning, afternoon, or evening of a particular day). I&#8217;m now making it take reservations for &#8220;timeslices&#8221;, where a timeslice has a start date, an end date, and any subset of {morning, afternoon, evening}. Doesn&#8217;t seem like a huge change, but it turns out to be pretty fundamental:</p>
<ul>
<li>
<p>
A lot of questions vaguely like &#8220;is this point within this range?&#8221; are now &#8220;do these two ranges overlap?&#8221; There&#8217;s an existing <code>Timeslice</code> object (which, despite the name, was about points in time). It has some time-related behavior, but responsibility for some other behavior leaked out of it because the data was so simple.
</p>
</li>
<li>
<p>
Some of the database operations were annoyingly slow after being hard to get right, quite likely because my SQL-fu is weak. Since the questions are becoming more complex, I want to do less calculating when questions are asked and more stashing partial answers in the database. So adding this feature requires more database work than just a simple schema migration.
</p>
<p>
(This feels like premature optimization of a feature I don&#8217;t <i>know</i> wouldn&#8217;t be fast enough, but my main motivation is that I&#8217;m more confident of getting the right answers if I stash partial answers. This is the most important business logic in the app.)
</p>
</li>
<li>
<p>
The UI needs to change. Should that be done by upgrading the existing reserve-a-point-in-time page (adding clutter for a case that&#8217;s used seldom) or adding a new page?
</p>
</li>
</ul>
<p>I want to make all these changes in such a way that (1) the tests are all passing most of the time and (2) the app is deployable most of the time. I devised the following strategy after writing a partial <a href="http://www.extremeprogramming.org/rules/spike.html">spike</a> and throwing it away:</p>
<ol>
<li>
<p>
<b>DONE</b> Change the current <a href="http://cappuccino.org/">Cappuccino</a> front end. It used to deliver
</p>
<pre>
?date=2010-09-02&#038;time=morning
</pre>
<p>to the <a href="http://www.sinatrarb.com/">Sinatra</a> backend. Now it delivers </p>
<pre>
timeslice={'firstDate':'2010-09-02', 'lastDate':'2010-09-02', 'times':['morning']}
</pre>
<p>
This isn&#8217;t hard because the front end doesn&#8217;t do any calculations on the date.
</p>
</li>
<li>
<p>
<b>DONE</b> Have the backend controller that receives the data quickly convert the new format into the old.
</p>
</li>
<li>
<p>
<b>DONE</b> Move conversion of new-format-to-old into the <code>Timeslice</code> object. (Only two classes make <code>Timeslice</code> objects, so that&#8217;s easy.)
</p>
</li>
<li>
<p>
<b>DONE</b> Change the Reservations table to add new columns. Change the <code>Reservation</code> object to allow it to be constructed using either the old or new format. Change all the non-test code to use the new constructor. (It&#8217;s convenient to keep the terser form around for the tests that use it.)
</p>
</li>
<li>
<p>
<b>IN PROGRESS</b><br />
<code>Reservation</code> and <code>Timeslice</code> aren&#8217;t completely dumb objects &#8212; they probably get told more than they get asked &#8212; but they do have accessors for <code>date</code> and <code>time</code>. Those accessors are still meaningful because (at this point) the <code>first_date</code> and <code>last_date</code> are always the same and the set of <code>times</code> can only ever contain one element.</p>
<p>However, change their names to <code>faked_date_TODO_replace_me</code> and <code>faked_time_TODO_replace_me</code>. Run the tests. For each no-such-method failure,
</p>
<ul>
<li>
<p>
If the purpose of the call can easily be expressed in terms of the new interface, rewrite the call to use it.
</p>
</li>
<li>
<p>
If not, use the convoluted, soon-to-be-replaced name.
</p>
</li>
</ul>
</li>
<li>
<p>
Replace the old code that answers the question &#8220;for which procedures may this animal be used at this moment?&#8221; with code that assumes cached partial answers. Mock out the cached partial answers and thereby design the partial answer table.
</p>
</li>
<li>
<p>
Add the cached table to the database. Change the code that creates reservations to cache partial answers.
</p>
</li>
<li>
<p>
Working from the controllers down, examine each method that uses <code>faked_date_TODO_replace_me</code> and <code>faked_time_TODO_replace_me</code>. What does the method do? What makes sense in a world where reservations and uses of animals are not for a single point in time? Where does the method really belong? Fix them.
</p>
</li>
<li>
<p>
Now that all uses are fixed, delete the methods with silly names.
</p>
</li>
<li>
<p>
Generalize the question-answering code to answer questions about timeslices more complicated than single points. Much careful testing here.
</p>
</li>
<li>
<p>
Change the UI to collect more complicated timeslices.
</p>
</li>
</ol>
<p>It&#8217;ll be interesting to see what the final structure of the code looks like. A lot of this code was written early in the project, so I&#8217;m sure it&#8217;ll improve a lot.</p>
<p>If you want to see the code, it&#8217;s on <a href="http://github.com/marick/critter4us">GitHub</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.exampler.com/blog/2010/02/25/changing-basic-assumptions-in-apps/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Attitude of the development team to the product</title>
		<link>http://www.exampler.com/blog/2010/01/31/attitude-of-the-development-team-to-the-product/</link>
		<comments>http://www.exampler.com/blog/2010/01/31/attitude-of-the-development-team-to-the-product/#comments</comments>
		<pubDate>Sun, 31 Jan 2010 19:40:51 +0000</pubDate>
		<dc:creator>Brian Marick</dc:creator>
		
		<category><![CDATA[agile]]></category>

		<guid isPermaLink="false">http://www.exampler.com/blog/2010/01/31/attitude-of-the-development-team-to-the-product/</guid>
		<description><![CDATA[Back in the old days, most of my Agile consulting was coming into well-performing Agile teams who wanted to talk about improving their testing. So I got to see a lot of seasoned teams. What struck me most, and made me happiest, was their stance toward their product and the product owner. Proud. Enthusiastic. Engaged.
Dave [...]]]></description>
			<content:encoded><![CDATA[<p>Back in the old days, most of my Agile consulting was coming into well-performing Agile teams who wanted to talk about improving their testing. So I got to see a lot of seasoned teams. What struck me most, and made me happiest, was their stance toward their product and the product owner. Proud. Enthusiastic. <i>Engaged</i>.</p>
<p><a href="http://nuts.redsquirrel.com/">Dave Hoover</a> of <a href="http://obtiva.com/">Obtiva</a> has been working on a product called <a href="http://www.madmimi.com/">Mad Mimi</a> for some time. At my request, he&#8217;s collected some of his tweets about it. He exemplifies that attitude I so enjoy. To pique your interest, here are some samples:</p>
<blockquote><p>
Wow, <a href="http://twitter.com/madmimi">@madmimi</a> has had a great 24 hours. Seems like a tipping point is coming soon. Really exciting to witness this stuff first-hand.<br />
Thu Jul 10 17:34:40 +0000 2008</p>
<p>Sheesh, I&#8217;m really impressed by the emails that people are putting together with <a href="http://twitter.com/madmimi">@madmimi</a>: <a href="http://madmimi.com/promotions/3295200582152/raw">http://madmimi.com/promotions/3295200582152/raw</a><br />
Thu Nov 20 13:47:40 +0000 2008</p>
<p><a href="http://twitter.com/ByENNEN">@ByENNEN</a>: Your wish is <a href="http://twitter.com/madmimi">@madmimi</a>&#8217;s command. Have a look now. :)<br />
Tue Dec 30 20:14:24 +0000 2008</p>
<p>In awe of <a href="http://twitter.com/madmimi">@madmimi</a> today. Went from $100k/year in revenue to $200k/year in revenue in just 2 months. Zero dollars spent on advertising, FTW!<br />
Wed Jan 14 22:04:50 +0000 2009</p>
<p>Fell asleep at 9 last night in the living room &#8220;tent&#8221; with the boys. Up at 4 this morning. Couldn&#8217;t stop myself from hacking on <a href="http://twitter.com/madmimi">@madmimi</a>.<br />
Mon Feb 16 13:31:44 +0000 2009</p>
<p><a href="http://twitter.com/Kellypaull">@Kellypaull</a> Yes, I use <a href="http://twitter.com/madmimi">@madmimi</a>. I also built it. :)<br />
Mon Apr 20 05:29:20 +0000 2009</p>
<p>Twitter Driven Development: 13 days ago <a href="http://twitter.com/misterpowell">@misterpowell</a> complained about <a href="http://twitter.com/mailchimp">@mailchimp</a>&#8217;s RSS-to-Email. Today, <a href="http://twitter.com/madmimi">@madmimi</a> released its RSS-to-Email!<br />
Wed Jun 03 21:48:36 +0000 2009</p>
<p>I&#8217;m so biased nowadays. Every newsletter I receive via Constant Contact makes my stomach turn. Hard not to reply with <a href="http://twitter.com/madmimi">@madmimi</a> evangelism.<br />
Mon Jun 22 21:34:06 +0000 2009</p>
<p>This song about <a href="http://twitter.com/madmimi">@madmimi</a> just made my day <a href="http://is.gd/1rnQ8">http://is.gd/1rnQ8</a><br />
Wed Jul 08 19:54:48 +0000 2009</p>
<p>Can&#8217;t sleep after reading <a href="http://twitter.com/mfeathers">@mfeathers</a>&#8216; blog post and checking the latest <a href="http://twitter.com/madmimi">@madmimi</a> subscription numbers&#8230;<br />
Thu Sep 10 05:10:12 +0000 2009</p>
</blockquote>
<p><a href="http://redsquirrel.com/dave/mimi-tweets.html">Here&#8217;s the whole list.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.exampler.com/blog/2010/01/31/attitude-of-the-development-team-to-the-product/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Up in the Air</title>
		<link>http://www.exampler.com/blog/2010/01/31/up-in-the-air/</link>
		<comments>http://www.exampler.com/blog/2010/01/31/up-in-the-air/#comments</comments>
		<pubDate>Sun, 31 Jan 2010 18:36:50 +0000</pubDate>
		<dc:creator>Brian Marick</dc:creator>
		
		<category><![CDATA[the larger world]]></category>

		<guid isPermaLink="false">http://www.exampler.com/blog/2010/01/31/up-in-the-air/</guid>
		<description><![CDATA[I saw &#8220;Up in the Air&#8221; last night. While it&#8217;s a well-done movie, albeit entirely predictable, the world it portrays is a lot more disturbing than it seems at first. To explain, I recommend John Holbo&#8217;s close reading of David Frum&#8217;s Dead Right. Here&#8217;s the most relevant part:

[Frum writes] “The great, overwhelming fact of a [...]]]></description>
			<content:encoded><![CDATA[<p>I saw &#8220;Up in the Air&#8221; last night. While it&#8217;s a well-done movie, albeit entirely predictable, the world it portrays is a lot more disturbing than it seems at first. To explain, I recommend John Holbo&#8217;s <a href="http://examinedlife.typepad.com/johnbelle/2003/11/dead_right.html">close reading</a> of David Frum&#8217;s <i>Dead Right</i>. Here&#8217;s the most relevant part:</p>
<blockquote><p>
[Frum writes] “The great, overwhelming fact of a capitalist economy is risk. Everyone is at constant risk of the loss of his job, or of the destruction of his business by a competitor, or of the crash of his investment portfolio. Risk makes people circumspect. It disciplines them and teaches them self-control. Without a safety net, people won’t try to vault across the big top. Social security, student loans, and other government programs make it far less catastrophic than it used to be for middle-class people to dissolve their families. Without welfare and food stamps, poor people would cling harder to working-class respectability than they do now.”</p>
<p>[Now Holbo] The thing that makes capitalism good, apparently, is not that it generates wealth more efficiently than other known economic engines. No, the thing that makes capitalism good is that, by forcing people to live precarious lives, it causes them to live in fear of losing everything and therefore to adopt – as fearful people will – a cowed and subservient posture: in a word, they behave ‘conservatively’. Of course, crouching to protect themselves and their loved ones from the eternal lash of risk precisely won’t preserve these workers from risk. But the point isn’t to induce a society-wide conformist crouch by way of making the workers safe and happy. The point is to induce a society-wide conformist crouch. Period. A solid foundation is hereby laid for a desirable social order.
</p></blockquote>
<p>*Some Spoilers*</p>
<p>&#8220;Up in the Air&#8221; is almost unrelentingly conservative in that it simply <i>assumes</i> that the world of work today is the one Frum [seems to] desire. In the movie, Fate&#8211;impersonal forces of industry that are faceless until they hire George Clooney&#8211;strikes people unexpectedly, and the <i>only</i> solace or support they can have is their family. They get no help from the Agile Alliance, ACM, IEEE, craftsman guilds, AFSCME, AFL-CIO, their community, or the keen-eyed watchdogs of the press whipping up public opinion. There&#8217;s some help from the company&#8211;of what quality we don&#8217;t know&#8211;and the government offers only unemployment benefits that are explicitly called out as derisory. There&#8217;s some talk of protecting the firing process from lawsuits [government intervention in the process], but in the one case where a lawsuit is credibly threatened, a simple lie by Clooney makes it go away.</p>
<p>In the movie, the people below the airplanes have no option but a socially desirable [to some] defensive crouch. To the extent that movies capture the zeitgeist, that&#8217;s pretty disturbing. The movie comes out against atomization&#8211;being alone is Clooney&#8217;s unhappy fate&#8211;but the atoms can&#8217;t form molecules bigger than a family. <i>There are no other bonds</i>. OK: there&#8217;s Clooney&#8217;s last, human gesture to Natalie, but that&#8217;s something delivered in extremis, not a way of life. The character of Alex is more representative of the movie&#8217;s view of the world: outside the family, there are no norms and no obligations. </p>
<p>The movie shows a world in which Phil Gramm, one of the <a href="http://en.wikipedia.org/wiki/Commodity_Futures_Modernization_Act_of_2000">architects</a> of our current troubles, is on point when he talked about the US as &#8220;<a href="http://www.washingtontimes.com/news/2008/jul/09/mccain-adviser-addresses-mental-recession/">a nation of whiners</a>&#8220;. One strong element of conservatism is the preservation of hierarchy. To Gramm&#8211;who need never fear unemployment&#8211;I suspect that we-the-people are not particularly relevant. How annoying it must be when we complain! We should shut up, take our lumps, scrape through, and&#8211;as in the movie&#8217;s closing narrative&#8211;watch the planes containing our fate fly far overhead.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.exampler.com/blog/2010/01/31/up-in-the-air/feed/</wfw:commentRss>
		</item>
		<item>
		<title>A European pair-touring trip</title>
		<link>http://www.exampler.com/blog/2010/01/26/a-european-pair-touring-trip/</link>
		<comments>http://www.exampler.com/blog/2010/01/26/a-european-pair-touring-trip/#comments</comments>
		<pubDate>Tue, 26 Jan 2010 23:59:20 +0000</pubDate>
		<dc:creator>Brian Marick</dc:creator>
		
		<category><![CDATA[conferences]]></category>

		<guid isPermaLink="false">http://www.exampler.com/blog/2010/01/26/a-european-pair-touring-trip/</guid>
		<description><![CDATA[I&#8217;ll be speaking at the Scandinavian Developer Conference on March 16-17. I may be speaking at the Scottish Ruby Conference on March 26-27. I have to be back in the USA for Philly Emerging Tech on April 8th. I&#8217;d like to do a pair tour of Europe sometime in that time. I&#8217;m thinking of something [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ll be speaking at the <a href="http://www.scandevconf.se/">Scandinavian Developer Conference</a> on March 16-17. I may be speaking at the <a href="http://scottishrubyconference.com/">Scottish Ruby Conference</a> on March 26-27. I have to be back in the USA for <a href="http://www.phillyemergingtech.com/">Philly Emerging Tech</a> on April 8th. I&#8217;d like to do a pair tour of Europe sometime in that time. I&#8217;m thinking of something like this route:</p>
<p><img src="http://www.exampler.com/blog/wp-content/uploads/2010/01/img-60332607-7b082b51651a098706225938887db693.4b5f8350-full.png" height="587" width="560" border="1" hspace="4" vspace="4" alt=" Img 60332607-7B082B51651A098706225938887Db693.4B5F8350-Full" /></p>
<p>Göteburg, Sweden -> Amsterdam -> Paris -> Madrid -> London -> Edinburgh. If you&#8217;d be interested in working together, contact me. I&#8217;m looking into moving into programming-process consulting (like TDD), cutting-edge programming (like Clojure). I&#8217;m also wanting to somehow accelerate my learning of Spanish.</p>
<p>The rules for a pair tour is that you let me &#8220;couch surf&#8221; (sleep on your floor or couch) and provide some food (dinners, for example). I&#8217;m a poor American&#8211;I can&#8217;t afford European prices.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.exampler.com/blog/2010/01/26/a-european-pair-touring-trip/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Delivering value</title>
		<link>http://www.exampler.com/blog/2010/01/25/delivering-value/</link>
		<comments>http://www.exampler.com/blog/2010/01/25/delivering-value/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 16:55:29 +0000</pubDate>
		<dc:creator>Brian Marick</dc:creator>
		
		<category><![CDATA[agile]]></category>

		<guid isPermaLink="false">http://www.exampler.com/blog/2010/01/25/delivering-value/</guid>
		<description><![CDATA[It&#8217;s quite the rage today to talk about &#8220;delivering value&#8221; as opposed to &#8220;delivering software&#8221;. That scares me.
Consider the contractor who had our house in chaos for what seems like forever. We now have more counter space in the two upstairs bathrooms. I think you could make a strong argument that he would have delivered [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s quite the rage today to talk about &#8220;delivering value&#8221; as opposed to &#8220;delivering software&#8221;. That scares me.</p>
<p>Consider the contractor who had our house in chaos for what seems like forever. We now have more counter space in the two upstairs bathrooms. I think you could make a strong argument that he would have delivered more value to us if he&#8217;d taught us&#8211;<i>two of us in particular</i>&#8211;how to more efficiently use the space we already had. And yet I&#8217;m glad he didn&#8217;t. I preferred him to deliver what we wanted to pay him to deliver.</p>
<p>On the other hand, my dad built houses. I remember him once telling a prospective client that the architect&#8217;s plans they had were wrong. Given the man&#8217;s job, he&#8217;d come home dirty every day, so he&#8217;d probably want to go directly to the shower. The plans had him tromping all through the house. Instead, he needed a doorway from the garage to a little hall with a bathroom one step away. I think they let him redraw the plans, thereby delivering more value.</p>
<p>So there&#8217;s a tricky balance here. Are we up to it?</p>
<p>As my wife put it the first time she met my friends, &#8220;You software people have really strong opinions&#8230; about everything!&#8221; The average software person is more likely than, say, the average veterinarian to talk to someone briefly about her job and immediately come up with ten ways she ought to do it better. Telling such a jumper-to-conclusions that the team should look beyond what the business wants to what it <i>needs</i> is&#8230; maybe tempting them to play to their weaknesses. </p>
<p>I would instead tell a team they must, over the course of many months, prove to the business that they are <i>worthy</i> of being invited to the larger conversation about what the business needs. And to do that, they must&#8211;first and foremost&#8211;deliver what the business wants, while also acting as a humble student of that business.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.exampler.com/blog/2010/01/25/delivering-value/feed/</wfw:commentRss>
		</item>
		<item>
		<title>A parable about mocking frameworks</title>
		<link>http://www.exampler.com/blog/2010/01/24/a-parable-about-mocking-frameworks/</link>
		<comments>http://www.exampler.com/blog/2010/01/24/a-parable-about-mocking-frameworks/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 01:45:26 +0000</pubDate>
		<dc:creator>Brian Marick</dc:creator>
		
		<category><![CDATA[TDD]]></category>

		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.exampler.com/blog/2010/01/24/a-parable-about-mocking-frameworks/</guid>
		<description><![CDATA[Somewhere around 1985, I introduced Ralph Johnson to a bigwig in the Motorola software research division. Object-oriented programming was around the beginning of its first hype phase, Smalltalk was the canonical example, and Ralph was heavily into Smalltalk, so I expected a good meeting. 
The bigwig started by explaining how a team of his had [...]]]></description>
			<content:encoded><![CDATA[<p>Somewhere around 1985, I introduced Ralph Johnson to a bigwig in the Motorola software research division. Object-oriented programming was around the beginning of its first hype phase, Smalltalk was the canonical example, and Ralph was heavily into Smalltalk, so I expected a good meeting. </p>
<p>The bigwig started by explaining how a team of his had done object-oriented programming 20 years before in assembly language. I slid under the table in shame. Now, it&#8217;s certainly technically possible that they&#8217;d implemented polymorphic function calls based on a class tag&#8211;after all, that&#8217;s what compilers do. Still, the setup required to do that was surely <i>far greater</i> than the burden Smalltalk and its environment put on the programmer. I immediately thought that the difference in the flexibility and ease that Smalltalk and its environment brought to OO programming made the two programming experiences completely <a href="http://bit.ly/6eONUj">incommensurable</a>. (The later discussion confirmed that snap impression.) </p>
<p>I suspect the same is true of mocking frameworks. When you have to write <a href="http://xunitpatterns.com/Test%20Double.html">test doubles</a> by hand, doing so is an impediment to the steady cadence of TDD. When you write a statement in a mocking framework&#8217;s pseudo-language, doing so is part of the cadence. I bet the difference in experience turns into a difference in design, just as Smalltalk designs were different from even the most object-oriented assembler designs (though I expect not to the same extent).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.exampler.com/blog/2010/01/24/a-parable-about-mocking-frameworks/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Mocks, the removal of test detail, and dynamically-typed languages</title>
		<link>http://www.exampler.com/blog/2010/01/13/mocks-the-removal-of-test-detail-and-dynamically-typed-languages/</link>
		<comments>http://www.exampler.com/blog/2010/01/13/mocks-the-removal-of-test-detail-and-dynamically-typed-languages/#comments</comments>
		<pubDate>Wed, 13 Jan 2010 17:41:32 +0000</pubDate>
		<dc:creator>Brian Marick</dc:creator>
		
		<category><![CDATA[TDD]]></category>

		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.exampler.com/blog/2010/01/13/mocks-the-removal-of-test-detail-and-dynamically-typed-languages/</guid>
		<description><![CDATA[
Simplify, simplify, simplify! &#8211; Henry David Thoreau


(A billboard I saw once.)

Part 1: Mocking as a way of removing words
One of the benefits of mocks is that tests don&#8217;t have to build up complicated object structures that have nothing essential to do with the purpose of a test. For example, I have  an entry point [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;">
Simplify<span style="text-decoration: line-through;">, simplify, simplify! </span><br />&#8211; <span style="text-decoration: line-through;">Henry David</span> Thoreau
</p>
<p style="text-align: center;">
(A billboard I saw once.)
</p>
<p><b>Part 1: Mocking as a way of removing words</b></p>
<p>One of the benefits of mocks is that tests don&#8217;t have to build up complicated object structures that have nothing essential to do with the purpose of a test. For example, I have  an entry point to a <a href="http://github.com/marick/critter4us">webapp</a> that looks like this:</p>
<pre><span class="ident">get</span> <span class="punct">&#8216;</span><span class="string">/json/animals_that_can_be_taken_out_of_service</span><span class="punct">&#8216;,</span> <span class="symbol">:date</span> <span class="punct">=></span> <span class="punct">&#8216;</span><span class="string">2009-01-01</span><span class="punct">&#8216;</span>
</pre>
<p>It is to return a JSON version of something like this:</p>
<pre><span class="punct">{</span> <span class="punct">&#8216;</span><span class="string">unused animals</span><span class="punct">&#8216;</span> <span class="punct">=></span> <span class="punct">[&#8217;</span><span class="string">jake</span><span class="punct">&#8216;]</span> <span class="punct">}</span>
</pre>
<p>Jake can be taken out of service on Jan 1, 2009 because he is not reserved for that day or any following day. </p>
<p>In typical object-oriented fashion, the controller doesn&#8217;t do much except ask something else to do something. The code will look something like this:</p>
<pre>  <span class="ident">get</span> <span class="punct">&#8216;</span><span class="string">/json/animals_that_can_be_taken_out_of_service</span><span class="punct">&#8216;</span> <span class="keyword">do</span>
    <span class="comment"># Tell the &#8220;timeslice&#8221; we are concerned with the date given.</span>

    <span class="comment"># Ask the timeslice: What animals can be reserved on/after that date?</span>
    <span class="comment"># (That excludes the animals already taken out of service.) </span>

    <span class="comment"># Those animals fall into two categories:</span>
    <span class="comment"># - some have reservations after the timeslice date. </span>
    <span class="comment"># - some do not.</span>
    <span class="comment"># Ask the timeslice to create the two categories.</span>

    <span class="comment"># Return the list of animals without reservations. </span>
    <span class="comment"># Those are the ones that can be taken out of service as of the given date. </span>
  <span class="keyword">end</span>
</pre>
<p>If I were testing this without mocks, I&#8217;d be obliged to arrange things so that there would be examples of each of the categories. Here&#8217;s the creation of a minimal such structure: </p>
<pre>  <span class="ident">jake</span> <span class="punct">=</span> <span class="constant">Animal</span><span class="punct">.</span><span class="ident">random</span><span class="punct">(</span><span class="symbol">:name</span> <span class="punct">=></span> <span class="punct">&#8216;</span><span class="string">jake</span><span class="punct">&#8216;)</span>
  <span class="ident">brooke</span> <span class="punct">=</span> <span class="constant">Animal</span><span class="punct">.</span><span class="ident">random</span><span class="punct">(</span><span class="symbol">:name</span> <span class="punct">=></span> <span class="punct">&#8216;</span><span class="string">brooke</span><span class="punct">&#8216;)</span>
  <span class="constant">Reservation</span><span class="punct">.</span><span class="ident">random</span><span class="punct">(</span><span class="symbol">:date</span> <span class="punct">=></span> <span class="constant">Date</span><span class="punct">.</span><span class="ident">new</span><span class="punct">(</span><span class="number">2009</span><span class="punct">,</span> <span class="number">1</span><span class="punct">,</span> <span class="number">1</span><span class="punct">))</span> <span class="keyword">do</span>
    <span class="ident">use</span> <span class="ident">brooke</span>
    <span class="ident">use</span> <span class="constant">Procedure</span><span class="punct">.</span><span class="ident">random</span>
  <span class="keyword">end</span>
</pre>
<p>The <code><span class="ident">random</span></code> methods save a good deal of setup by defaulting unmentioned parameters and by hiding the fact that <code><span class="ident">Reservations</span></code> have_many <code><span class="ident">Groups</span></code>, <code><span class="ident">Groups</span></code> have_many <code><span class="ident">Uses</span></code>, and each <code><span class="ident">Use</span></code> has an <code><span class="ident">Animal</span></code> and a <code><span class="ident">Procedure</span></code>. But they still distract the eye with irrelevant information. For example, the controller method we&#8217;re writing really cares nothing for the existence of <code><span class="ident">Reservations</span></code> or <code><span class="ident">Procedures</span></code>&#8211;but the test has to mention them. That sort of thing makes tests harder to read and more fragile. </p>
<p>In constrast to this style of TDD, mocking lets the <i>test</i> ignore everything that the <i>code</i> can. Here&#8217;s a mock test for this controller method:</p>
<pre>    <span class="ident">should</span> <span class="punct">&#8220;</span><span class="string">return a list of animals with no pending reservations</span><span class="punct">&#8220;</span> <span class="keyword">do</span>
      <span class="ident">brooke</span> <span class="punct">=</span> <span class="constant">Animal</span><span class="punct">.</span><span class="ident">random</span><span class="punct">(</span><span class="symbol">:name</span> <span class="punct">=></span> <span class="punct">&#8216;</span><span class="string">brooke</span><span class="punct">&#8216;)</span>
      <span class="ident">jake</span> <span class="punct">=</span> <span class="constant">Animal</span><span class="punct">.</span><span class="ident">random</span><span class="punct">(</span><span class="symbol">:name</span> <span class="punct">=></span> <span class="punct">&#8216;</span><span class="string">jake</span><span class="punct">&#8216;)</span>

      <span class="ident">during</span> <span class="punct">{</span>
        <span class="ident">get</span> <span class="punct">&#8216;</span><span class="string">/json/animals_that_can_be_taken_out_of_service</span><span class="punct">&#8216;,</span> <span class="symbol">:date</span> <span class="punct">=></span> <span class="punct">&#8216;</span><span class="string">2009-01-01</span><span class="punct">&#8216;</span>
      <span class="punct">}.</span><span class="ident">behold!</span> <span class="punct">{</span>
        <span class="attribute">@timeslice</span><span class="punct">.</span><span class="ident">should_receive</span><span class="punct">(</span><span class="symbol">:move_to</span><span class="punct">).</span><span class="ident">once</span><span class="punct">.</span><span class="ident">with</span><span class="punct">(</span><span class="constant">Date</span><span class="punct">.</span><span class="ident">new</span><span class="punct">(</span><span class="number">2009</span><span class="punct">,</span><span class="number">1</span><span class="punct">,</span><span class="number">1</span><span class="punct">))</span>
        <span class="attribute">@timeslice</span><span class="punct">.</span><span class="ident">should_receive</span><span class="punct">(</span><span class="symbol">:animals_that_can_be_reserved</span><span class="punct">).</span><span class="ident">once</span><span class="punct">.</span>
                   <span class="ident">and_return</span><span class="punct">([</span><span class="ident">brooke</span><span class="punct">,</span> <span class="ident">jake</span><span class="punct">])</span>
        <span class="attribute">@timeslice</span><span class="punct">.</span><span class="ident">should_receive</span><span class="punct">(</span><span class="symbol">:hashes_from_animals_to_pending_dates</span><span class="punct">).</span><span class="ident">once</span><span class="punct">.</span>
                   <span class="ident">with</span><span class="punct">([</span><span class="ident">brooke</span><span class="punct">,</span> <span class="ident">jake</span><span class="punct">]).</span>
                   <span class="ident">and_return</span><span class="punct">([{</span><span class="ident">brooke</span> <span class="punct">=></span> <span class="punct">[</span><span class="constant">Date</span><span class="punct">.</span><span class="ident">new</span><span class="punct">(</span><span class="number">2009</span><span class="punct">,</span><span class="number">1</span><span class="punct">,</span><span class="number">1</span><span class="punct">),</span> <span class="constant">Date</span><span class="punct">.</span><span class="ident">new</span><span class="punct">(</span><span class="number">2010</span><span class="punct">,</span><span class="number">1</span><span class="punct">,</span><span class="number">1</span><span class="punct">)]},</span>
                               <span class="punct">{</span><span class="ident">jake</span> <span class="punct">=></span> <span class="punct">[]}])</span>
      <span class="punct">}</span>
      <span class="ident">assert_json_response</span>
      <span class="ident">assert_jsonification_of</span><span class="punct">(&#8217;</span><span class="string">unused animals</span><span class="punct">&#8216;</span> <span class="punct">=></span> <span class="punct">[&#8217;</span><span class="string">jake</span><span class="punct">&#8216;])</span>
    <span class="keyword">end</span>
</pre>
<p>There are no <code><span class="ident">Reservations</span></code> and no <code><span class="ident">Procedures</span></code> and no code-discussions of irrelevant connections amongst objects. The test is more terse and&#8211;I think&#8211;more understandable (once you understand my weird conventions and allow for my inability to choose good method names). That&#8217;s an advantage of mocks. </p>
<p><b>Part 2: Dynamic languages let you remove even more irrelevant detail</b></p>
<p>But I&#8217;m starting to think we can actually go a little further in languages like Ruby and <a href="http://cappuccino.org/">Objective-J</a>. I&#8217;ll use different code to show that.</p>
<p>When the client side of this app receives the list of animals that can be removed from service, it uses that to populate the GUI. The user chooses some animals and clicks a button. Various code ensues. Eventually, a <code><span class="ident">PersistentStore</span></code> object spawns off a <code><span class="ident">Future</span></code> that asynchronously sends a POST request and deals with the response. It does that by coordinating with two objects: one that knows about converting from the lingo of the program (model objects and so forth) into HTTP/JSON, and a <code><span class="ident">FutureMaker</span></code> that makes an appropriate future. The real code and its test are written in Objective-J, but here&#8217;s a version in Ruby:</p>
<pre><span class="ident">should</span> <span class="punct">&#8220;</span><span class="string">coordinate taking animals out of service</span><span class="punct">&#8220;</span> <span class="keyword">do</span>
  <span class="ident">during</span> <span class="punct">{</span>
    <span class="attribute">@sut</span><span class="punct">.</span><span class="ident">remove_from_service</span><span class="punct">(&#8221;</span><span class="string">some animals</span><span class="punct">&#8220;,</span> <span class="punct">&#8220;</span><span class="string">an effective date</span><span class="punct">&#8220;)</span>
  <span class="punct">}.</span><span class="ident">behold!</span> <span class="punct">{</span>
    <span class="attribute">@http_maker</span><span class="punct">.</span><span class="ident">should_receive</span><span class="punct">(</span><span class="symbol">:take_animals_out_of_service_route</span><span class="punct">).</span><span class="ident">at_least</span><span class="punct">.</span><span class="ident">once</span><span class="punct">.</span>
                <span class="ident">and_return</span><span class="punct">:</span> <span class="punct">&#8220;</span><span class="string">some route</span><span class="punct">&#8220;</span>
    <span class="attribute">@http_maker</span><span class="punct">.</span><span class="ident">should_receive</span><span class="punct">(</span><span class="symbol">:POST_content_from</span><span class="punct">).</span><span class="ident">once</span><span class="punct">.</span>
                <span class="ident">with</span><span class="punct">(</span><span class="symbol">:date</span> <span class="punct">=></span> <span class="punct">&#8216;</span><span class="string">an effective date</span><span class="punct">&#8216;,</span>
                     <span class="symbol">:animals</span> <span class="punct">=></span> <span class="punct">&#8220;</span><span class="string">some animals</span><span class="punct">&#8220;).</span>
                <span class="ident">and_return</span><span class="punct">(&#8217;</span><span class="string">post content</span><span class="punct">&#8216;)</span>
    <span class="attribute">@future_maker</span><span class="punct">.</span><span class="ident">should_receive</span><span class="punct">(</span><span class="symbol">:spawn_POST</span><span class="punct">).</span><span class="ident">once</span><span class="punct">.</span>
                  <span class="ident">with</span><span class="punct">(&#8217;</span><span class="string">some route</span><span class="punct">&#8216;,</span> <span class="punct">&#8216;</span><span class="string">post content</span><span class="punct">&#8216;)</span>
  <span class="punct">}</span>
<span class="keyword">end</span>
</pre>
<p>I&#8217;ve done something sneaky here. In real life, <code><span class="ident">remove_from_service</span></code> will take actual <code><span class="ident">Animal</span></code> objects. In Objective-J, they&#8217;d be created like this:</p>
<pre>  <span class="ident">betsy</span> <span class="punct">=</span> <span class="punct">[[</span><span class="constant">Animal</span> <span class="ident">alloc</span><span class="punct">]</span> <span class="ident">initWithName</span><span class="punct">:</span> <span class="punct">&#8216;</span><span class="string">betsy</span><span class="punct">&#8216;</span> <span class="ident">kind</span><span class="punct">:</span> <span class="punct">&#8216;</span><span class="string">cow</span><span class="punct">&#8216;];</span>
</pre>
<p>But facts about Animals&#8211;that, say, they have names and kinds&#8211;are irrelevant to the purpose of this method. All it does is hand an incoming list of them to a converter method. So&#8211;in such a case&#8211;why not use strings that describe the arguments instead of the arguments themselves? </p>
<pre>
    <span class="attribute">@sut</span><span class="punct">.</span><span class="ident">remove_from_service</span><span class="punct">(&#8221;</span><span class="string">some animals</span><span class="punct">&#8220;,</span> <span class="punct">&#8220;</span><span class="string">an effective date</span><span class="punct">&#8220;)</span>
</pre>
<p>In Java, type safety rarely lets you do that, but why let the legacy of Java affect us in languages like Ruby?</p>
<p>Now, I&#8217;m not sure how often these descriptive arguments are a good idea. One could argue that integration errors are a danger with mocks anyway, and that not using real examples of what flows between objects only increases that danger. Or that the increase in clarity for some is outweighed by a decrease for others: if you don&#8217;t understand what&#8217;s meant by the strings, there&#8217;s nothing (like looking at how test data was constructed) to help you. I haven&#8217;t found either of those to be a problem yet, but it is my own code after all.</p>
<p>(I will note that I do add some type hints. For example, I&#8217;m increasingly likely to write this:</p>
<pre>    <span class="attribute">@sut</span><span class="punct">.</span><span class="ident">remove_from_service</span><span class="punct">(<b>[&#8221;</b></span><span class="string">some animals</span><span class="punct">&#8220;],</span> <span class="punct">&#8220;</span><span class="string">an effective date</span><span class="punct">&#8220;)</span>
</pre>
<p>I&#8217;ve put &#8220;some animals&#8221; in brackets to emphasize that the argument is an array.)</p>
<p>If you&#8217;ve done something similar to this, let&#8217;s talk about it at a conference sometime. In the next few months, I&#8217;ll be at <a href="http://speakerconf.com/">Speakerconf</a>, the <a href="http://www.scandevconf.se/">Scandinavian Developer Conference</a>, <a href="http://www.phillyemergingtech.com/">Philly Emerging Tech</a>, an Agile Day in Costa Rica, and possibly <a href="http://www.phillyemergingtech.com/">Scottish Ruby Conference</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.exampler.com/blog/2010/01/13/mocks-the-removal-of-test-detail-and-dynamically-typed-languages/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Some preliminary thoughts on end-to-end testing in Growing Object-Oriented Software</title>
		<link>http://www.exampler.com/blog/2010/01/08/some-preliminary-thoughts-on-end-to-end-testing-in-growing-object-oriented-software/</link>
		<comments>http://www.exampler.com/blog/2010/01/08/some-preliminary-thoughts-on-end-to-end-testing-in-growing-object-oriented-software/#comments</comments>
		<pubDate>Fri, 08 Jan 2010 16:48:51 +0000</pubDate>
		<dc:creator>Brian Marick</dc:creator>
		
		<category><![CDATA[TDD]]></category>

		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.exampler.com/blog/2010/01/08/some-preliminary-thoughts-on-end-to-end-testing-in-growing-object-oriented-software/</guid>
		<description><![CDATA[I&#8217;ve been working through Growing Object-Oriented Software (henceforth #goos), translating it into Ruby. An annoyingly high percentage of my time has been spent messing with the end-to-end tests. Part of that is due to a cavalcade of incompatibilities that made me fake out an XMPP server within the same process as the app-under-test (named the [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working through <i><a href="http://www.growing-object-oriented-software.com/">Growing Object-Oriented Software</a></i> (henceforth <a href="http://twitter.com/#search?q=%23goos">#goos</a>), <a href="http://github.com/marick/growing-oo-software-in-ruby">translating it into Ruby</a>. An annoyingly high percentage of my time has been spent messing with the end-to-end tests. Part of that is due to a cavalcade of incompatibilities that made me fake out an XMPP server within the same process as the app-under-test (named <i>the Auction Sniper</i>), the Swing GUI thread, and the GUI scraper. Threading hell.</p>
<p>But part of it is not. Part of it is because end-to-end tests just <i>are</i> awkward and fragile (which #goos is careful to point out). If such tests are worth it, it&#8217;s because some combination of these sources of value outweighs their cost:</p>
<ul>
<li>
<p>
They help clarify everyone&#8217;s understanding of the <b>problem to be solved</b>.
</p>
</li>
<li>
<p>
Trying to make the tests run fast, be less fragile, be easier to debug in the case of failure, etc. makes the app&#8217;s <b>overall design better</b>.
</p>
</li>
<li>
<p>
They <b>detect incorrect changes</b> (that is, changes in behavior that were not intended, as distinct from ones you did intend that will require the test to be changed to make it an example of the newly-correct behavior).
</p>
</li>
<li>
<p>
They provide a <b>cadence</b> to the programming, helping to break it up into nicely-sized chunks.
</p>
</li>
</ul>
<p>In working through #goos so far (chapter 16), the end-to-end tests have not found any bugs, so zero value there. I realized last night, though, that what most bugged me about them is that they made my programming &#8220;ragged&#8221;&#8211;that is, I kept microtesting away, changing classes, being happy, but when I popped up to run the end-to-end test I was working on, it or another one would break in a way that did not feel helpful. (However, I should note that it&#8217;s a different thing to try to mimic someone else&#8217;s solution than to conjure up your own, so some of the jerkiness is just inherent to learning from a book.) </p>
<p>I think part of the problem is the style of the tests. Here&#8217;s one of them, written with <a href="http://cukes.info/">Cucumber</a>:</p>
<pre>
   Scenario: Sniper makes a higher bid, but loses
       Given the sniper has joined an ongoing auction
       When the auction reports another bidder has bid 1000 (and that the next increment is 98)
       Then the sniper shows that it's bidding 1098 to top the previous price
           And the auction receives a bid of 1098 from the sniper

       When the auction closes
       Then the sniper shows that it's lost the auction
</pre>
<p>This test describes <i>all</i> the outwardly-observable behavior of the Sniper over time. Most importantly, at each point, it talks about two interfaces: the XMPP interface and the GUI. During coding, I found that context switching unsettling (possibly because I have an uncommonly bad short- and medium-term memory for a programmer). Worse, I don&#8217;t believe this style of test really helps to clarify the problem to be solved. There are two issues: what the Sniper <i>does</i> (bid in an auction) and what it <i>shows</i> (information about the known state of the auction). They can be talked about separately.</p>
<p>What the Sniper <i>does</i> is most clearly described by a state diagram (as on p. 85) or state table. A state diagram may not be the right thing to show a non-technical product owner, but the idea of the &#8220;state of the auction&#8221; is not conceptually very foreign (indeed, the imaginary product owner has asked for it to be shown in the user interface). So we could write something like this on a blackboard:</p>
<p><img src="http://www.exampler.com/blog/wp-content/uploads/2010/01/joined.png" height="293" width="528"/></p>
<p>Just as in #goos, this is enough to get us started. We have an example of a single state transition, so let&#8217;s implement it! The blackboard text can be written down in whatever test format suits your fancy: Fit table, Cucumber text, programming language text, etc. </p>
<p><b>Where do we stand?</b></p>
<p>At this point, the single Cucumber test I showed above is breaking into at least three tests: the one on the blackboard, a similar one for the BIDDING to LOSING transition, and something as yet undescribed for the GUI. Two advantages to that: first, a correct change to the code should only break one of the tests. That breakage can&#8217;t be <i>harder</i> to figure out than breaking the single, more complicated test. Second, and maybe it&#8217;s just me, but I feel better getting triumphantly to the end of a medium-sized test than I do getting partway through a bigger end-to-end one.</p>
<p>The test on the blackboard is still a <a href="http://www.exampler.com/old-blog/2003/08/21/#agile-testing-project-1">business-facing</a> test; it&#8217;s written in the language of the business, not the language of the implementation, and it&#8217;s talking about the application, not pieces of it.</p>
<p>Here&#8217;s one implementation of the blackboard test. I&#8217;ve written it in my normal Ruby microtesting style because that shows more of the mechanism. </p>
<pre>
<span class="ident">context</span> <span class="punct">&#8220;</span><span class="string">pending state</span><span class="punct">&#8220;</span> <span class="keyword">do</span>

  <span class="ident">setup</span> <span class="keyword">do</span>
    <span class="ident">start_app_at</span><span class="punct">(</span><span class="constant">AuctionSnapshot</span><span class="punct">.</span><span class="ident">new</span><span class="punct">(</span><span class="symbol">:state</span> <span class="punct">=></span> <span class="constant">PENDING</span><span class="punct">))</span>
  <span class="keyword">end</span>

  <span class="ident">should</span> <span class="punct">&#8220;</span><span class="string">respond to a new price by counter-bidding the minimum amount</span><span class="punct">&#8220;</span> <span class="keyword">do</span>
    <span class="ident">during</span> <span class="punct">{</span>
      <span class="attribute">@app</span><span class="punct">.</span><span class="ident">receive_auction_event</span><span class="punct">(</span><span class="constant">AuctionEvent</span><span class="punct">.</span><span class="ident">price</span><span class="punct">(</span><span class="symbol">:price</span> <span class="punct">=></span> <span class="number">1000</span><span class="punct">,</span>
                                                    <span class="symbol">:increment</span> <span class="punct">=></span> <span class="number">98</span><span class="punct">,</span>
                                                    <span class="symbol">:bidder</span> <span class="punct">=></span> <span class="punct">&#8220;</span><span class="string">someone else</span><span class="punct">&#8220;))</span>
    <span class="punct">}.</span><span class="ident">behold!</span> <span class="punct">{</span>
      <span class="attribute">@transport_translator</span><span class="punct">.</span><span class="ident">should_receive</span><span class="punct">(</span><span class="symbol">:bid</span><span class="punct">).</span><span class="ident">once</span><span class="punct">.</span><span class="ident">with</span><span class="punct">(</span><span class="number">1098</span><span class="punct">)</span>
      <span class="attribute">@anyone_who_cares</span><span class="punct">.</span><span class="ident">should_receive_notification</span><span class="punct">(</span><span class="constant">STATE_CHANGE</span><span class="punct">).</span><span class="ident">at_least</span><span class="punct">.</span><span class="ident">once</span><span class="punct">.</span>
                        <span class="ident">with</span><span class="punct">(</span><span class="constant">AuctionSnapshot</span><span class="punct">.</span><span class="ident">new</span><span class="punct">(</span><span class="symbol">:state</span> <span class="punct">=></span> <span class="constant">BIDDING</span><span class="punct">,</span>
                                                 <span class="symbol">:last_price</span> <span class="punct">=></span> <span class="number">1000</span><span class="punct">,</span>
                                                 <span class="symbol">:last_bid</span> <span class="punct">=></span> <span class="number">1098</span><span class="punct">))</span>
    <span class="punct">}</span>
  <span class="keyword">end</span>
<span class="keyword">end</span>
</pre>
<p>Here&#8217;s a picture of that test in action. It is <i>not</i> end-to-end because it doesn&#8217;t test the translation to-and-from XMPP. </p>
<p><img src="http://www.exampler.com/blog/wp-content/uploads/2010/01/test.png" height="405" width="535" /></p>
<p>In order to check that the Sniper has the right internal representation of what&#8217;s going on in the auction, I have it fling out (via the Observer or Publish/Subscribe pattern) information about that. That would seem to be an encapsulation violation, but this is only the information that we&#8217;ve determined (at the blackboard, above) to be relevant in/to the world outside the app. So it&#8217;s not like exposing whether internal data is stored in a dictionary, list, array, or tree. </p>
<p>At this point, I&#8217;d build the code that passed this test and others like it in the normal #goos outside-in style. Then I&#8217;d microtest the translation layer into existence. And then I&#8217;d do an end-to-end test, but I&#8217;d do it <i>manually</i>. (Gasp!) That would involve building much the same fake auction server as in #goos, but with some sort of rudimentary user interface that&#8217;d let me send appropriately formatted XMPP to the Sniper. (Over the course of the project, this would grow into a more capable tool for manual exploratory testing.)</p>
<p>So the test would mean starting the XMPP server, starting the fake auction and having it log into the server, starting the Sniper, checking that the fake auction got a JOIN request, and sending back a PRICE event. This is just to see the individual pieces fitting together. Specifically:</p>
<ul>
<li>
Can the translation layer receive real XMPP messages?
</li>
<li>
Does it hand the Sniper what it expects?
</li>
<li>
Does the outgoing translation layer/object really translate into XMPP?
</li>
</ul>
<p>The final question&#8211;is the XMPP message&#8217;s payload in the right format for the auction server?&#8211;can&#8217;t really be tested until we have a real auction server to hook up to. As discussed in #goos, those servers aren&#8217;t readily available, which is why the book uses fake ones. So, in a real sense, my strategy is the same as #goos&#8217;s: test as end-to-end as you reasonably can and plug in fakes for the ends (or middle pieces) that are too hard to reach. We just have a different interpretation of &#8220;reasonably can&#8221; and &#8220;too hard to reach&#8221;. </p>
<p>Having done that for the first test, would I do it again for the BIDDING to LOSING transition test? Well, yeah, probably, just to see a two-step transition. But by the time I finished all the transitions, I suspect code to pass the next transition test would be so unlikely to affect integration of interfaces that I wouldn&#8217;t bother. </p>
<p>Moreover, having finished the Nth transition test, I would only exercise what I&#8217;d changed. I would <i>not</i> (<b>not, not, not!</b>) run all the previous tests as if I were a slow and error-prone automated test suite. (Most likely, though, I&#8217;d try to vary my manual test, making it different from both the transition test that prompted the code changes and from previous manual tests. Adding easy variety to tests can both help you stumble across bugs and&#8211;more importantly&#8211;make you realize new things about the problem you&#8217;re trying to solve and the product you&#8217;re trying to build.) </p>
<p>What about real automated end-to-end tests?</p>
<p>I&#8217;d let reality (like the reality of missed bugs or tests hard to do manually) force me to add end-to-end tests of the #goos sort, but I would probably never have anywhere near the number of end-to-end scenario/workflow tests that #goos recommends (as of chapter 16). While I think workflows are a nice way of fleshing out a story or feature, a good way to start generating tests, and a dandy conversation tool, none of those things require automation.</p>
<p>I could do any number of my state-transition tests, making the Sniper ever more competent at dealing with auctions, but I&#8217;d probably get to the GUI at about the same time as #goos. </p>
<p>What do we know of the GUI? We know it has to faithfully display the externally-relevant known state of the auction. That is, it has to subscribe to what the Sniper already publishes. I imagine I&#8217;d have the same microtests and implementation as #goos (except for having the Swing TableModel subscribe instead of being called directly). </p>
<p>Having developed the TableModel to match my tests, I&#8217;d still have to check whether it matches the real Swing implementation. I&#8217;d do that manually until I was dragged kicking and screaming into using some GUI scraping tool to automate it.</p>
<p><b>How do I feel?</b></p>
<p>Nervous. #goos has not changed my opinion about end-to-end tests. But its authors are smarter and more experienced than I am. So why do they love&#8211;or at least accept&#8211;end-to-end tests while I fear and avoid them?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.exampler.com/blog/2010/01/08/some-preliminary-thoughts-on-end-to-end-testing-in-growing-object-oriented-software/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Want to pair with me?</title>
		<link>http://www.exampler.com/blog/2010/01/04/want-to-pair-with-me/</link>
		<comments>http://www.exampler.com/blog/2010/01/04/want-to-pair-with-me/#comments</comments>
		<pubDate>Tue, 05 Jan 2010 02:25:10 +0000</pubDate>
		<dc:creator>Brian Marick</dc:creator>
		
		<category><![CDATA[agile]]></category>

		<guid isPermaLink="false">http://www.exampler.com/blog/2010/01/04/want-to-pair-with-me/</guid>
		<description><![CDATA[I&#8217;ll be flying out of Miami for SpeakerConf. I&#8217;m thinking of taking the train there, and stopping to pair with people along the way (in the manner of Corey Haine&#8217;s pair programming tour). The basic idea is that we should pair on some real software that either you or I are working on right now. [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ll be flying out of Miami for SpeakerConf. I&#8217;m thinking of taking the train there, and stopping to pair with people along the way (in the manner of Corey Haine&#8217;s <a href="http://programmingtour.blogspot.com">pair programming tour</a>). The basic idea is that we should pair on some real software that either you or I are working on right now. The type of software or programming language doesn&#8217;t matter. If you feed me or give me a place to sleep, that would be fine - but not necessary.</p>
<p>If you&#8217;d like to do that, <a href="mailto:marick@exampler.com">send me mail</a>. </p>
<p>I could take one of two trains to Washington, DC. The first follows <a href="http://www.amtrak.com/servlet/ContentServer/AM_Route_C/1241245652448/1237405732511">this route</a>:</p>
<p><img src="http://www.exampler.com/blog/wp-content/uploads/2010/01/ord-dc.gif" height="200" width="600" border="1" hspace="4" vspace="4" alt="Ord-Dc" /></p>
<p>or <a href="http://www.amtrak.com/servlet/ContentServer/AM_Route_C/1241245652139/1237405732511">this one</a>:</p>
<p><img src="http://www.exampler.com/blog/wp-content/uploads/2010/01/chi-dc2.gif" height="200" width="600" border="1" hspace="4" vspace="4" alt="Chi-Dc2" /></p>
<p>From DC, I&#8217;d travel down the coast along <a href="http://www.amtrak.com/servlet/ContentServer/AM_Route_C/1237608339450/1237405732511">this route</a>:</p>
<p><img src="http://www.exampler.com/blog/wp-content/uploads/2010/01/downward.gif" height="600" width="193" border="1" hspace="4" vspace="4" alt="Downward" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.exampler.com/blog/2010/01/04/want-to-pair-with-me/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Growing Object-Oriented Software - In Ruby!</title>
		<link>http://www.exampler.com/blog/2009/12/17/growing-object-oriented-software-in-ruby/</link>
		<comments>http://www.exampler.com/blog/2009/12/17/growing-object-oriented-software-in-ruby/#comments</comments>
		<pubDate>Thu, 17 Dec 2009 23:48:08 +0000</pubDate>
		<dc:creator>Brian Marick</dc:creator>
		
		<category><![CDATA[agile]]></category>

		<guid isPermaLink="false">http://www.exampler.com/blog/2009/12/17/growing-object-oriented-software-in-ruby/</guid>
		<description><![CDATA[I&#8217;m working through Steve Freeman and Nat Pryce&#8217;s Growing Object-Oriented Software, Guided by Tests, translating their Java into Ruby. I&#8217;ve put it up as a Github project if you&#8217;d like to follow along.
]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m working through <a href="http://twitter.com/sf105">Steve Freeman</a> and <a href="http://twitter.com/natpryce">Nat Pryce</a>&#8217;s <i><a href="http://www.growing-object-oriented-software.com/">Growing Object-Oriented Software, Guided by Tests</a></i>, translating their Java into Ruby. I&#8217;ve put it up as a <a href="http://github.com/marick/growing-oo-software-in-ruby">Github project</a> if you&#8217;d like to follow along.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.exampler.com/blog/2009/12/17/growing-object-oriented-software-in-ruby/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
