<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Talk Like A Duck: Tag bdd</title>
    <link>http://talklikeaduck.denhaven2.com/articles/tag/bdd</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>In Ruby, it's not the dog, it's the tricks!</description>
    <item>
      <title>Why I Don't Mind Using RSpec - In Fact I've Come to Love It.</title>
      <description>&lt;p&gt;About a year ago when I first encountered RSpec, I thought that the idea sounded good, but I was concerned about how much the implementation at that time pushed new methods into Object and Kernel. It felt to me as though it could interfere with the code being specified/tested. Indeed back then there were some problems when RSpec and Rails bumped heads over the use of certain Ruby metaprogramming techniques.  I&amp;#8217;d been a &lt;span class="caps"&gt;TDD&lt;/span&gt; user advocate for many years, heck I was there right after Kent Beck, &amp;#8220;test-infected&amp;#8221; Erich Gamma and sat in on some of their early pairing sessions during an annual &lt;span class="caps"&gt;OTI&lt;/span&gt; company technical conference at Montebello in Quebec, when JUnit was in it&amp;#8217;s infancy.  The cleaner language of RSpec did have it&amp;#8217;s attractions, particularly in trying to get across the idea to newcomers that &lt;span class="caps"&gt;TDD&lt;/span&gt; was really writing mini-specifications rather than tests, which helps put them in the right mindset, but for those of us who had already crossed that paradigm shift, or been born on the right side of it, it didn&amp;#8217;t seem so important.&lt;/p&gt;


	&lt;p&gt;Since then the RSpec implementation has matured, and after talking to David Chelimsky and Dave Astels at RubyConf, I decided to give it another look, and, armed with a new perspective on the use of mocks and stubs to isolate specifications and tests in &lt;span class="caps"&gt;BDD&lt;/span&gt;/TDD, I quickly became a convert.  I still use other frameworks as external requirements dictate, but RSpec has become my first choice.&lt;/p&gt;


	&lt;p&gt;These days, though the choice of testing/specification framework seems to have become one of those religious issues which divide the community, almost as much as emacs vs. vim vs. textmate.  I run into people all the time who reject RSpec because it&amp;#8217;s &amp;#8220;too magical!&amp;#8221;  Although I&amp;#8217;ve never been able to get them to expand on that thought. Perhaps it&amp;#8217;s based on the kind of concerns I had about it at first, maybe it&amp;#8217;s something else.  I&amp;#8217;d love to have it explained.&lt;/p&gt;


	&lt;p&gt;And like advocates do, other arguments get expressed, some of which don&amp;#8217;t get the scrutiny they deserve.&lt;/p&gt;


	&lt;p&gt;For example, a few days ago Rob Sanheim, someone I know and respect, wrote about why &lt;a href="http://robsanheim.com/2008/01/25/why-i-use-testspec-over-rspec/"&gt;he eschews RSpec for Test::Spec&lt;/a&gt;. His basic, quite brief argument is that because RSpec is 10 times bigger in terms of lines of code than Test::Spec it must be worse.&lt;/p&gt;


&lt;h2&gt;How to Lie with Statistics&lt;/h2&gt;
Nice statistics, but back when I was in college, one of the must-read books was &amp;#8220;How to Lie with Statistics&amp;#8221;.  Given the right pick of statistics you can prove anything.

	&lt;p&gt;First off I think that Rob was unfair to lump the lib and spec or test directories together.  Even if you might believe that code bulk is bad, I think that it&amp;#8217;s reasonable to think of the code bulk in the implementation to be like &amp;#8216;bad cholesterol&amp;#8217;, and test-code which verifies that implementation as &amp;#8216;good cholesterol.&amp;#8217;  Most of you are probably too young to be concerned about it yet, but my doctors tell me that a high &lt;span class="caps"&gt;HDL&lt;/span&gt;/LDL ratio is more important than an absolute &lt;span class="caps"&gt;HDL&lt;/span&gt;+LDL.  The theory at least is that the &lt;span class="caps"&gt;HDL&lt;/span&gt; helps sweep the &lt;span class="caps"&gt;LDL&lt;/span&gt; out of the vessels, kind of like a good test suite keeps code under control.&lt;/p&gt;


	&lt;p&gt;Here are the numbers I get running sloccount on the latest RSpec and test/unit gems:&lt;/p&gt;


	&lt;table style="border:1px solid black; align:right;"&gt;
		&lt;tr&gt;
			&lt;th&gt;Framework &lt;/th&gt;
			&lt;th&gt;lib &lt;/th&gt;
			&lt;th&gt;spec/test&lt;/th&gt;
			&lt;th&gt;test/code ratio &lt;/th&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt; Rspec &lt;/td&gt;
			&lt;td&gt; 5473 &lt;/td&gt;
			&lt;td&gt;10108  &lt;/td&gt;
			&lt;td&gt; 1.8 &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt; Test::Spec &lt;/td&gt;
			&lt;td&gt; 275 &lt;/td&gt;
			&lt;td&gt; 879 &lt;/td&gt;
			&lt;td&gt; 3.2 &lt;/td&gt;
		&lt;/tr&gt;
	&lt;/table&gt;




	&lt;p&gt;So at first blush it looks bad for RSpec, Test::Spec even tests itself more thoroughly!&lt;/p&gt;


	&lt;p&gt;The real problem with Rob&amp;#8217;s post is that he&amp;#8217;s comparing Apple seeds with Apples.  Of course Test::Spec is considerably smaller than RSpec, it&amp;#8217;s a bump on Test::Unit to add the new assertion style.  So we need to at least add Test::Unit&amp;#8217;s numbers&lt;/p&gt;


	&lt;table style="border:1px solid black; align:right;"&gt;
		&lt;tr&gt;
			&lt;th&gt;Framework &lt;/th&gt;
			&lt;th&gt;lib &lt;/th&gt;
			&lt;th&gt;spec/test&lt;/th&gt;
			&lt;th&gt;test/code ratio &lt;/th&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt; Test:Unit &lt;/td&gt;
			&lt;td&gt; 2741 &lt;/td&gt;
			&lt;td&gt; 0 &lt;/td&gt;
			&lt;td&gt; 0 &lt;/td&gt;
		&lt;/tr&gt;
	&lt;/table&gt;




	&lt;p&gt;Now I&amp;#8217;m sure that Nathaniel &amp;#8220;ate his own dog food&amp;#8221; when he developed Test::Unit, and Ryan is continuing to dine on it, now that he&amp;#8217;s taken over its maintenance, but that dog food apparently doesn&amp;#8217;t leave home.  Now if we look at the combination of Test::Unit and Test::Spec the comparison looks like this:&lt;/p&gt;


	&lt;table style="border:1px solid black; align:right;"&gt;
		&lt;tr&gt;
			&lt;th&gt;Framework &lt;/th&gt;
			&lt;th&gt;lib &lt;/th&gt;
			&lt;th&gt;spec/test&lt;/th&gt;
			&lt;th&gt;test/code ratio &lt;/th&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt; Rspec &lt;/td&gt;
			&lt;td&gt; 5473 &lt;/td&gt;
			&lt;td&gt;10108  &lt;/td&gt;
			&lt;td&gt; 1.8 &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt; TU+TS &lt;/td&gt;
			&lt;td&gt; 2713 &lt;/td&gt;
			&lt;td&gt; 879 &lt;/td&gt;
			&lt;td&gt; 0.3 &lt;/td&gt;
		&lt;/tr&gt;
	&lt;/table&gt;




	&lt;p&gt;So RSpec looks a little better, particularly when it comes to eating it&amp;#8217;s own dog food.&lt;/p&gt;


	&lt;p&gt;But, as that Billy Mays guy on the Infomercials is wont to say, &amp;#8220;Wait! There&amp;#8217;s more!&amp;#8221;.&lt;/p&gt;


	&lt;p&gt;RSpec also includes a built-in mocking framework, now with the &amp;#8216;traditional&amp;#8217; choice you need to throw in your choice of mock framework, here&amp;#8217;s are the stats for Flexmock and Mocha&lt;/p&gt;


	&lt;table style="border:1px solid black; align:right;"&gt;
		&lt;tr&gt;
			&lt;th&gt;Framework &lt;/th&gt;
			&lt;th&gt;lib &lt;/th&gt;
			&lt;th&gt;spec/test&lt;/th&gt;
			&lt;th&gt;test/code ratio &lt;/th&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt; Flexmock &lt;/td&gt;
			&lt;td&gt; 1034  &lt;/td&gt;
			&lt;td&gt; 2743 &lt;/td&gt;
			&lt;td&gt; 2.6 &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt; Mocha    &lt;/td&gt;
			&lt;td&gt; 1218  &lt;/td&gt;
			&lt;td&gt; 3622 &lt;/td&gt;
			&lt;td&gt; 2.8 &lt;/td&gt;
		&lt;/tr&gt;
	&lt;/table&gt;




	&lt;p&gt;So now we&amp;#8217;ve got two sub-variants to look at:&lt;/p&gt;


	&lt;table style="border:1px solid black; align:right;"&gt;
		&lt;tr&gt;
			&lt;th&gt;Framework &lt;/th&gt;
			&lt;th&gt;lib &lt;/th&gt;
			&lt;th&gt;spec/test&lt;/th&gt;
			&lt;th&gt;test/code ratio &lt;/th&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt; Rspec &lt;/td&gt;
			&lt;td&gt; 5473 &lt;/td&gt;
			&lt;td&gt;10108  &lt;/td&gt;
			&lt;td&gt; 1.8 &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt; TU+TS+FM &lt;/td&gt;
			&lt;td&gt; 3747 &lt;/td&gt;
			&lt;td&gt; 3622 &lt;/td&gt;
			&lt;td&gt; 1.0 &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt; TU+TS+Mocha &lt;/td&gt;
			&lt;td&gt; 3931 &lt;/td&gt;
			&lt;td&gt;  3931 &lt;/td&gt;
			&lt;td&gt; 1.1 &lt;/td&gt;
		&lt;/tr&gt;
	&lt;/table&gt;




	&lt;p&gt;Now you might say that RSpec still is 40% larger than even the larger of the two competing combinations, but this is also ignoring the fact that RSpec also includes RBehave which is another higher level integration/acceptance testing framework.&lt;/p&gt;


	&lt;p&gt;So in retrospect, I&amp;#8217;d humbly submit that code bulk isn&amp;#8217;t such a good comparison criteria in this case.&lt;/p&gt;


	&lt;p&gt;So whatever your test framework &amp;#8216;belief system&amp;#8217; do as you feel best, but do unto others!&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;d still like to hear more about why people think that RSpec is &amp;#8220;too magic&amp;#8221; though.&lt;/p&gt;


	&lt;p&gt;By the way on the subject of lying statistics.  I&amp;#8217;m sure that most of us have by now seen &lt;a href="http://www.indeed.com/jobtrends?q=ruby%2C+java&amp;#38;relative=1"&gt;this chart of Ruby job prospects.&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Which looks like, and is, &lt;span class="caps"&gt;GREAT&lt;/span&gt; news for Rubyists, but how many have seen &lt;a href="http://www.indeed.com/jobtrends?q=ruby%2C+java"&gt;this from the same source.&lt;/a&gt; It&amp;#8217;s the same data, just looked at through a different lens.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;m still not looking for Java work though!&lt;/p&gt;</description>
      <pubDate>Tue, 29 Jan 2008 16:24:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:29b762a2-2d17-453e-9346-48acb81d03d2</guid>
      <author>Rick DeNatale</author>
      <link>http://talklikeaduck.denhaven2.com/articles/2008/01/29/why-i-dont-mind-using-rspec-in-fact-ive-come-to-love-it</link>
      <category>ruby</category>
      <category>rails</category>
      <category>tdd</category>
      <category>bdd</category>
      <category>Rspec</category>
      <category>TestUnit</category>
      <category>TestSpec</category>
      <trackback:ping>http://talklikeaduck.denhaven2.com/articles/trackback/485</trackback:ping>
    </item>
    <item>
      <title>Refactoring With Continuous Testing - a Guided Tour</title>
      <description>&lt;div style='width:180; float:left; text-align:right; font-size:xx-small; border-width:1px; border-color:#444444; border-style:solid; padding:3px; margin-bottom:30px; margin-right:30px;'&gt;&lt;img src="http://talklikeaduck.denhaven2.com/files/2007-10-11_davidcensoredonrefrigerator.jpg" alt="DavidCensoredOnRefrigerator" height="240" width="180" title="Photo by Flickr user melomane, cc-by-nc-sa"&gt;&lt;br/&gt;
&lt;a href='http://flickr.com/photos/melomane/333546498/'&gt;Refrigerator Censorship&lt;/a&gt;
&lt;br/&gt;&amp;copy;
&lt;a href='http://flickr.com/people/melomane'&gt;&lt;/a&gt;
&lt;br/&gt;&lt;a href='http://creativecommons.org/licenses/by-nc-nd/2.0/'&gt;&lt;img src='http://i.creativecommons.org/l/by-nc-nd/2.0/80x15.png' title='used under a Creative Commons Attribution-NonCommercial-NoDerivs License' width='80' height='15' border='0'/&gt;&lt;/a&gt;
&lt;/div&gt;

Today on &lt;a href="http://www.rubyfleebie.com/rubyize-this-3rd-edition/"&gt;Ruby Fleebie&lt;/a&gt;, Frank poses some ruby code to be "rubyized." I took this as an opportunity to do a little exposition of re-factoring under the watchful eye of 
&lt;a href="http://www.zenspider.com/ZSS/Products/ZenTest/"&gt;autotest.&lt;/a&gt;
&lt;p&gt;So I've taken Frank's code and run it through the re-factoring machine several times.  A word to the 'squeamish' because of the use case, there are a few words in the code which some folks, and spam filters might find mildly offensive, but we're all adults here right?&lt;/p&gt;
&lt;p&gt;Now I've got to admit that I really came up with the final solution pretty quickly after seeing the blog post, but then I went back and eased up to it for pedagogical purposes.  So if you're in the mood, sit down and lets re-factor some ruby!&lt;/p&gt;




&lt;h2&gt;The Original Code&lt;/h2&gt;
&lt;p&gt;Here's Frank's original code:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;&lt;notextile&gt;def remove_insults(input)
  ctr = 0
  input.each do |word|
    word = word.downcase
    if word == &amp;quot;stupid&amp;quot; || word == &amp;quot;moron&amp;quot; || 
       word == &amp;quot;dumbass&amp;quot; || word == &amp;quot;retard&amp;quot;
      i=0
      word.length.times do
        input[ctr][i,1] = &amp;quot;*&amp;quot;
        i+=1
      end
    end
    ctr += 1
  end
  puts input.join(&amp;quot; &amp;quot;).to_s 
end
remove_insults &amp;quot;you truly are a moron sir!&amp;quot;.split(&amp;quot; &amp;quot;)  &lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
I've split one line (the long if statement) to try to keep the horizontal scrolling down when viewed here.
&lt;h2&gt;Getting Ready for Autotest&lt;/h2&gt;
&lt;p&gt;My first step was to setup a local subversion repository, so that I could go back over my work and tell you about it.  Then I set up a project directory structure and imported it.&lt;/p&gt;
&lt;/p&gt;Autotest want's a particular directory structure, so I set up a project directory with a lib subdirectory to hold the code, and a test directory to hold the testcase.  The code also needs to be structured as a class, so I changed the code a bit and put it in lib/civilizer.rb&lt;/p&gt; 
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Civilizer&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.remove_insults&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="ident"&gt;civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;ctr&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;
    &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
      &lt;span class="ident"&gt;word&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;downcase&lt;/span&gt;
      &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;stupid&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;||&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;moron&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;||&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;dumbass&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;||&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;retard&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
        &lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="number"&gt;0&lt;/span&gt;
        &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;times&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
          &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;ctr&lt;/span&gt;&lt;span class="punct"&gt;][&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;*&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
          &lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;+=&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
      &lt;span class="ident"&gt;ctr&lt;/span&gt; &lt;span class="punct"&gt;+=&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt; 
  &lt;span class="keyword"&gt;end&lt;/span&gt;    
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="constant"&gt;Civilizer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;remove_insults&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;you truly are a moron sir!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;.&lt;/span&gt;&lt;span class="ident"&gt;split&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt; &lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that I also set this class up so that it has two methods, remove_insults prints the bowdlerized input, while civilize returns it as a string.  This change makes the code testable&lt;/p&gt; 
&lt;p&gt;Now we need a test case, that goes in test/test_civilizer.rb:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;&lt;notextile&gt;require &amp;quot;test/unit&amp;quot;

require &amp;quot;civilizer&amp;quot;

class TestCivilizer &amp;lt; Test::Unit::TestCase
  def test_case_name
    assert false    
  end
end&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;More autotest conventions here, we're testing the class Civilizer which lives in lib/civilizer.rb so that autotest can find it, the test case class needs to be TestCivilizer (i.e. the class under test suffixed by Test).&lt;/p&gt;
&lt;p&gt;This initial test case is designed to fail, at this stage I'm just verifying that autotest is happy with my setup, and runs the test when either the code under test or the test case changes.&lt;/p&gt;
&lt;h2&gt;A Real Test Case&lt;/h2&gt;
&lt;p&gt;The next step is to test the actual code. So I changed the test_case_name method (that clever name was generated by the textmate tc snippet by the way, and I didn't change it) to:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;test_basic_operation&lt;/span&gt;
    &lt;span class="ident"&gt;assert_equal&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;you truly are a ***** sir!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="constant"&gt;Civilizer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;civilize&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;you truly are a moron sir!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;.&lt;/span&gt;&lt;span class="ident"&gt;split&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;))&lt;/span&gt;  
  &lt;span class="keyword"&gt;end&lt;/span&gt; &lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When I save this, autotest runs the test and it passes.  Okay, now that we've got a baseline to refactor against, lets start changing code.&lt;/p&gt;
&lt;h2&gt;Our First Change&lt;/h2&gt;
&lt;p&gt;Let's make use of Ruby's Array#include? method and get rid of that if statement with the long chain of ||s:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Civilizer&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.remove_insults&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="ident"&gt;civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;ctr&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;
    &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
      &lt;span class="ident"&gt;word&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;downcase&lt;/span&gt;
      &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="punct"&gt;%w[&lt;/span&gt;&lt;span class="string"&gt;stupid moron dumbass retard&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;include?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
        &lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="number"&gt;0&lt;/span&gt;
        &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;times&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
          &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;ctr&lt;/span&gt;&lt;span class="punct"&gt;][&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;*&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
          &lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;+=&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
      &lt;span class="ident"&gt;ctr&lt;/span&gt; &lt;span class="punct"&gt;+=&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt; 
  &lt;span class="keyword"&gt;end&lt;/span&gt;    
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="constant"&gt;Civilizer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;remove_insults&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;you truly are a moron sir!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;.&lt;/span&gt;&lt;span class="ident"&gt;split&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Once again, I save this, and autotest automatically confirms that my change didn't break anything.&lt;/p&gt;
&lt;h2&gt;Let's Throw out a Loop or Two&lt;/h2&gt;
&lt;p&gt;That loop to generate the replacement string, seems unwieldy and error prone, let's get rid of it. Here's the new code. I'm focusing on just the method here, the rest of the file hasn't changed:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;ctr&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;
  &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
    &lt;span class="ident"&gt;word&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;downcase&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="punct"&gt;%w[&lt;/span&gt;&lt;span class="string"&gt;stupid moron dumbass retard&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;include?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;ctr&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;*&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="ident"&gt;ctr&lt;/span&gt; &lt;span class="punct"&gt;+=&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt; 
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Once again we've successfully cleaned up the code a bit, and the test success shows we haven't broken anything.&lt;/p&gt;
&lt;p&gt;While we're looking at loops, how about the one which steps through the words. We're initializing a counter before the loop and incrementing it at the bottom of the loop.  Smells too much like C if you ask me!&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each_with_index&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;ctr&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
    &lt;span class="ident"&gt;word&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;downcase&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="punct"&gt;%w[&lt;/span&gt;&lt;span class="string"&gt;stupid moron dumbass retard&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;include?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;ctr&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;*&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt; 
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now this looks more rubyish, but looking at it in retrospect, a better move here would have been to use input.map here with a block which returned either the original nice, or blotted out naughty word, but I didn't think of that at the time.  Of course with my tests I could go back and do that, but I'll leave that as an exercise for the interested reader.&lt;/p&gt;
&lt;p&gt;Anyway, that if statement in the middle is taking up more than it's share of vertical space, let's fix that by using a statement modifier:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each_with_index&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;ctr&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
    &lt;span class="ident"&gt;word&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;downcase&lt;/span&gt;
    &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;ctr&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;*&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="punct"&gt;%w[&lt;/span&gt;&lt;span class="string"&gt;stupid moron dumbass retard&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;include?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt; 
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This code is getting shorter and tidier as we go, although not as short and tidy as that idea of using map, oh well, but keep with me, it's going to end up real short.&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each_with_index&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;ctr&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
    &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;ctr&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;*&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="punct"&gt;%w[&lt;/span&gt;&lt;span class="string"&gt;stupid moron dumbass retard&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;include?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;downcase&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt; 
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I don't see any need for a separate assignment statement to downcase the input, so I moved that to the argument of include?, still shorter, but hang on.&lt;/p&gt;
&lt;h2&gt;Time For Some More Tests, and a Shift in Strategy&lt;/h2&gt;
&lt;p&gt;We've gotten to this point without changing any testcase code.  I've been using the testcase to ensure that I haven't changed the code in a way that would make it fail to meet the original 'specification.&lt;/p&gt;
&lt;p&gt;Let's revisit the testcase now. It's a pretty simple test case, how about some variations.  Here's a new test method I added to  test/test_civilizer.rb:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;test_should_find_multiple_words&lt;/span&gt;
  &lt;span class="ident"&gt;assert_equal&lt;/span&gt;  &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;With all due respect, you must be a ******, you *****!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; 
         &lt;span class="constant"&gt;Civilizer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;
                &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;With all due respect, you must be a retard, you moron!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;.&lt;/span&gt;&lt;span class="ident"&gt;split&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;))&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I've reformatted this a bit to try to keep it narrower for the blog presentation.&lt;/p&gt;
&lt;p&gt;Finally, when I save this, autotest informs me that the test has failed, a little debugging reveals that the problem is those pesky punctuation characters. That String#split method is limiting us to splitting words on spaces.&lt;/p&gt;
&lt;p&gt;Now one way to fix that would be to use a regexp instead of a string as the argument to String#split, but why not just use a regexp to implement the Civilizer, here's the new sleek version of the civilize method:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;gsub&lt;/span&gt;&lt;span class="punct"&gt;(/&lt;/span&gt;&lt;span class="regex"&gt;&lt;span class="escape"&gt;\b&lt;/span&gt;(stupid|moron|dumbass|retard)&lt;span class="escape"&gt;\b&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;/)&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;match&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;*&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt; &lt;span class="ident"&gt;match&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt;&lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;    &lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; 
&lt;p&gt;We've gotten the body of the method down to a one liner, &lt;strong&gt;and&lt;/strong&gt; we now properly handle punctuation!&lt;/p&gt;
&lt;h2&gt;The Value of [TB]DD&lt;/h2&gt;
&lt;p&gt;Let's add another test:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;test_should_ignore_case&lt;/span&gt;
  &lt;span class="ident"&gt;assert_equal&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;*******!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="constant"&gt;Civilizer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;civilize&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Dumbass!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Oops!&lt;/strong&gt; this test fails.  Our original tests didn't exercise the use of lowercase in the original code.	 &lt;/p&gt;
&lt;p&gt;This just shows that even test infected developers are human.  Actually if we had developed the original code in a test driven style, we wouldn't have invoked lowercase until we'd written a test case to motivate it.&lt;/p&gt;
&lt;p&gt;Another useful tool to talk about putting in the arsenal is a coverage tool like rcov which profiles your running tests to show how much of the code under test is being exercised, although in this case, it wouldn't have shown the problem&lt;/p&gt;
&lt;p&gt;Anyway, let's fix the problem, we just make the regexp case insensitive:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;gsub&lt;/span&gt;&lt;span class="punct"&gt;(/&lt;/span&gt;&lt;span class="regex"&gt;&lt;span class="escape"&gt;\b&lt;/span&gt;(stupid|moron|dumbass|retard)&lt;span class="escape"&gt;\b&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;match&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;*&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt; &lt;span class="ident"&gt;match&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt;&lt;span class="punct"&gt;}&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;All it took was one little 'i' to fix this bug.  Now autotest is once again showing us the green light.&lt;/p&gt;
&lt;h2&gt;Is the Specification Right?&lt;/h2&gt;
&lt;p&gt;I've been ignoring it all along, but having the caller split the input before giving it to the Civilizer has been bothering me even way before I changed the implementation to using gsub with a regexp, and since then, that code to 'unsplit' it has been sticking out like a sore thumb.  So, after switching from my consultant hat to my client hat and having a quick conference, "we've" agreed to change the interface so that the parameter is a simple string.&lt;/p&gt;
&lt;p&gt;Having agreed to this specification change, let's change the specification.  What do we change? The testcase code of course,  this is the point of test-driven design (or behavior driven design for you &lt;a href="http://www.google.com/url?sa=t&amp;ct=res&amp;cd=1&amp;url=http%3A%2F%2Fen.wikipedia.org%2Fwiki%2FSapir-Whorf_hypothesis"&gt;Sapir&#8211;Whorf&lt;/a&gt; &lt;a href="http://rspec.rubyforge.org/"&gt;adherents&lt;/a&gt;), whether you call them tests or something else, they are really specifications.&lt;/p&gt;
&lt;p&gt;Without further ado, here's the new spec:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;test/unit&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;civilizer&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;TestCivilizer&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;Test&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Unit&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;TestCase&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;test_should_find_one_word&lt;/span&gt;
    &lt;span class="ident"&gt;assert_equal&lt;/span&gt;             &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;you truly are a ***** sir!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;,&lt;/span&gt; 
          &lt;span class="constant"&gt;Civilizer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;civilize&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;you truly are a moron sir!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;  
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;test_should_find_multiple_words&lt;/span&gt;
    &lt;span class="ident"&gt;assert_equal&lt;/span&gt;              &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;With all due respect, you must be a ******, you *****!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; 
           &lt;span class="constant"&gt;Civilizer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;civilize&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;With all due respect, you must be a retard, you moron!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;test_should_ignore_case&lt;/span&gt;
    &lt;span class="ident"&gt;assert_equal&lt;/span&gt;           &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;*******!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; 
        &lt;span class="constant"&gt;Civilizer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;civilize&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Dumbass!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I've used slightly unusual formatting here too, which makes it easy to visually compare the expectation with the input.&lt;/p&gt;
&lt;p&gt;In good TDD style, we save this test &lt;strong&gt;before&lt;/strong&gt; we change the code to meet the new specification.  As we expected, autotest shows us a red light.  This is an indication that our changed tests are good.  Now let's change the code:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Civilizer&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.remove_insults&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="ident"&gt;civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;gsub&lt;/span&gt;&lt;span class="punct"&gt;(/&lt;/span&gt;&lt;span class="regex"&gt;&lt;span class="escape"&gt;\b&lt;/span&gt;(stupid|moron|dumbass|retard)&lt;span class="escape"&gt;\b&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="ident"&gt;i&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;match&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;*&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt; &lt;span class="ident"&gt;match&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt;&lt;span class="punct"&gt;}&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;    
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="constant"&gt;Civilizer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;remove_insults&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;you truly are a moron sir!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Meeting the new spec just required getting rid of the join in civilize, and the split in the final statement which gets executed when we run this code for 'real' as opposed to testing it.  Once again, the feedback from autotest goes green.&lt;/p&gt;
&lt;h2&gt;Test Code Deserves to Be Beautiful Too&lt;/h2&gt;
&lt;p&gt;At this point I stepped back and tidied up the test code.  I wanted to make it DRYer, so I introduced a private method to move the repeated code out of each test case:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;test/unit&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;civilizer&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;TestCivilizer&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;Test&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Unit&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;TestCase&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;test_should_find_one_word&lt;/span&gt;
    &lt;span class="ident"&gt;assert_civilizes&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;you truly are a moron sir!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; 
                     &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;you truly are a ***** sir!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; 
            
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;test_should_find_multiple_words&lt;/span&gt;
    &lt;span class="ident"&gt;assert_civilizes&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;With all due respect, you must be a retard, you moron!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt;
                     &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;With all due respect, you must be a ******, you *****!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;test_should_ignore_case&lt;/span&gt;
    &lt;span class="ident"&gt;assert_civilizes&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Dumbass!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt;
                     &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;*******!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt; 
  
  &lt;span class="ident"&gt;private&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;assert_civilizes&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;expected&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;assert_equal&lt;/span&gt; &lt;span class="ident"&gt;expected&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="constant"&gt;Civilizer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;civilize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;input&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I don't know about you, but I like the way this code looks.  I made a conscious decision on the order of the arguments. Normally assert* methods first argument is what's expected, but here it's the second.  The decision on the argument ordering was tied up in what to name the method.  I read it as assert_civilizes this [to] that.  I probably spent a full minute or two pondering this, probably the most 'agonizing' decision in this exercise.  If I kept on with this particular 'project' that might change, no code is sacred!&lt;/p&gt; 
&lt;h2&gt;Another Test, Another Spec Change?&lt;/h2&gt;
&lt;p&gt;The last test I wrote was this:&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;    
&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;test_should_treat_parts_of_words&lt;/span&gt; 
  &lt;span class="ident"&gt;assert_civilizes&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;You, sir are a retarded moron.&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt;
                   &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;You, sir are a ******ed *****.&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I've left this as a proposed spec change.  It fails because one of the bad words is not bracketed by word boundaries. This would be easy to make work, just get rid of the two '\b' anchors in the regexp, but I'm not sure that it's a good idea, and neither is the 'client'.  Should 'stupidity' be considered a bad word? or oxymoron?&lt;/p&gt;
&lt;p&gt;I've raised it with the 'client' and I'm still waiting to hear back.&lt;/p&gt;
&lt;h2&gt;What Have We Learned?&lt;/h2&gt;
&lt;p&gt;The whole exercise, involving some 20 subversion commits, probably took me 30-45 minutes, far less time than writing this article.&lt;/p&gt;
&lt;p&gt;I hope that those of you who have stuck this out to the end found it interesting and perhaps useful.  I think it illustrates some key points about test-driven design, rapid iterative development, and dynamic languages:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Having and maintaining testcode as you go provides value by helping ensure that you aren't wandering away from the goal.&lt;/li&gt;
	&lt;li&gt;Good test code, particularly when run automatically, serves as a more powerful substitute for the type checking done by compilers of statically typed languages, it causes both interface and logic errors to cause fast failures which can usually be quickly corrected.&lt;/li&gt;
	&lt;li&gt;Just because code exists doesn't mean it's sacred.  I'm just as happy, probably happier when I throw old code away and replace it with better code, as long as I'm making progress.  Once again testing is a big boon to this goal.&lt;/li&gt;
&lt;/ul&gt;</description>
      <pubDate>Thu, 11 Oct 2007 06:47:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:19c3ac75-cafb-45e8-8901-6a34ceb89e23</guid>
      <author>Rick DeNatale</author>
      <link>http://talklikeaduck.denhaven2.com/articles/2007/10/11/refactoring-with-continuous-testing-a-guided-tour</link>
      <category>ruby</category>
      <category>best_practices</category>
      <category>tdd</category>
      <category>bdd</category>
      <category>refactoring</category>
      <category>autotest</category>
      <trackback:ping>http://talklikeaduck.denhaven2.com/articles/trackback/470</trackback:ping>
    </item>
  </channel>
</rss>
