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

<channel>
	<title>Meta Bates &#187; rspec</title>
	<atom:link href="http://www.metabates.com/tag/rspec/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.metabates.com</link>
	<description>The technical ramblings of Mark Bates.</description>
	<lastBuildDate>Wed, 01 Feb 2012 16:25:34 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Because everybody has an opinion&#8230;</title>
		<link>http://www.metabates.com/2011/04/15/because-everybody-has-an-opinion/</link>
		<comments>http://www.metabates.com/2011/04/15/because-everybody-has-an-opinion/#comments</comments>
		<pubDate>Sat, 16 Apr 2011 01:30:20 +0000</pubDate>
		<dc:creator>Mark Bates</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[active record]]></category>
		<category><![CDATA[coffee script]]></category>
		<category><![CDATA[erb]]></category>
		<category><![CDATA[haml]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.metabates.com/?p=430</guid>
		<description><![CDATA[In case you&#8217;ve been living in a cave this week you&#8217;ve probably heard that Ruby on Rails is going to be including both the CoffeeScript and SASS libraries, it will also make jQuery the default JavaScript framework, replacing the Prototype framework. I would like to start by addressing my experiences with CoffeeScript. My opinion of [...]]]></description>
			<content:encoded><![CDATA[<p>In case you&#8217;ve been living in a cave this week you&#8217;ve probably heard that <a href="http://www.rubyinside.com/rails-3-1-adopts-coffeescript-jquery-sass-and-controversy-4669.html">Ruby on Rails</a> is going to be including both the <a href="http://coffeescript.org/">CoffeeScript</a> and <a href="http://sass-lang.com/">SASS</a> libraries, it will also make <a href="http://jquery.com/">jQuery</a> the default JavaScript framework, replacing the <a href="http://www.prototypejs.org/">Prototype</a> framework.</p>
<p>I would like to start by addressing my experiences with CoffeeScript. My opinion of it is of ambivalence. I&#8217;ve used it on a project, I&#8217;ve played with and in the end I&#8217;ve come out with the opinion of &#8220;it&#8217;s ok&#8221;. It didn&#8217;t blow me away, but at the same time I can see why so many people like. It offers some really cool features that I really wish JavaScript had and you can cut down on the amount of code you have to write. On the other hand the apps I tend to write don&#8217;t tend to be that JavaScript heavy that I really needed to reach out for something like CoffeeScript.</p>
<p><img class="alignleft" src="http://blogs.worldbank.org/files/publicsphere/public%20opinion_JGRNLY.jpeg" alt="" width="326" height="246" />So, how do I feel about CoffeeScript being included with Rails? Well, I&#8217;ll get to that. Let&#8217;s go over some of the most common arguments I&#8217;ve heard from people this week about why they&#8217;re anti-CoffeeScript in Rails.</p>
<blockquote><p>&#8220;It&#8217;s an abstraction layer of JavaScript! JavaScript isn&#8217;t that bad, why can&#8217;t you just write JavaScript?&#8221;</p>
<p>&#8220;It&#8217;s going to be a hinderance to newbies. It&#8217;ll be too much of a learning curve!&#8221;</p></blockquote>
<p>Let&#8217;s start with that second point first, shall we? I agree, it does represent a new element that needs to be learned when coming to Rails. But here&#8217;s the pretty nifty thing about how it&#8217;s all implemented in Rails. In order to actually use CoffeeScript in Rails you have to create your files named foo.js.coffee if, however, you just name your file foo.js then, guess what? You will have to write plain old JavaScript! Seems like newbies, and those who don&#8217;t like CoffeeScript, can just keep writing plain old JavaScript without anything stopping them at all.</p>
<p>Now, let&#8217;s talk about the abstraction layer argument. Yes, CoffeeScript is an abstraction on top of JavaScript, but let&#8217;s take a look at a few other parts of the Rails stack and see how they hold up against this argument.</p>
<p>Here&#8217;s a fairly common Rails stack:</p>
<ul>
<li>ActiveRecord</li>
<li>Haml</li>
<li>jQuery</li>
<li>RSpec</li>
</ul>
<p>What do all those things have in common? Well, they&#8217;re all abstraction layers that sit on top of something else, don&#8217;t they? Let&#8217;s look at that list again?</p>
<ul>
<li>ActiveRecord &#8211; SQL (Structured Query Language)</li>
<li>Haml &#8211; HTML</li>
<li>jQuery &#8211; JavaScript, you could just as easily hand roll those AJAX calls in pure JavaScript.</li>
<li>RSpec &#8211; Test/Unit</li>
</ul>
<p>What I&#8217;ve found funny about the particular argument is that I&#8217;ve heard it MOST from those who use things like HAML, which is a DEFINITELY an abstraction layer that sits on top of HTML. See where I&#8217;m going with this one? Good, I don&#8217;t want to belabor the point. <img src='http://www.metabates.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>So, finally, where do I stand on this whole thing? Well, I view like it Test/Unit and Prototype. Those are both the current standard (although jQuery will replace Prototype in 3.1) and I don&#8217;t like or use either of them. Instead I configure Rails to use jQuery and RSpec. I don&#8217;t like Haml, but those that do simply replace ERB with Haml and they move on with their day. So my take is this, it&#8217;s there, it&#8217;s included. Use it if you like, or don&#8217;t. Is it really that big a deal? No, it really isn&#8217;t. If Rails dropped ERB and went with Haml as the default, would I bitch and moan, probably a bit, but then I&#8217;d just install the Rails-ERB gem and move on with my day, just like I do with jQuery and RSpec today.</p>
<p>So sit back, relax, use the libraries that you want to use, Rails let&#8217;s you do that. Oh, while you&#8217;re relaxing why not try out CoffeeScript, who knows, you might just enjoy it. Or not.</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.metabates.com/2011/04/15/because-everybody-has-an-opinion/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Testing Tools Aren&#8217;t All the Same, Choose Wisely</title>
		<link>http://www.metabates.com/2011/03/04/407-testing-tools-arent-all-the-same-choose-wisely/</link>
		<comments>http://www.metabates.com/2011/03/04/407-testing-tools-arent-all-the-same-choose-wisely/#comments</comments>
		<pubDate>Fri, 04 Mar 2011 15:57:04 +0000</pubDate>
		<dc:creator>Mark Bates</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[cucumber]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[steak]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[tests]]></category>

		<guid isPermaLink="false">http://www.metabates.com/?p=407</guid>
		<description><![CDATA[&#8220;Testing is painful.&#8221; &#8220;Testing is hard.&#8221; &#8220;Testing is complicated.&#8221; &#8220;Testing is not fun.&#8221; I hear those sorts of things all the time when I talk to people about testing. I agree that sometimes testing can be all of those things, but if you choose the right tools, the tools that best suite you, testing doesn&#8217;t [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p><img class="alignright" title="mario" src="http://www.divanikkiz.com/site/images/stories/mlss_mario-hammer.jpg" alt="" width="255" height="282" />&#8220;Testing is painful.&#8221;</p></blockquote>
<blockquote><p>&#8220;Testing is hard.&#8221;</p></blockquote>
<blockquote><p>&#8220;Testing is complicated.&#8221;</p></blockquote>
<blockquote><p>&#8220;Testing is not fun.&#8221;</p></blockquote>
<p>I hear those sorts of things all the time when I talk to people about testing. I agree that sometimes testing can be all of those things, but if you choose the right tools, the tools that best suite you, testing doesn&#8217;t have to be. Let me give you an example of what I&#8217;m talking about, how choosing the right tools can make a huge impact on how you feel about testing.</p>
<p>When working for a client recently I came across the need for end to end integration testing. I needed to test, amongst other things, the flow of a user registering through the application in a few different ways. Because registration behaves differently based on where you come from and where you want to go, I needed a good way to test that entire flow, so simple unit and functional tests just were not going to cut it.</p>
<p>In the Ruby community there is a big push to use a testing framework called, <a href="http://cukes.info/" target="_blank">Cucumber</a>. Cucumber is a behavior driven development (BDD) tool that let&#8217;s you write user stories in plain English. Those stories then get translated into Ruby code that tests those stories against your application. Because of it&#8217;s popularity, and some of it&#8217;s quite amazing features, this was my first stop on the path to integration testing bliss.</p>
<p>Let me give you an example of a Cucumber script:</p>
<div id="gist-854764" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">Feature:</span><span class="nf"> Registration</span></div><div class='line' id='LC2'><span class="nf">  In order to use My Great Application</span></div><div class='line' id='LC3'><span class="nf">  As a user</span></div><div class='line' id='LC4'><span class="nf">  I want to be able to register</span></div><div class='line' id='LC5'><span class="nf">  </span></div><div class='line' id='LC6'><span class="nf">  </span><span class="k">Scenario:</span><span class="nf"> &#39;Standard Registration&#39;</span></div><div class='line' id='LC7'><span class="k">    Given </span><span class="nf">I am not currently logged in</span></div><div class='line' id='LC8'><span class="nf">    </span><span class="k">When </span><span class="nf">I am on the signup page</span></div><div class='line' id='LC9'><span class="nf">    </span><span class="k">Then </span><span class="nf">I should see &quot;</span><span class="s">Sign Up</span><span class="nf">&quot;</span></div><div class='line' id='LC10'><span class="nf">    </span><span class="k">And </span><span class="nf">I fill in &quot;</span><span class="s">Name (required)</span><span class="nf">&quot; with &quot;</span><span class="s">Mickey Dolenz</span><span class="nf">&quot;</span></div><div class='line' id='LC11'><span class="nf">    </span><span class="k">And </span><span class="nf">I fill in &quot;</span><span class="s">Email (required)</span><span class="nf">&quot; with &quot;</span><span class="s">mickey@monkees.com</span><span class="nf">&quot;</span></div><div class='line' id='LC12'><span class="nf">    </span><span class="k">And </span><span class="nf">I fill in &quot;</span><span class="s">Password (required)</span><span class="nf">&quot; with &quot;</span><span class="s">password</span><span class="nf">&quot;</span></div><div class='line' id='LC13'><span class="nf">    </span><span class="k">And </span><span class="nf">I fill in &quot;</span><span class="s">Password confirmation</span><span class="nf">&quot; with &quot;</span><span class="s">password</span><span class="nf">&quot;</span></div><div class='line' id='LC14'><span class="nf">    </span><span class="k">And </span><span class="nf">I press &quot;</span><span class="s">Register</span><span class="nf">&quot;</span></div><div class='line' id='LC15'><span class="nf">    </span><span class="k">Then </span><span class="nf">I should see &quot;</span><span class="s">Sign Up - Confirm Your Account</span><span class="nf">&quot;</span></div><div class='line' id='LC16'><span class="nf">    </span><span class="k">Then </span><span class="nf">I should be on the registration thank you page</span></div><div class='line' id='LC17'><span class="nf">    </span><span class="k">Then </span><span class="nf">&quot;</span><span class="s">mickey@monkees.com</span><span class="nf">&quot; should receive an email</span></div><div class='line' id='LC18'><span class="nf">    </span><span class="k">When </span><span class="nf">I open the email</span></div><div class='line' id='LC19'><span class="nf">    </span><span class="k">Then </span><span class="nf">I should see &quot;</span><span class="s">Confirm my account</span><span class="nf">&quot; in the email body</span></div><div class='line' id='LC20'><span class="nf">    </span><span class="k">When </span><span class="nf">I follow &quot;</span><span class="s">Confirm my account</span><span class="nf">&quot; in the email</span></div><div class='line' id='LC21'><span class="nf">    </span><span class="k">Then </span><span class="nf">I should be on the welcome page</span></div><div class='line' id='LC22'><span class="nf">    </span><span class="k">And </span><span class="nf">I should see &quot;</span><span class="s">Welcome to the Great Application</span><span class="nf">&quot;</span></div><div class='line' id='LC23'><span class="nf">    </span></div><div class='line' id='LC24'><span class="nf">  </span><span class="k">Scenario:</span><span class="nf"> &#39;Accepting an invitation&#39;</span></div><div class='line' id='LC25'><span class="k">    Given </span><span class="nf">I am not currently logged in</span></div><div class='line' id='LC26'><span class="nf">    </span><span class="k">And </span><span class="nf">the &quot;</span><span class="s">Boys and Girls Club</span><span class="nf">&quot; invites &quot;</span><span class="s">mickey@monkees.com</span><span class="nf">&quot; to join</span></div><div class='line' id='LC27'><span class="nf">    </span><span class="k">Then </span><span class="nf">&quot;</span><span class="s">mickey@monkees.com</span><span class="nf">&quot; should receive an email</span></div><div class='line' id='LC28'><span class="nf">    </span><span class="k">When </span><span class="nf">I open the email</span></div><div class='line' id='LC29'><span class="nf">    </span><span class="k">Then </span><span class="nf">I should see &quot;</span><span class="s">Accept Invitation</span><span class="nf">&quot; in the email body</span></div><div class='line' id='LC30'><span class="nf">    </span><span class="k">When </span><span class="nf">I follow &quot;</span><span class="s">Accept Invitation</span><span class="nf">&quot; in the email</span></div><div class='line' id='LC31'><span class="nf">    </span><span class="k">Then </span><span class="nf">I should be on the signup page</span></div><div class='line' id='LC32'><span class="nf">    </span><span class="k">Then </span><span class="nf">I should see &quot;</span><span class="s">Sign Up</span><span class="nf">&quot;</span></div><div class='line' id='LC33'><span class="nf">    </span><span class="k">And </span><span class="nf">I fill in &quot;</span><span class="s">Name (required)</span><span class="nf">&quot; with &quot;</span><span class="s">Mickey Dolenz</span><span class="nf">&quot;</span></div><div class='line' id='LC34'><span class="nf">    </span><span class="k">And </span><span class="nf">the &quot;</span><span class="s">Email (required)</span><span class="nf">&quot; field should contain &quot;</span><span class="s">mickey@monkees.com</span><span class="nf">&quot;</span></div><div class='line' id='LC35'><span class="nf">    </span><span class="k">And </span><span class="nf">I fill in &quot;</span><span class="s">Password (required)</span><span class="nf">&quot; with &quot;</span><span class="s">password</span><span class="nf">&quot;</span></div><div class='line' id='LC36'><span class="nf">    </span><span class="k">And </span><span class="nf">I fill in &quot;</span><span class="s">Password confirmation</span><span class="nf">&quot; with &quot;</span><span class="s">password</span><span class="nf">&quot;</span></div><div class='line' id='LC37'><span class="nf">    </span><span class="k">And </span><span class="nf">I press &quot;</span><span class="s">Register</span><span class="nf">&quot;</span></div><div class='line' id='LC38'><span class="nf">    </span><span class="k">Then </span><span class="nf">the account &quot;</span><span class="s">mickey@monkees.com</span><span class="nf">&quot; should be &quot;</span><span class="s">activated</span><span class="nf">&quot;</span></div><div class='line' id='LC39'><span class="nf">    </span><span class="k">Then </span><span class="nf">I should be on the accept/decline invitation page</span></div><div class='line' id='LC40'><span class="nf">    </span><span class="k">And </span><span class="nf">I should see &quot;</span><span class="s">Join the Boys and Girls Club</span><span class="nf">&quot;</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/854764/81be0e41bf076636677685e985192e211aa693e0/registration.feature" style="float:right;">view raw</a>
            <a href="https://gist.github.com/854764#file_registration.feature" style="float:right;margin-right:10px;color:#666">registration.feature</a>
            <a href="https://gist.github.com/854764">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>That script tests the user registration flow through an application in a couple of different ways, first through &#8216;standard&#8217; registration, and then through being invited to join. Now, the beauty of Cucumber is that these scripts are &#8216;human&#8217; readable. Your product manager, or other stake holders, should be able to write these scripts themselves, and you, the developer, should be able to just plug them in and code until those scripts pass.</p>
<p>Unfortunately, while that sounds like a little slice of Heaven, the reality is far from it in practice. First, getting stake holders to actually write these &#8216;stories&#8217;, as their typically called, is a tough chore to begin with. If they do write them, they&#8217;re typically not going to be &#8216;plug and play&#8217;. Why? Well, when Cucumber reads these scripts it goes line by line and tries to find some code that matches the regular expression of that line and then execute it. If it doesn&#8217;t find matching code, then it fails. That means that your stake holders need to write these scripts in a very particular way or developers need to sit down and massage those stories to fit the correct regular expression.</p>
<p>Now, let me just take this opportunity to say that this is not a post about how much I hate Cucumber, in fact I think Cucumber is a pretty amazing piece of software, and does in fact have a lot of great uses. Instead, what I&#8217;m talking about it is how Cucumber turned out not to be the right tool for the job for me on a recent project.</p>
<p>So why wasn&#8217;t Cucumber the right tool for the job? Great question, glad you asked. Cucumber turned out not to be the right tool for a few reasons. The biggest of which was that I was the one who was writing the user stories. The stake holders had no desire to write these stories, which meant I had to write them. The I had to write the &#8216;steps&#8217; that back each line of the script. In all fairness, Cucumber does give you some great steps right out of the box. After some fiddling I finally got the Cucumber scripts up and running and testing my work flow. But I definitely ran into some issues.</p>
<p>Because Cucumber isn&#8217;t pure Ruby I had a hard time doing something as simple as just printing out the request&#8217;s body and headers without having to write a step that did just that, then add that step to my story, etc&#8230; It&#8217;s overall fiddlyness and non-intuitive way of doing things caused me a lot of grief and time. And, most importantly, I wasn&#8217;t really getting the big benefit of Cucumber, stake holder&#8217;s writing the stories. So I was doing all this work and not getting the benefits of Cucumber.</p>
<p>So what did I do? I turned to a library called <a href="https://github.com/cavalle/steak" target="_blank">Steak</a>. Steak allows you to write integration tests using pure Ruby and integrates directly in with <a href="http://relishapp.com/rspec" target="_blank">RSpec</a>, my preferred testing framework. With Steak I was able to write my integration tests in just a few minutes.</p>
<div id="gist-854844" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="nb">require</span> <span class="no">File</span><span class="o">.</span><span class="n">expand_path</span><span class="p">(</span><span class="no">File</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="bp">__FILE__</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39;/acceptance_helper&#39;</span><span class="p">)</span></div><div class='line' id='LC2'><br/></div><div class='line' id='LC3'><span class="n">feature</span> <span class="s2">&quot;Registration Steak&quot;</span><span class="p">,</span> <span class="sx">%q{</span></div><div class='line' id='LC4'><span class="sx">  In order to use My Great Application</span></div><div class='line' id='LC5'><span class="sx">  As a user</span></div><div class='line' id='LC6'><span class="sx">  I want to be able to register</span></div><div class='line' id='LC7'><span class="sx">}</span> <span class="k">do</span></div><div class='line' id='LC8'><br/></div><div class='line' id='LC9'>&nbsp;&nbsp;<span class="n">scenario</span> <span class="s2">&quot;register throught the standard registration process&quot;</span> <span class="k">do</span></div><div class='line' id='LC10'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">visit</span> <span class="n">signup_path</span></div><div class='line' id='LC11'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">expect</span> <span class="p">{</span></div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">fill_in_registration</span><span class="p">(</span><span class="ss">:name</span> <span class="o">=&gt;</span> <span class="s1">&#39;Mickey Dolenz&#39;</span><span class="p">,</span> <span class="ss">:email</span> <span class="o">=&gt;</span> <span class="s1">&#39;mickey@monkees.com&#39;</span><span class="p">)</span></div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span><span class="o">.</span><span class="n">to</span> <span class="n">change</span><span class="p">(</span><span class="n">delivered_emails</span><span class="p">,</span> <span class="ss">:size</span><span class="p">)</span><span class="o">.</span><span class="n">by</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span></div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC16'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">user</span> <span class="o">=</span> <span class="no">User</span><span class="o">.</span><span class="n">find_by_email</span><span class="p">(</span><span class="s1">&#39;mickey@monkees.com&#39;</span><span class="p">)</span></div><div class='line' id='LC17'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">user</span><span class="o">.</span><span class="n">should</span> <span class="n">be_unverified</span></div><div class='line' id='LC18'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC19'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">page</span><span class="o">.</span><span class="n">should</span> <span class="n">have_content</span><span class="p">(</span><span class="s1">&#39;You have signed up successfully. However, we could not sign you in because your account is unconfirmed.&#39;</span><span class="p">)</span></div><div class='line' id='LC20'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">current_path</span><span class="o">.</span><span class="n">should</span> <span class="o">==</span> <span class="n">root_path</span></div><div class='line' id='LC21'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC22'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">visit</span> <span class="n">signin_path</span></div><div class='line' id='LC23'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">fill_in</span> <span class="s1">&#39;user_email&#39;</span><span class="p">,</span> <span class="ss">:with</span> <span class="o">=&gt;</span> <span class="s1">&#39;mickey@monkees.com&#39;</span></div><div class='line' id='LC24'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">fill_in</span> <span class="s1">&#39;user_password&#39;</span><span class="p">,</span> <span class="ss">:with</span> <span class="o">=&gt;</span> <span class="s1">&#39;password&#39;</span></div><div class='line' id='LC25'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">click_button</span> <span class="s1">&#39;Sign In&#39;</span></div><div class='line' id='LC26'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC27'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">page</span><span class="o">.</span><span class="n">should</span> <span class="n">have_content</span><span class="p">(</span><span class="s1">&#39;You have to confirm your account before continuing.&#39;</span><span class="p">)</span></div><div class='line' id='LC28'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">current_path</span><span class="o">.</span><span class="n">should</span> <span class="o">==</span> <span class="n">new_user_session_path</span></div><div class='line' id='LC29'><br/></div><div class='line' id='LC30'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">click_email_link_matching</span><span class="p">(</span><span class="sr">/users\/confirmation/</span><span class="p">,</span> <span class="n">delivered_emails</span><span class="o">.</span><span class="n">first</span><span class="p">)</span></div><div class='line' id='LC31'><br/></div><div class='line' id='LC32'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">current_path</span><span class="o">.</span><span class="n">should</span> <span class="o">==</span> <span class="n">welcome_users_path</span></div><div class='line' id='LC33'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">page</span><span class="o">.</span><span class="n">should</span> <span class="n">have_content</span><span class="p">(</span><span class="s1">&#39;Welcome to the Great Application&#39;</span><span class="p">)</span></div><div class='line' id='LC34'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">user</span><span class="o">.</span><span class="n">reload</span></div><div class='line' id='LC35'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">user</span><span class="o">.</span><span class="n">should</span> <span class="n">be_activated</span></div><div class='line' id='LC36'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC37'>&nbsp;&nbsp;</div><div class='line' id='LC38'>&nbsp;&nbsp;<span class="n">scenario</span> <span class="s2">&quot;register from an invitation&quot;</span> <span class="k">do</span></div><div class='line' id='LC39'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">mark</span> <span class="o">=</span> <span class="n">users</span><span class="p">(</span><span class="ss">:mark</span><span class="p">)</span></div><div class='line' id='LC40'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">organization</span> <span class="o">=</span> <span class="n">mark</span><span class="o">.</span><span class="n">organizations</span><span class="o">.</span><span class="n">first</span></div><div class='line' id='LC41'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">signin</span><span class="p">(</span><span class="n">mark</span><span class="p">)</span></div><div class='line' id='LC42'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC43'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">visit</span> <span class="n">new_organization_invitation_path</span><span class="p">(</span><span class="n">organization</span><span class="p">)</span></div><div class='line' id='LC44'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">expect</span> <span class="p">{</span></div><div class='line' id='LC45'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">expect</span> <span class="p">{</span></div><div class='line' id='LC46'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">fill_in</span> <span class="s1">&#39;organization_invitation_worker_emails&#39;</span><span class="p">,</span> <span class="ss">:with</span> <span class="o">=&gt;</span> <span class="s1">&#39;mickey@monkees.com&#39;</span></div><div class='line' id='LC47'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">click_button</span> <span class="s1">&#39;Send Invites&#39;</span></div><div class='line' id='LC48'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="no">DJ</span><span class="o">.</span><span class="n">first</span><span class="o">.</span><span class="n">invoke_job</span></div><div class='line' id='LC49'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span><span class="o">.</span><span class="n">to</span> <span class="n">change</span><span class="p">(</span><span class="n">delivered_emails</span><span class="p">,</span> <span class="ss">:size</span><span class="p">)</span><span class="o">.</span><span class="n">by</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span></div><div class='line' id='LC50'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span><span class="o">.</span><span class="n">to</span> <span class="n">change</span><span class="p">(</span><span class="n">organization</span><span class="o">.</span><span class="n">invitations</span><span class="p">,</span> <span class="ss">:count</span><span class="p">)</span><span class="o">.</span><span class="n">by</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span></div><div class='line' id='LC51'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC52'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">invitation</span> <span class="o">=</span> <span class="n">organization</span><span class="o">.</span><span class="n">invitations</span><span class="o">.</span><span class="n">first</span></div><div class='line' id='LC53'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC54'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">signout</span></div><div class='line' id='LC55'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC56'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">click_first_link_in_email</span><span class="p">(</span><span class="n">delivered_emails</span><span class="o">.</span><span class="n">first</span><span class="p">)</span></div><div class='line' id='LC57'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC58'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">current_path</span><span class="o">.</span><span class="n">should</span> <span class="o">==</span> <span class="n">signup_path</span></div><div class='line' id='LC59'><br/></div><div class='line' id='LC60'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">fill_in_registration</span><span class="p">(</span><span class="ss">:name</span> <span class="o">=&gt;</span> <span class="s1">&#39;Mickey Dolenz&#39;</span><span class="p">)</span></div><div class='line' id='LC61'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC62'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">current_path</span><span class="o">.</span><span class="n">should</span> <span class="o">==</span> <span class="n">organization_invitation_path</span><span class="p">(</span><span class="n">organization</span><span class="p">,</span> <span class="n">invitation</span><span class="p">)</span></div><div class='line' id='LC63'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC64'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">user</span> <span class="o">=</span> <span class="no">User</span><span class="o">.</span><span class="n">find_by_email</span><span class="p">(</span><span class="s1">&#39;mickey@monkees.com&#39;</span><span class="p">)</span></div><div class='line' id='LC65'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">user</span><span class="o">.</span><span class="n">should</span> <span class="n">be_activated</span></div><div class='line' id='LC66'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC67'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">expect</span> <span class="p">{</span></div><div class='line' id='LC68'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">click_on</span> <span class="s1">&#39;Get Started Now!&#39;</span></div><div class='line' id='LC69'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span><span class="o">.</span><span class="n">to</span> <span class="n">change</span><span class="p">(</span><span class="n">user</span><span class="o">.</span><span class="n">organizations</span><span class="p">,</span> <span class="ss">:count</span><span class="p">)</span><span class="o">.</span><span class="n">by</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span></div><div class='line' id='LC70'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC71'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">current_path</span><span class="o">.</span><span class="n">should</span> <span class="o">==</span> <span class="n">organization_campaign_path</span><span class="p">(</span><span class="n">organization</span><span class="p">,</span> <span class="n">organization</span><span class="o">.</span><span class="n">campaigns</span><span class="o">.</span><span class="n">first</span><span class="p">)</span></div><div class='line' id='LC72'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC73'>&nbsp;&nbsp;</div><div class='line' id='LC74'><span class="k">end</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/854844/45d1d080b1d1a19954d6894e08e2261b1b368166/registration_spec.rb" style="float:right;">view raw</a>
            <a href="https://gist.github.com/854844#file_registration_spec.rb" style="float:right;margin-right:10px;color:#666">registration_spec.rb</a>
            <a href="https://gist.github.com/854844">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>While my Steak scripts a bit more wordy and are definitely not &#8216;human&#8217; readable and editable by stakeholders, they did achieve my goal of allowing me to write integration tests quickly.</p>
<p>So here you see I picked a very powerful tool, that has a lot of great benefits, Cucumber, but I picked it for the wrong reasons. I picked it because it was popular, and not because it would help me achieve my goals. If my goals where to have stakeholders write the stories and hand them off to development, than it would&#8217;ve been a better choice. But in the end my goal was to write integration tests and write them quickly, which is why Steak ended up being the right tool for that job.</p>
<p>This has all been a really long winded way of saying doing some research before choosing your testing frameworks, or any framework for that matter. Play with it, research it, make sure it meets your goals, not somebody else&#8217;s. If you choose the right tools then testing doesn&#8217;t need to be scary, complicated, frustrating, etc&#8230; Testing is a <a href="http://www.metabates.com/2010/07/01/testing-is-not-an-option/">requirement</a> and a must have, so why not make it fun?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.metabates.com/2011/03/04/407-testing-tools-arent-all-the-same-choose-wisely/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>How to Become a Test-driven Developer</title>
		<link>http://www.metabates.com/2010/10/12/how-to-become-a-test-driven-developer/</link>
		<comments>http://www.metabates.com/2010/10/12/how-to-become-a-test-driven-developer/#comments</comments>
		<pubDate>Tue, 12 Oct 2010 16:31:01 +0000</pubDate>
		<dc:creator>Mark Bates</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[bdd]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[tests]]></category>

		<guid isPermaLink="false">http://www.metabates.com/?p=367</guid>
		<description><![CDATA[In a previous post, Testing Is Not An Option, I talked a lot about why you should write tests, and the arguments you can put forth to your client, manager, or whoever it may be as to why you should write tests. What I didn&#8217;t talk about was how to start writing tests. So let&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>In a previous post, <a href="http://www.metabates.com/2010/07/01/testing-is-not-an-option/" target="_blank">Testing Is Not An Option</a>, I talked a lot about why you should write tests, and the arguments you can put forth to your client, manager, or whoever it may be as to why you should write tests. What I didn&#8217;t talk about was how to start writing tests. So let&#8217;s talk about that for a bit, shall we?</p>
<p>When I&#8217;m talking with a potential client, well at least a client that has an existing code base, I always ask what their code coverage stats are. Now, I know at code coverage stats aren&#8217;t the be all end all of measuring how good your tests are, but they&#8217;re a basic enough metric to use as a guide. If they say they&#8217;re high, then I usually dig in more about how they&#8217;re testing; what frameworks, BDD, TDD, that sort of thing. Usually though I get a few minutes where they apologize and sheepishly give me their reasons for having little or no tests.</p>
<p>Here are few of those reasons:</p>
<ul>
<li>We don&#8217;t/didn&#8217;t have the time.</li>
<li>We don&#8217;t know how.</li>
<li>It was/is too complicated.</li>
<li>It was/is too overwhelming.</li>
</ul>
<p>Let&#8217;s talk about each of this points for a minute.</p>
<h3>&#8220;We don&#8217;t/didn&#8217;t have the time.&#8221;</h3>
<h3><span style="font-weight: normal; font-size: 13px;">I never accept time as an argument against testing. Testing ends up repaying it&#8217;s time investment, and will ultimately give you more time than if you didn&#8217;t write code. It&#8217;s a win-win. Again see my previous post in how to get the time signed off on as part of t he project timeline.</span></h3>
<h3>&#8220;We don&#8217;t know how.&#8221;</h3>
<p>Learn. There&#8217;s no better time than the present and no better way to learn than being thrown into the deep end. The web is crawling with documentation, screen casts, how to articles and tutorials, and there are plenty of books to get you going. In short the k knowledge is literally at your finger tips, and to be honest it&#8217;s easier than you think.</p>
<h3>&#8220;It was/is too complicated.&#8221;</h3>
<p>That usually means you&#8217;re doing it wrong. Take a step back and assess what it is you&#8217;re trying to do. You&#8217;re tests should be simple and concise. Don&#8217;t write tests that are hundreds of lines long. They&#8217;re tests, not entrance exams to MIT.</p>
<h3>&#8220;It was/is too overwhelming.&#8221;</h3>
<p>Certainly if you didn&#8217;t write tests as you went along it can get quite overwhelming thinking about all the tests you now need to write for your monolithic app. I&#8217;ll talk about how you can solve that problem in a minute.</p>
<h2>Making It Happen</h2>
<p>Ok, so now that we&#8217;ve identified a few of the excuses let&#8217;s talk about how you can starting writing tests today for your application. So, take a deep breath and let&#8217;s begin.</p>
<p>If you&#8217;re staring at an existing application, don&#8217;t try to tackle it all at once, you&#8217;ll just get overwhelmed, scared, and confused. Instead take it one file/class at a time. First start with your models, as this is where the majority of your application business logic should be. Alphabetically each day pick the next class (or a couple of them) in the list and start to fill our your test files.</p>
<p>What do I mean by fill out your tests files, I mean creating pending tests for each of the methods of your model. Here&#8217;s an example of a basic Ruby* class and what the pending RSpec spec file would look like:</p>
<pre><code># Class: class Entity def tax_id if self.person? # code here else # code here end end def person? # code here end end # Spec: describe Entity do describe "tax_id" do it "should return a Social Security number if the entity is a Person" do pending end it "should return a Tax ID number if the entity is a Corporation" do pending end end describe "person?" do it "should return true if the entity is a person" do pending end it "should return false if the entity is not a person" do pending end end end</code></pre>
<p>Notice how the method that has the if/else statement in it has two pending tests for it. We need to test each variation of the method.</p>
<p>Now when you run your tests you&#8217;ll see that you have a bunch of pending tests. Great! Now you just need to fill them in, but at least you know what should be filled in.</p>
<p>I also recommend that you do this every time you create a new method. As soon as you give your method a name go to your corresponding test and create a pending test for that method. This way you know that you have to test that method later. (In a perfect world I would love to see you write your test before returning to your class to fill in the method itself, but baby steps for now.)</p>
<p>Once you have all your pending tests setup each day try to fill in the details of each pending test for a whole class. If that&#8217;s too much, then try to set aside an hour a day and fill in as many pending tests as you can. Alternatively you can also fill in the tests during the course of the day as you use one of the methods without tests.</p>
<p>Another great way to start filling in your test suite is each time you get a new bug, write a test to reproduce it. This is a great habit to get into as you&#8217;ll eventually have a great suite of regression tests in place to help prevent those nasty bugs from returning. Write the test, see that it fails, then fix your bug. When your teat passes then you know you&#8217;ve fixed the bug!</p>
<p>Finally, start small. Start by writing unit tests. These are the types of tests I just described. They test a very particular part of your code base to ensure that it does what it should do. These tests are typically easy to write and act as a great corner stone to your test suite as a whole. Don&#8217;t try to jump right in with full integration tests. The frameworks typically have a steep learning curve, and are more complicated to get up and running. This will lead to frustration and the old feeling of being overwhelmed. You can add these tests in later as you gain experience.</p>
<p>Well, there you have it, a few simple tricks to help you get started testing today. I know this post was a bit on the lengthy side, but I&#8217;m glad you stuck with me. Your life will be better for it. When you have a large and expansive test suite life is just better. Food tastes better. The sky is bluer. There will be a skip in your step. And you can use your incredibly high code coverage stats as a pick up line in a bar. On second thought, scratch that last thought. I wrote a test to see if that would work and it failed. It failed miserably.</p>
<h6>* Please not that while I use Ruby as the example language here, the concept applies to whatever language you use.</h6>
]]></content:encoded>
			<wfw:commentRss>http://www.metabates.com/2010/10/12/how-to-become-a-test-driven-developer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CoverMe – Code Coverage for Ruby 1.9 Reaches RC1</title>
		<link>http://www.metabates.com/2010/09/30/coverme-%e2%80%93-code-coverage-for-ruby-1-9-reaches-rc1/</link>
		<comments>http://www.metabates.com/2010/09/30/coverme-%e2%80%93-code-coverage-for-ruby-1-9-reaches-rc1/#comments</comments>
		<pubDate>Thu, 30 Sep 2010 16:09:25 +0000</pubDate>
		<dc:creator>Mark Bates</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Releases]]></category>
		<category><![CDATA[Updates]]></category>
		<category><![CDATA[cover_me]]></category>
		<category><![CDATA[gem]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[rcov]]></category>
		<category><![CDATA[release]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[tests]]></category>

		<guid isPermaLink="false">http://www.metabates.com/?p=363</guid>
		<description><![CDATA[In August I announced CoverMe a code coverage tool for Ruby 1.9. Well, today I announce that it has hit it&#8217;s first release candidate! I&#8217;ve very excited by the fact it&#8217;s getting close to an &#8216;official&#8217; release. The response to CoverMe has been great and through feedback from the community I&#8217;ve made a lot of [...]]]></description>
			<content:encoded><![CDATA[<p>In <a href="http://www.metabates.com/2010/08/13/coverme-code-coverage-for-ruby-1-9/">August</a> I announced <a href="http://github.com/markbates/cover_me" target="_blank">CoverMe</a> a code coverage tool for Ruby 1.9. Well, today I announce that it has hit it&#8217;s first release candidate! I&#8217;ve very excited by the fact it&#8217;s getting close to an &#8216;official&#8217; release.</p>
<p>The response to CoverMe has been great and through feedback from the community I&#8217;ve made a lot of improvements and fixed a lot of issues.</p>
<p>While quite a few things have changed under the hood, not much has changed in how you use CoverMe.</p>
<h2>Installation</h2>
<p>The following are instructions for how you would configure CoverMe for a Rails 3 project, adjust to your local environment accordingly.</p>
<p>In  your Gemfile add the following:</p>
<pre>gem 'cover_me', '&gt;= 1.0.0.rc1', :group =&gt; :test</pre>
<p>Then run:</p>
<pre>$ bundle install</pre>
<p>After CoverMe is installed place the following line at the <strong><em>VERY TOP</em></strong> of your &#8216;test_helper.rb&#8217; or &#8216;spec_helper.rb&#8217; file (for Cucumber put it at the top of the &#8216;env.rb&#8217; file):</p>
<pre>require 'cover_me'</pre>
<p>I can&#8217;t emphasize enough how important it is that the require statement is at the <strong><em>VERY</em></strong> top of that file!</p>
<p>Finally (and optionally) run:</p>
<pre>$ rails g cover_me:install</pre>
<p>This will simply install a Rake task that will wrap both Test::Unit and RSpec tasks with CoverMe and will launch the results at the end of the test suites. I would recommend it. It&#8217;s kinda the whole point. <img src='http://www.metabates.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h2>That&#8217;s it!</h2>
<p>Enjoy the release candidate, and of course, please let me know if you find any issues with it. Issues can be reported on <a href="http://github.com/markbates/cover_me/issues" target="_blank">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.metabates.com/2010/09/30/coverme-%e2%80%93-code-coverage-for-ruby-1-9-reaches-rc1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CoverMe &#8211; Code Coverage for Ruby 1.9</title>
		<link>http://www.metabates.com/2010/08/13/coverme-code-coverage-for-ruby-1-9/</link>
		<comments>http://www.metabates.com/2010/08/13/coverme-code-coverage-for-ruby-1-9/#comments</comments>
		<pubDate>Fri, 13 Aug 2010 17:49:44 +0000</pubDate>
		<dc:creator>Mark Bates</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Releases]]></category>
		<category><![CDATA[gem]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[rcov]]></category>
		<category><![CDATA[release]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[tests]]></category>

		<guid isPermaLink="false">http://www.metabates.com/?p=343</guid>
		<description><![CDATA[Ruby 1.9(.2) is an amazing language to develop applications in. It&#8217;s faster, more powerful, cleaner, and a huge improvement over Ruby 1.8.x. Because of those reasons every Ruby developer should move to this exciting new version of our language. When making a move of this size it&#8217;s important to have the right tools to help [...]]]></description>
			<content:encoded><![CDATA[<p>Ruby 1.9(.2) is an amazing language to develop applications in. It&#8217;s faster, more powerful, cleaner, and a huge improvement over Ruby 1.8.x. Because of those reasons every Ruby developer should move to this exciting new version of our language.</p>
<div id="_mcePaste">When making a move of this size it&#8217;s important to have the right tools to help us along. Unfortunately, one of the most useful tools as a Ruby developer, <a href="http://github.com/relevance/rcov">RCov</a>, does not work with Ruby 1.9.</div>
<div id="_mcePaste">RCov, for those unfamiliar analyzes your code and tells you which part of your code was not executed. This is INCREDIBLY useful when hooked up to your test suite. While, it&#8217;s not the only metric you should use when determining how good your test coverage it, it certainly is a great first step to point out exactly which parts of your code haven&#8217;t been touched at all!</div>
<p>Enter <a href="http://github.com/markbates/cover_me">CoverMe</a>.</p>
<h2>History</h2>
<p>While working on a Ruby 1.9/Rails 3 project, and loving everything about it (except for the lack of RCov), I came across a <a href="http://engineering.attinteractive.com/2010/08/code-coverage-in-ruby-1-9/">post</a> by Aaron Patterson (of <a href="http://github.com/tenderlove/nokogiri">Nokogiri</a> fame). In this post he quickly outlined a very basic coverage tool using the new built-in Coverage module in Ruby 1.9.</p>
<p>After spending a morning playing with it, I was quickly able to grow the idea into something useful for the project. Later that day the company I was consulting for (<a href="http://www.biddingforgood.com">BiddingForGood.com</a>), and in particular their chief architect, <a href="http://twitter.com/stuartmg">Stuart Garner</a>, told me to take a day or two and clean it up and release it for the world to use, and so <a href="http://github.com/markbates/cover_me">here</a> it is.</p>
<h2>Features</h2>
<p>Here is a brief overview of the features of CoverMe:</p>
<h3>Index Page</h3>
<ul>
<li>Sortable column headers (File, Lines, Lines of Code, Tested %).</li>
<li>Searching/filtering by file name.</li>
<li>Filtering by coverage percent.</li>
<li>Color coded list of files to quickly see which ones are 100% covered, &gt; 90% covered, or less than 90% covered.</li>
<li>Large color coded average coverage percent, for quick reference.</li>
</ul>
<h3>Detail Page</h3>
<ul>
<li>Line by line coverage report</li>
<li>Color coded lines to quickly see which lines where executed and which ones were not.</li>
<li>Side by side viewing with the corresponding test/spec file (if one exists).</li>
</ul>
<p>See the <a href="http://github.com/markbates/cover_me">README</a> file for more information on installation and usage.</p>
<h2>Thanks</h2>
<p>I would just quickly like to give another quick thanks to Aaron Patterson for pointing out the Coverage module in Ruby 1.9 and inspiring this, hopefully, helpful little gem. Also another big thanks to Stuart Garner for pushing me to package this up and release it to the world.</p>
<h2>Screenshots</h2>

<a href='http://www.metabates.com/2010/08/13/coverme-code-coverage-for-ruby-1-9/detail_side_by_side/' title='detail_side_by_side'><img width="150" height="150" src="http://www.metabates.com/wp-content/uploads/2010/08/detail_side_by_side-150x150.png" class="attachment-thumbnail" alt="detail_side_by_side" title="detail_side_by_side" /></a>
<a href='http://www.metabates.com/2010/08/13/coverme-code-coverage-for-ruby-1-9/detail/' title='detail'><img width="150" height="150" src="http://www.metabates.com/wp-content/uploads/2010/08/detail-150x150.png" class="attachment-thumbnail" alt="detail" title="detail" /></a>
<a href='http://www.metabates.com/2010/08/13/coverme-code-coverage-for-ruby-1-9/index_filter/' title='index_filter'><img width="150" height="150" src="http://www.metabates.com/wp-content/uploads/2010/08/index_filter-150x150.png" class="attachment-thumbnail" alt="index_filter" title="index_filter" /></a>
<a href='http://www.metabates.com/2010/08/13/coverme-code-coverage-for-ruby-1-9/index_search/' title='index_search'><img width="150" height="150" src="http://www.metabates.com/wp-content/uploads/2010/08/index_search-150x150.png" class="attachment-thumbnail" alt="index_search" title="index_search" /></a>
<a href='http://www.metabates.com/2010/08/13/coverme-code-coverage-for-ruby-1-9/index/' title='index'><img width="150" height="150" src="http://www.metabates.com/wp-content/uploads/2010/08/index-150x150.png" class="attachment-thumbnail" alt="index" title="index" /></a>

]]></content:encoded>
			<wfw:commentRss>http://www.metabates.com/2010/08/13/coverme-code-coverage-for-ruby-1-9/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Testing is NOT an Option</title>
		<link>http://www.metabates.com/2010/07/01/testing-is-not-an-option/</link>
		<comments>http://www.metabates.com/2010/07/01/testing-is-not-an-option/#comments</comments>
		<pubDate>Thu, 01 Jul 2010 14:04:38 +0000</pubDate>
		<dc:creator>Mark Bates</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[cucumber]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[tests]]></category>

		<guid isPermaLink="false">http://www.metabates.com/?p=337</guid>
		<description><![CDATA[Five years ago I left the world of contracting and reentered the world of the full time employee, and I enjoyed every minute of it (well, almost). Now fast forward five years and I find myself once again at a crossroads. Do I continue on as an FTE or do I become a contractor, and [...]]]></description>
			<content:encoded><![CDATA[<p>Five years ago I left the world of contracting and reentered the world of the full time employee, and I enjoyed every minute of it (well, almost). Now fast forward five years and I find myself once again at a crossroads. Do I continue on as an FTE or do I become a contractor, and play the field, so to speak? Looks like I&#8217;m going to go with the hired gun route for a little while, but that&#8217;s not really the point of this post.</p>
<p>During the past week or so I&#8217;ve spoken with many great companies and people. I&#8217;ve been fortunate enough to have a high degree of interest in what I can bring to the table. During those discussions I talked with a really nice guy at a what seems to be a really cool company, I won&#8217;t name names, because this isn&#8217;t about either the person or the company, but rather something the engineer said during our phone conversation that got me to thinking.</p>
<p><img class="alignleft" title="Failure Testing" src="http://www.commercialventvac.com/finao/failure_testing.jpg" alt="" width="400" height="240" />&#8220;We don&#8217;t have any tests because I couldn&#8217;t convince the company to allocate the time for them.&#8221; That statement really hung with me. After I got off the phone I started thinking really hard about that statement, and all I could think of was how testing is not an option and people shouldn&#8217;t need to be convinced to have time allocated to them.</p>
<p>As developers it is our responsibility to insist on testing. Always include testing in your time estimates. Never give the client (or your company) an option that includes a time estimate without testing. If a feature takes 2 days to code and a day to write tests, then your estimate is 3 days, never 2. You should never say, &#8220;Well, I can get it done in two days if I don&#8217;t write any tests.&#8221; That&#8217;s just an unacceptable thing to say. What you should be saying is, &#8220;That feature will take three days to code&#8221;.</p>
<p>I don&#8217;t feel I should sit here and tell you all the reasons why you should test, you should know them already, and frankly, they&#8217;re all very obvious! But, if you need a few bullet points to &#8216;convince&#8217; your client, here are a few:</p>
<ul>
<li>Less bugs &#8211; The more tests you have the less bugs you will have. It&#8217;s just a fact. You won&#8217;t have 100% bug free code, that&#8217;s a nearly impossible goal, but you highly reduce the likely hood that as soon as you get your code into production your users will find all the breaking points of your code.</li>
<li>Better maintainability, means faster feature turn around &#8211; When you have a large test suite it means adding, updating, or even removing features because a whole lot easier, which means it SAVES time! Why? Simple, you don&#8217;t have to go through and manually test every aspect of your code to make sure you didn&#8217;t break something elsewhere by adding that validation, or by refactoring that bit of code, etc&#8230; That translates into real $ savings.</li>
<li>Test driven development saves time &#8211; this isn&#8217;t quite the same as my last bullet point. Imagine, if you will, you are writing a four step wizard in your application. If you write a few test scripts using something like Cucumber first before you write your code you can simply keep re-running those to make sure your code is working. If you don&#8217;t have those test scripts written then you continually have to keep going to a browser and entering all the information in each of the steps so you can test something in step four. Which one do you think takes longer, having a few test scripts you can run, or manually going through the four page wizard each time you make a change?</li>
<li>It&#8217;s an investment &#8211; thinking of having test scripts like owning a house. When you don&#8217;t have tests and you just keep testing in the browser or the command line what you are doing is a kin to &#8220;renting&#8221;. There is money being spent, but at the end of the day you have nothing to show for it. You&#8217;ve spent hours &#8220;testing&#8221;, but tomorrow when you come in you have to do it all over again. When you spend those hours writing tests you are actually &#8220;buying&#8221; something. You have something to show for that time and money you&#8217;ve spent. Tomorrow, next week, next month, next year, those scripts will still be there, they&#8217;ll still be working for you, giving  you a return on your investment.</li>
</ul>
<p>Well, I hope I have hopefully made a case to you the engineer as to why you should insist on testing. It&#8217;s the right thing to do, for you, for your application and for you client. If if anyone tries to give you grief about it, send them my way, I&#8217;ll sort em out!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.metabates.com/2010/07/01/testing-is-not-an-option/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Configatron 2.2.0 Released, now with Ruby 1.9 and JRuby support!</title>
		<link>http://www.metabates.com/2009/01/01/configatron-220-released-now-with-ruby-19-and-jruby-support/</link>
		<comments>http://www.metabates.com/2009/01/01/configatron-220-released-now-with-ruby-19-and-jruby-support/#comments</comments>
		<pubDate>Thu, 01 Jan 2009 16:31:00 +0000</pubDate>
		<dc:creator>Mark Bates</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[Updates]]></category>
		<category><![CDATA[cachetastic]]></category>
		<category><![CDATA[configatron]]></category>
		<category><![CDATA[genosaurus]]></category>
		<category><![CDATA[jruby]]></category>
		<category><![CDATA[mack]]></category>
		<category><![CDATA[multiruby]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[ruby 1.9]]></category>

		<guid isPermaLink="false">http://www.mackframework.com/?p=210</guid>
		<description><![CDATA[Happy New Year everyone! With the help of the absolutely amazing multiruby library and an edge version of rspec from GitHub, the latest version of Configatron now supports JRuby 1.1.6 and Ruby 1.9.1rc1. There are no other functional changes to the library, so it&#8217;s a full drop in replacement for vesion 2.1.6. I highly encourage [...]]]></description>
			<content:encoded><![CDATA[<p>Happy New Year everyone!</p>
<p>With the help of the absolutely amazing <a href="http://blog.robseaman.com/2008/12/20/switching-between-ruby-1-8-1-9-with-multiruby" target="_blank">multiruby</a> library and an edge version of rspec from GitHub, the latest version of Configatron now supports JRuby 1.1.6 and Ruby 1.9.1rc1. There are no other functional changes to the library, so it&#8217;s a full drop in replacement for vesion 2.1.6.</p>
<p>I highly encourage everyone to checkout multiruby and start upgrading their libraries so we can all move to 1.9 quicker, which means more speed and more power. Once we&#8217;re all in 1.9 land we can really make use of some of the amazing features it provides.</p>
<p>Anyway, I&#8217;ll be working on upgrading all my libraries and applications to work on 1.8 and 1.9, and hopefully JRuby, over the next couple of months. So be on the look out for a new versions of Cachetastic, Genosaurus [update: Genosaurus already works with 1.9 and JRuby. Hoorah!], and, of course, Mack.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.metabates.com/2009/01/01/configatron-220-released-now-with-ruby-19-and-jruby-support/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Release 0.8.2</title>
		<link>http://www.metabates.com/2008/11/30/release-082/</link>
		<comments>http://www.metabates.com/2008/11/30/release-082/#comments</comments>
		<pubDate>Mon, 01 Dec 2008 02:57:12 +0000</pubDate>
		<dc:creator>Mark Bates</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Releases]]></category>
		<category><![CDATA[Updates]]></category>
		<category><![CDATA[active record]]></category>
		<category><![CDATA[addressable]]></category>
		<category><![CDATA[data mapper]]></category>
		<category><![CDATA[deferred? routes]]></category>
		<category><![CDATA[ebb]]></category>
		<category><![CDATA[english]]></category>
		<category><![CDATA[Ezra Zygmuntowicz]]></category>
		<category><![CDATA[facets]]></category>
		<category><![CDATA[gems]]></category>
		<category><![CDATA[haml]]></category>
		<category><![CDATA[mack]]></category>
		<category><![CDATA[merb]]></category>
		<category><![CDATA[release]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[thin]]></category>

		<guid isPermaLink="false">http://www.mackframework.com/?p=206</guid>
		<description><![CDATA[Hey there folks, sorry for the long wait for this release, but it&#8217;s here. It&#8217;s been a long November for yours truly. I&#8217;ve had to find a new job. I&#8217;ve had pneumonia. We, at least in America, have celebrated Thanksgiving. And, of course, who can forget RubyConf 2008? So with that said, what&#8217;s in 0.8.2? [...]]]></description>
			<content:encoded><![CDATA[<p>Hey there folks, sorry for the long wait for this release, but it&#8217;s here. It&#8217;s been a long November for yours truly. I&#8217;ve had to find a new job. I&#8217;ve had pneumonia. We, at least in America, have celebrated Thanksgiving. And, of course, who can forget RubyConf 2008?</p>
<p>So with that said, what&#8217;s in 0.8.2? Honestly, not a whole lot. There are a couple of bug fixes, a button_to_remote (think submit_to_remote in Rails) helper, and deferred routes. More on deferred routes in a moment, as it&#8217;s actually a pretty cool feature that only Mack and Merb share. And finally there is bundled gems.</p>
<h3>Bundled Gems</h3>
<p>What do I mean I say &#8216;bundled gems&#8217;? Well, because of the rather large number of gems that get installed with Mack, and because of some gem version dependency issues, Mack is now bundling it&#8217;s third party dependency gems inside itself. For example, mack-facets used to rely on the gems &#8216;facets&#8217; and &#8216;english&#8217;. Those gems are now bundled inside the mack-facets gem and now longer need to be downloaded and installed by end users. This should make installing Mack super easy. It should also make dealing with having multiple versions of Mack installed on your system easier to deal with and maintain.</p>
<h3>Deferred? Routes</h3>
<p>So what are deferred routes? Ezra wrote a really great write up back in <a href="http://brainspl.at/articles/2008/04/18/deferred-requests-with-merb-ebb-and-thin" target="_blank">April</a>. The idea is simple, with newer web servers such as Thin and Ebb, you can tell them to spawn a new thread to handle particular requests, such as long running processes like file uploads. This can really help speed things up as server can process regular requests using an event machine model, which is very fast, but can be really slow and block the server for longer processes. Now those processes can spawn into their own threads and not block the server.</p>
<p>In Mack 0.8.2 you can mark your routes with a deferred? =&gt; true option which will trigger this behavior. It&#8217;s much more advanced than the similar feature that can be found in Merb, which requires a separate configuration for your deferred actions, and the urls have to be &#8216;hard coded&#8217;. Mack let&#8217;s you use all the dynamic power of your routes, like you would want to. It&#8217;s just another option on the route itself. For a great tutorial on using deferred routes, check out the following page on www.mackery.com:</p>
<p><a href="http://www.mackery.com/routing/deferred_routes">http://www.mackery.com/routing/deferred_routes</a></p>
<h3>Upgraded Dependencies</h3>
<p>A few gems have been upgraded as part of this release, the big ones include DataMapper to 0.9.7, ActiveRecord to 2.2.2, and Haml to 2.0.4.</p>
<p>Changelog:</p>
<ul>
<li>[#237] Fixed render :rjs throws errors</li>
<li>[#236] Upgraded to ActiveRecord 2.2.2</li>
<li>[#235] Upgraded to DataMapper 0.9.7</li>
<li>[#230] Upgraded to facets 2.4.5</li>
<li>[#229] Upgraded to english 0.3.1</li>
<li>[#227] Removed WEBrick logging</li>
<li>[#226] Bundled gems.</li>
<li>[#225] Removed dependency on Thin</li>
<li>[#223] Fixed mackery console fails</li>
<li>[#148] Added button_to_remote helper method.</li>
<li>[#16] Added deferred? routes.</li>
<li>gem: active_record 2.2.2</li>
<li>gem: data_mapper 0.9.7</li>
<li>gem: addressable 2.0.0</li>
<li>gem: facets 2.4.5</li>
<li>gem: english 0.3.1</li>
<li>gem: rspec 1.1.11</li>
<li>gem: haml 2.0.4</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.metabates.com/2008/11/30/release-082/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Release 0.6.0</title>
		<link>http://www.metabates.com/2008/07/16/release-060/</link>
		<comments>http://www.metabates.com/2008/07/16/release-060/#comments</comments>
		<pubDate>Wed, 16 Jul 2008 14:04:22 +0000</pubDate>
		<dc:creator>Mark Bates</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Releases]]></category>
		<category><![CDATA[Updates]]></category>
		<category><![CDATA[active record]]></category>
		<category><![CDATA[darsono sutedja]]></category>
		<category><![CDATA[data mapper]]></category>
		<category><![CDATA[haml]]></category>
		<category><![CDATA[mack]]></category>
		<category><![CDATA[mack-more]]></category>
		<category><![CDATA[markaby]]></category>
		<category><![CDATA[release]]></category>
		<category><![CDATA[rspec]]></category>

		<guid isPermaLink="false">http://www.mackframework.com/?p=110</guid>
		<description><![CDATA[Well, it&#8217;s finally here, Mack 0.6.0! This release has taken a long time, but I feel that it&#8217;s definitely worth it. This has to be the best release of Mack to date. During this release the Mack dev team grew by 100%, Darsono Sutedja, previously a contributor to Mack, is now a full time Mack [...]]]></description>
			<content:encoded><![CDATA[<p>Well, it&#8217;s finally here, Mack 0.6.0! This release has taken a long time, but I feel that it&#8217;s definitely worth it. This has to be the best release of Mack to date. During this release the Mack dev team grew by 100%, Darsono Sutedja, previously a contributor to Mack, is now a full time Mack core team developer! Darsono has done an absolutely great job on this release, thanks Darsono. With that out of the way, let&#8217;s jump straight to the good stuff, shall we?</p>
<h3>DataMapper 0.9.2 Support</h3>
<p>At long last Mack supports DataMapper 0.9.2. Because previous versions of Mack used DataMapper 0.3.2, there is some upgrade work that you&#8217;ll need to do, but trust me, it&#8217;s worth it. DataMapper 0.9.2 is a gigantic leap forward from 0.3.2. If you have problems installing the data_mapper gem, make sure that you don&#8217;t have gems.datamapper.org in your source path for rubygems. You can remove it with the following command:</p>
<pre>gem source -r http://gems.datamapper.orgÂ </pre>
<h3>RSpec Testing Support</h3>
<p>RSpec is now the default testing framework for new Mack applications. This innovative testing framework makes it fun, and simple, to do behavior driven development. If you haven&#8217;t yet played with RSpec, I would highly recommend it. I wasn&#8217;t a big fan of &#8216;spec&#8217; testing prior to meeting Adam French, of DataMapper fame, and he turned me on to the joys of rspec. I think you&#8217;ll like it too, if you give it a chance. <img src='http://www.metabates.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h3>mack-more</h3>
<p>There is now a mack-more package. This will house all the optional gems available to the Mack framework. This include things like HAML and Markaby support, localization, etc&#8230; Use what you want, ignore the rest. This will help keep the core code clean, light, and of course, fast.</p>
<h3>Localization/l10n Support</h3>
<p>Darsono did a great job with the mack-localization gem. There is now optional support for internationalization in Mack applications. Check out the gem, it&#8217;s definitely worth it if you need to support multiple languages for your web application.</p>
<h3>Much, much more!</h3>
<p>Of course, there&#8217;s a lot more Mack than the stuff I just mentioned, there&#8217;s tons of bug fixes, some code clean up, some API changes, transactional testing support, the ability to catch specific errors in routes and have them diverted to a controller/action for handling.</p>
<p>There is a great wiki entry on upgrading your existing Mack project to 0.6.0 <a href="http://wiki.mackframework.com/index.php/en/Upgrading%20from%200.5.x%20to%200.6.x" target="_blank">here</a>. I highly recommend reading it whether or not you have an existing Mack application.</p>
<p>With this release the Mack team is also fully embracing Lighthouse. If you find bugs, or have suggestions please visit <a href="http://lighthouse.mackframework.com" target="_blank">http://lighthouse.mackframework.com</a>Â and log them there. You&#8217;ll also find the list of features that will eventually be added to Mack.</p>
<p>Changelog:</p>
<ul>
<li>INCOMPATIBILITY NOTICE: Moved Mack::Configuration.root to Mack.root</li>
<li>INCOMPATIBILITY NOTICE: Moved Mack::Configuration.env to Mack.env</li>
<li>INCOMPATIBILITY NOTICE: Mack::Configuration.* path methods no longer exist. Use mack-paths instead.</li>
<li>INCOMPATIBILITY NOTICE: Dropped mack_ruby_core_extensions in favor or mack-facets</li>
<li>INCOMPATIBILITY NOTICE: Mack::Controller::Base is now Mack::Controller (and it&#8217;s now a module)</li>
<li>INCOMPATIBILITY NOTICE: Haml renderer is now part of mack-more.</li>
<li>INCOMPATIBILITY NOTICE: Markaby renderer is now part of mack-more.</li>
<li>INCOMPATIBILITY NOTICE: Changed request param&#8217;s accessor routine, from params(key) to params[key]</li>
<li>INCOMPATIBILITY NOTICE: Test::Unit::TestCase is no longer the default testing framework, RSpec is. If you wish to useÂ Test::Unit::TestCase add the following config parameter to your config/app_config/default.yml file:<br />
Â Â mack::testing_framework: test_case</li>
<li>INCOMPATIBILITY NOTICE: ENV["_mack_env"] and ENV["_mack_root"] are no longer supported, please use ENV["MACK_ENV"] and ENV["MACK_ROOT"], or just Mack.env and Mack.root</li>
<li>INCOMPATIBILITY NOTICE: MACK_DEFAULT_LOGGER constant is no longer available. Please use Mack.logger instead.</li>
<li>INCOMPATIBILITY NOTICE: The ApplicationHelper module is now deprecated. Please move view level helpers into Mack::ViewHelpers::* and controller helpers into Mack::ControllerHelpers::&lt;controller_name&gt;</li>
<li>thin.ru and thin.yml are no longer needed, you may delete them.</li>
<li>RSpec assertions are now automatically added.</li>
<li>Added a Mack::Testing::Response class to make testing of responses easier.</li>
<li>moved test_extensions to testing and added the module Testing to the files in it.</li>
<li>Added a dependency on mack-more</li>
<li>Added a set of Rake tasks to update existing Mack applications.</li>
<li>[#30] Added Mack::Logging::Filter to filter out unwanted parameters from the logs.</li>
<li>In routing you can now define a route that will catch an Exception from another controller.</li>
<li>ORM will not be initialized if the app never specify which ORM to use.</li>
<li>All Mack unit tests are now written using rspec-1.1.4.</li>
<li>mack command now takes an optional -t flag to determine which testing framework to use&#8211;value could be test_case or rspec [default]</li>
<li>new setting added to app_config: testing_framework</li>
<li>gem: cachetastic 1.7.2</li>
<li>gem: application_configuration 1.5.0</li>
<li>gem: erubis 2.6.2</li>
<li>gem: genosaurus 1.2.1</li>
<li>gem: thin 0.8.2</li>
<li>gem: rspec 1.1.4</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.metabates.com/2008/07/16/release-060/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>0.6.0 Coming VERY soon!</title>
		<link>http://www.metabates.com/2008/07/10/060-coming-very-soon/</link>
		<comments>http://www.metabates.com/2008/07/10/060-coming-very-soon/#comments</comments>
		<pubDate>Thu, 10 Jul 2008 18:40:59 +0000</pubDate>
		<dc:creator>Mark Bates</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[data mapper]]></category>
		<category><![CDATA[mack]]></category>
		<category><![CDATA[mack-more]]></category>
		<category><![CDATA[routing]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[upgrade]]></category>
		<category><![CDATA[wiki]]></category>

		<guid isPermaLink="false">http://www.mackframework.com/?p=109</guid>
		<description><![CDATA[Well folks, as you know, things have been a bit quiet on the Mack front these days, but it&#8217;s all been for a very good reason. We&#8217;ve been prepping the next release, 0.6.0. This release is expected to hit the streets sometime the beginning of next week. There&#8217;s a lot of really great stuff in [...]]]></description>
			<content:encoded><![CDATA[<p>Well folks, as you know, things have been a bit quiet on the Mack front these days, but it&#8217;s all been for a very good reason. We&#8217;ve been prepping the next release, 0.6.0. This release is expected to hit the streets sometime the beginning of next week. There&#8217;s a lot of really great stuff in the release, DataMapper 0.9.2 support (finally!), RSpec testing support, a mack-more project to house a bunch of cool Mack related gems, Exception handling in Routing, and more&#8230; A full list will be available when the release happens.</p>
<p>In addition to the great new features, a lot of bugs have been worked out, and more of the API has solidified further. Because of some of these changes I&#8217;ve posted an upgrade guide from 0.5.x to 0.6.0. This guide can be found on the <a href="http://wiki.mackframework.com/index.php/en/Upgrading%20from%200.5.x%20to%200.6.x" target="_blank">wiki</a>.&nbsp;</p>
<p>This guide is meant to make upgrading as quickly and as a painless possible. There are a couple of big changes, but they should be fairly simple to make.</p>
<p>I&#8217;m very happy with this release, it&#8217;s been long toiled over, and it shows. It&#8217;s very stable, fast, and fun. I think everyone is really going to like it.&nbsp;</p>
<p>As more info about the release becomes available, I&#8217;ll keep everyone posted.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.metabates.com/2008/07/10/060-coming-very-soon/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

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

