<?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>Inforbiomatica &#187; Rails</title>
	<atom:link href="http://www.moseshohman.com/blog/category/programming/rails/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.moseshohman.com/blog</link>
	<description>software development, informatics, etc.</description>
	<lastBuildDate>Wed, 24 Aug 2011 04:43:27 +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>Turns out, cucumber/webrat is worse</title>
		<link>http://www.moseshohman.com/blog/2010/03/16/turns-out-cucumberwebrat-is-worse/</link>
		<comments>http://www.moseshohman.com/blog/2010/03/16/turns-out-cucumberwebrat-is-worse/#comments</comments>
		<pubDate>Tue, 16 Mar 2010 05:17:30 +0000</pubDate>
		<dc:creator>Moses</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Testing]]></category>

		<guid isPermaLink="false">http://www.moseshohman.com/blog/?p=72</guid>
		<description><![CDATA[At CDD we use a fairly strange stack to run our automated in-browser (Selenium RC) integration tests. When we started writing these tests back in 2007, we used the best technology we knew of that was then available, a Rails plugin called funkytown, since-abandoned brainchild of Pivotal Labs. Funkytown&#8217;s code is a little weird, and [...]]]></description>
			<content:encoded><![CDATA[<p>At CDD we use a fairly strange stack to run our automated in-browser (Selenium RC) integration tests.</p>

<p>When we started writing these tests back in 2007, we used the best technology we knew of that was then available, a Rails plugin called funkytown, since-abandoned brainchild of Pivotal Labs. Funkytown&#8217;s code is a little weird, and we&#8217;ve had to fix bugs and inflexibilities from time to time. We monkeypatched its rake tasks. Over the years we updated the bundled version of the selenium RC jar file several times.</p>

<p>We wrote another library (selenium-spec, which we open sourced once a while back) on top of funkytown that integrated selenium tests into rspec, provided the ability to chain examples (see <a href="http://www.moseshohman.com/blog/2007/08/08/chained-selenium-rspec-examples/">this blog post</a>), as well as
 some webrat-like helper methods, except better, enabling code like <code>element('results').should be_visible</code>.</p>

<p>So that&#8217;s what we&#8217;ve been using for a few years now. It&#8217;s not pretty, but it works. When cucumber and webrat came out, all the buzz made me think that we&#8217;d inevitably switch over some day in the beautiful future when everything will be perfect. However, I recently had the opportunity to try them out on a another pet project of mine, and I was surprised to learn that even though they have a much bigger install base than our install base of one, our crazy stack turns out to be better.</p>

<p>There are three major problems with cucumber/webrat/selenium RC, as far as I can tell:</p>

<ol>
    <li>You can&#8217;t really use fixtures.</li>
    <li>Debugger breakpoints in your application code don&#8217;t work.</li>
    <li>I swear there was a number three.</li>
</ol>

<p>All of those (well, at least the first two) aren&#8217;t true of our crazy stack, and I wouldn&#8217;t want to give them up.</p>

<p>There are some nice things about cucumber/webrat. The annotations are neat, and it&#8217;s kind of cool that you can run your tests as both Rails integration and selenium RC tests (although I imagine once your tests get realistically complex at all that is no longer so assured).</p>

<p>Perhaps a good opportunity, one day in that beautiful future, for us to clean up our stack, rebase it on some more modern infrastructure (or rewrite our own), and open source what for us has been a really useful tool.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.moseshohman.com/blog/2010/03/16/turns-out-cucumberwebrat-is-worse/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Too many mock objects == ruby refactoring death</title>
		<link>http://www.moseshohman.com/blog/2008/07/06/too-many-mock-objects-ruby-refactoring-death/</link>
		<comments>http://www.moseshohman.com/blog/2008/07/06/too-many-mock-objects-ruby-refactoring-death/#comments</comments>
		<pubDate>Mon, 07 Jul 2008 00:22:36 +0000</pubDate>
		<dc:creator>Moses</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Testing]]></category>

		<guid isPermaLink="false">http://www.moseshohman.com/blog/2008/07/06/too-many-mock-objects-ruby-refactoring-death/</guid>
		<description><![CDATA[It&#8217;s a question we face as test-driven ruby programmers: Should we use mock objects or real objects in our tests? Both approaches have trade-offs, and their biggest downsides both have to do with wasting programmer time. If you test with real objects, then your tests run slowly (especially if you use an ORM that binds [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s a question we face as test-driven ruby programmers: Should we use mock objects or real objects in our tests?</p>

<p>Both approaches have trade-offs, and their biggest downsides both have to do with wasting programmer time. If you test with real objects, then your tests run slowly (especially if you use an ORM that binds your domain objects tightly to the database like ActiveRecord). Your tests hit the database, and this is slow. There are other sources of slowness, but nothing has anywhere near as great an effect as hitting the DB.</p>

<p>If you test with mock objects, once your app has any kind of complexity, your refactoring and test writing processes become slow. This is not immediately apparent when you start using mock objects. But as you start writing more and more code, eventually you start having to come up with a crazy number of mock expectations just to test some of your methods. It is true that this is good feedback that the class you&#8217;re testing presents too complex an interface to other collaborating objects, or that it collaborates with too many objects, etc. What starts simple will eventually become too complex, and at some point you&#8217;re going to need to refactor.</p>

<p>More insidious than this, however, is the effect this web of mocks you&#8217;ve wrapped yourself in has on refactoring. You don&#8217;t notice how thoroughly you&#8217;ve painted yourself into a corner until you want to refactor some ugly aspect of a core class that collaborates with many objects in your system. Suddenly all of those collaborating objects&#8217; tests break because they expect certain method calls from this core object. These tests break because you&#8217;ve changed a method signature, a method name, or even worse just an implementation, because no matter what those BDDers tell you, if you test with mocks, to too great a degree that means you&#8217;re testing implementation, not behavior (or is that behaviour).</p>

<p>So, now you have to go through all of those mock-based tests and &#8220;correct&#8221; them, i.e. change their expectations so that they fit the new method name/signature/implementation. This is horrible. The whole point of tests during refactoring is to verify that your refactoring hasn&#8217;t changed the behavior of the system (that being half of the definition of refactoring). The tests should pass before you refactor, and they should pass after you refactor. Not only does this break the fundamental refactoring process, it also can take a lot of time, because you have to remember the context of each of those test cases that you have to fix.</p>

<p>You can do something about slow running tests that hit a database (in extreme cases you can use a faster in-memory database, or even parallelize your tests). Of course they won&#8217;t run as fast as they would if they didn&#8217;t hit a database, but in my opinion it&#8217;s something you can live with. <a target="_blank" href="http://akuaku.org">Dav Yaginuma</a> has a good suggestion for what to do with this time: Go write that email you need to write, go take the bathroom break, go walk around the office and stretch your legs. It&#8217;s not like that&#8217;s really wasted time. It is wasted time, however, if you&#8217;re sitting there squinting at the screen fixing all of your mock expectations. You can&#8217;t do anything else with that time.</p>

<p>I&#8217;m kind of half-convinced now that people who advocate the heavy use of mocking either have really nice IDEs that make fixing the expectations a breeze, or they don&#8217;t refactor. And if they&#8217;re using Ruby that means they don&#8217;t refactor. Ok, tongue out of cheek. Seriously, I&#8217;d love to hear from folks who have used and continue to use mocks heavily on long running projects, to hear how they handle the refactoring issue. I have pretty much sworn off mocks except in old-school traditional cases (&#8220;mocking out an external  dependency too expensive to call directly&#8221;) because of it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.moseshohman.com/blog/2008/07/06/too-many-mock-objects-ruby-refactoring-death/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>MacPorts Ruby, now with DTrace</title>
		<link>http://www.moseshohman.com/blog/2008/02/21/macports-ruby-now-with-dtrace/</link>
		<comments>http://www.moseshohman.com/blog/2008/02/21/macports-ruby-now-with-dtrace/#comments</comments>
		<pubDate>Thu, 21 Feb 2008 07:38:11 +0000</pubDate>
		<dc:creator>Moses</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[ruby dtrace macports]]></category>

		<guid isPermaLink="false">http://www.moseshohman.com/blog/2008/02/21/56</guid>
		<description><![CDATA[We are gearing up to do some profiling/performance improvement at work, and we use MacPorts (mostly at my stubborn insistence) to install Ruby on our OS X dev boxes. Unfortunately, the MacPorts version of Ruby is not DTrace-enabled, so we were faced with the decision to either go with the Apple-installed Ruby or not use [...]]]></description>
			<content:encoded><![CDATA[<p>We are gearing up to do some profiling/performance improvement at work, and we use MacPorts (mostly at my stubborn insistence) to install Ruby on our OS X dev boxes. Unfortunately, the MacPorts version of Ruby is not DTrace-enabled, so we were faced with the decision to either go with the Apple-installed Ruby or not use DTrace.</p>

<p>Fortunately, there was a third option. I spent some time massaging Joyent&#8217;s Ruby DTrace patch so that it would compile with Apple&#8217;s version of DTrace (subtly different from Solaris&#8217;s), and so it would play nice with the other patches in the official Ruby MacPort distribution. Anyway, long story short: you can get it via my newest RubyForge project, <a href="http://rubyforge.org/projects/rubyport-dtrace">rubyport-dtrace</a>. You can install either from the tarfile or by checking out from Subversion, see the instructions in the distribution.</p>

<p>Why I like MacPorts: I like being able to cleanly remove software I install. I also like that I can compile Ruby with DTrace and other patches that I might want (such as the Railsbench GC patch, which I&#8217;m also working in to the rubyport-dtrace (dare I call it) code, it might already work but I haven&#8217;t tested it).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.moseshohman.com/blog/2008/02/21/macports-ruby-now-with-dtrace/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Chained Selenium RSpec examples</title>
		<link>http://www.moseshohman.com/blog/2007/08/08/chained-selenium-rspec-examples/</link>
		<comments>http://www.moseshohman.com/blog/2007/08/08/chained-selenium-rspec-examples/#comments</comments>
		<pubDate>Thu, 09 Aug 2007 02:21:42 +0000</pubDate>
		<dc:creator>Moses</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Testing]]></category>

		<guid isPermaLink="false">http://www.moseshohman.com/blog/2007/08/08/50</guid>
		<description><![CDATA[From the RSpec documentation: It is very tempting to use before(:all) and after(:all) for situations in which it is not appropriate. before(:all) shares some (not all) state across multiple examples. This means that the examples become bound together, which is an absolute no-no in testing. You should really only ever use before(:all) to set up [...]]]></description>
			<content:encoded><![CDATA[<p>From the <a href="http://rspec.rubyforge.org/documentation/before_and_after.html">RSpec documentation</a>:</p>

<blockquote>
  <p>It is very tempting to use before(:all) and after(:all) for situations in which it is not appropriate.
  before(:all) shares some (not all) state across multiple examples. This means that the examples
  become bound together, which is <span style="color:red;">an absolute no-no</span> in testing.
  You should really only ever use before(:all) to set up things that are global collaborators but not 
  the things that you are describing in the examples.</p>
</blockquote>

<p>Well-known conventional wisdom says that different test cases (in spec-speak, &#8220;examples&#8221;) should not depend on one another for state, should be runnable in any order, etc. I certainly agree with this wisdom in general, but I think there&#8217;s one case where this rule should be broken. We&#8217;ve been writing a fair number of Selenium RC tests lately for our app, using RSpec to drive Selenium RC. When writing integration tests like this, each example (in test speak, &#8220;test method&#8221;) is often a very long script with lots of shoulds/asserts in it. We lose the nice descriptive power of small examples with specific, descriptive text, and instead are faced with a choice between vague and high-level example descriptions and really long example descriptions using ugly here documents that can easily fall out of synch with the example code.</p>

<p>Instead, we want to be able to do something like this:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">    describe <span style="color:#996600;">&quot;A user customizing a car&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
      use_chained_examples
&nbsp;
      before<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
        <span style="color:#0066ff; font-weight:bold;">@model</span> = models<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:spiffy</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        log_in
        go_to_car_customization_start_page
      <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
      it <span style="color:#996600;">&quot;should first be required to select car model&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
        page_title.<span style="color:#9900CC;">should</span> == <span style="color:#996600;">&quot;Select a model&quot;</span>
        droplist<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;model_id&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">should</span> be_present
        droplist<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;model_id&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">options</span>.<span style="color:#9900CC;">should</span> == <span style="color:#006600; font-weight:bold;">&#91;</span>
          <span style="color:#996600;">&quot;(Please select a model)&quot;</span>,
          models<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:spiffy</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">name</span>,
          models<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:sporty</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">name</span>
        <span style="color:#006600; font-weight:bold;">&#93;</span>
        droplist<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;model_id&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">selected_value</span>.<span style="color:#9900CC;">should</span> == <span style="color:#996600;">&quot;&quot;</span>
&nbsp;
        droplist<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;model_id&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#CC0066; font-weight:bold;">select</span><span style="color:#006600; font-weight:bold;">&#40;</span>@model.<span style="color:#9900CC;">id</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        click_next_button
      <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
      it <span style="color:#996600;">&quot;should then be required to select paint color&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
        page_title.<span style="color:#9900CC;">should</span> == <span style="color:#996600;">&quot;Select #{@model.name} color&quot;</span>
        droplist<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;color_id&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">should</span> be_present
        <span style="color:#008000; font-style:italic;"># etc.</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>


<p>A <code>before(:each)</code> block can be used to reset the page between each example, which we&#8217;ve found useful when testing a bunch of validations or something similar. Note too that using chained examples is not the default behavior, and must be explicitly specified by the developer, who should &#8220;know what they are doing&#8221; if they do this.</p>

<p>Anyway, obviously we did figure out how to make this happen, and after we&#8217;ve refined it a bit if people are interested we&#8217;ll open source our selenium rspec stuff as a plugin. Note that our selenium specs use a different <code>spec_helper.rb</code> than the rest of our normal specs, so we&#8217;re keeping the ability to chain examples out of our standard specs, as conventional wisdom would recommend. Let me know what you think.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.moseshohman.com/blog/2007/08/08/chained-selenium-rspec-examples/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Keeping Rails migrations happy</title>
		<link>http://www.moseshohman.com/blog/2007/05/09/keeping-rails-migrations-happy/</link>
		<comments>http://www.moseshohman.com/blog/2007/05/09/keeping-rails-migrations-happy/#comments</comments>
		<pubDate>Wed, 09 May 2007 18:01:02 +0000</pubDate>
		<dc:creator>Moses</dc:creator>
				<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://www.moseshohman.com/blog/2007/05/09/47</guid>
		<description><![CDATA[Two quick things we&#8217;ve learned about migrations at CDD: Avoid using your model objects in your migrations, e.g. stuff like Group.create!(:name =&#62; "Watson Lab"). The problem with this is that later you might add a required field to your model, and then this migration will throw an exception. Occasionally you need some logic from a [...]]]></description>
			<content:encoded><![CDATA[<p>Two quick things we&#8217;ve learned about migrations at <a href="http://www.collaborativedrug.com">CDD</a>:</p>

<ul>
<li>Avoid using your model objects in your migrations, e.g. stuff like <code>Group.create!(:name =&gt; "Watson Lab")</code>. The problem with this is that later you might add a required field to your model, and then this migration will throw an exception. Occasionally you need some logic from a model in a migration, but if at all possible I&#8217;d suggest exposing that logic in a way that doesn&#8217;t require creating or loading model objects in your migration itself. The migration should just know about SQL, nothing else.</li>
<li>Say you branch your code base for a release, and you anticipate needing to support that branch for any length of time. Sometimes you&#8217;ll need to address an issue in the production code that requires another migration. What we&#8217;ve found works best with ActiveRecord migrations is:

<ol>
<li>In the trunk, delete all existing migrations when you branch.</li>
<li>Dump a version of the branch schema, and make that migration #1 (<code>001_production_branch_schema.rb</code>) in your trunk.</li>
<li>Start your next trunk migration several numbers higher than your last migration on the production release branch. So, if your
last migration on the branch was 40, start 40+N, where N gives you enough cushion to accommodate any
additional migrations needed for the branch until your next release.</li>
<li>Any time you add another migration to the branch, in the trunk replace <code>001_production_branch_schema.rb</code> with a new dump of your branch schema.</li>
</ol></li>
</ul>

<p>Kind of a hack, but it works better than anything else we&#8217;ve come up with. My former colleague, <a href="http://detailedbalance.net/glove-compartment/">Rhett Sutphin</a>, took a different approach to this problem when he wrote a Java/Groovy port of migrations called <a href="http://code.google.com/p/bering/">bering</a> (to which I minimally contributed in its early stages). In bering, migrations are specific to a particular release. Each release is numbered and gets its own separate migration directory, and migrations start at one again for each new release.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.moseshohman.com/blog/2007/05/09/keeping-rails-migrations-happy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

