<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/rss2full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><rss version="2.0">
  <channel>
    <title>Something Nimble</title>
    <link>http://www.somethingnimble.com/bliki</link>
    <pubDate>Sun, 01 Jun 2008 16:09:00 GMT</pubDate>
    <description>Something Nimble</description>
    <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/somethingnimble" type="application/rss+xml" /><item>
      <title>deepTest. those promiscuous teen years</title>
      <link>http://www.somethingnimble.com/bliki/deep-test-1_2_0</link>
      <description>&lt;h4&gt;catching up. . .&lt;/h4&gt;
&lt;p&gt;

When we last saw DeepTest, it was stepping intrepidly out into the world to parallelize your
tests.  Just a young buck but raring and ready to go.  A lot has
happened since then, and DeepTest has made it to its teen years (in the
world of software that means version 1.2 of course).
&lt;/p&gt;

&lt;p&gt;
DeepTest now supports
parallelizing RSpec examples in addition to Test::Unit based tests.  RSpec
support was like DeepTest's first dance -- it takes a while to screw up the
courage to ask her out on the floor, but it gets easier with each dance. And so DeepTest has become quite the socialite. Making its full-blown debut into adolescence, DeepTest now happily distributes
tests remotely, simultaneously do-si-do-ing with any number of machines.
&lt;/p&gt;

&lt;h4&gt;no more tripping over your own shoelaces&lt;/h4&gt;
&lt;p&gt;

It used to be that DeepTest was young and clumsy when dealing with your
database.  Using a single database caused occasional deadlocks when multiple
tests collided on the same table.  DeepTest has grown up and learned
some database diplomacy.  If you tell it to, DeepTest will setup a separate
database for each worker, thus avoiding deadlocks.  If you're using Mysql
and ActiveRecord with a fairly vanilla setup, all you need is this in your
Rakefile:
&lt;/p&gt;
&lt;pre&gt;
DeepTest::TestTask.new "task_name" do |t|
 ...
 t.worker_listener = "DeepTest::Database::MysqlSetupListener"
end
&lt;/pre&gt;
&lt;p&gt;
 The MysqlSetupListener will dump the schema from your test database,
 create a new database for each worker, load the dumped schema, and then
 connect the workers to one of the databases.  And separate databases means
 no more deadlocks.
&lt;/p&gt;
&lt;/p&gt;
 If you're not using Mysql, DeepTest does not currently have out-of-the-box
 support for your database.  &lt;tt&gt;DeepTest::Database::SetupListener&lt;/tt&gt; is
 available to help you, but you'll have to dig down and implement the details
 of creating and dropping databases and dumping and loading schemas.
&lt;/p&gt;
&lt;p&gt;
If you do decide to help DeepTest grow by trying out other databases flavors, please
 consider contributing the code so others can benefit from your
 labor.
&lt;p&gt;

&lt;h4&gt;first dance with RSpec&lt;/h4&gt;
&lt;p&gt;
Dancing with your RSpec examples is just as easy for DeepTest as playing
with your Test::Unit tests.  If you haven't done it yet, install the gem.
&lt;/p&gt;
&lt;p&gt;&lt;tt&gt;gem install deep_test&lt;/tt&gt;&lt;/p&gt;

&lt;p&gt;Then put something like this is your Rakefile:&lt;/p&gt;
&lt;pre&gt;
 require "rubygems"
 require "deep_test/rake_tasks"

 # sample SpecTask using DeepTest
 Spec::Rake::SpecTask.new(:deep_spec) do |t|
   t.spec_files = FileList['spec/**/*_spec.rb']
   t.deep_test :number_of_workers =&amp;gt; 2   # optional, defaults to 2
 end
&lt;/pre&gt;

&lt;h4&gt;get an entourage to do the work for you&lt;/h4&gt;
&lt;p&gt;

The most exciting addition for DeepTest is the ability to distribute your tests
across multiple machines.  Instead of sitting there all by its lonesome on your
poor little developer machine, DeepTest can now command an army of machines to
do its bidding and run your tests even faster.  To get started you'll need 2
or more machines that will run tests (call them deeptest1 and deeptest2), and
your developer machine that has a project already using DeepTest to run
functional tests locally.  Both the deeptest machines will need to be able to
access the developer machine over password-less ssh. All machines involved need
to have rsync installed.  On deeptest1 and deeptest2, install the gem.  Then
start a test server on each one.

&lt;/p&gt;
&lt;p&gt;
&lt;tt&gt;gem install deep_test&lt;/tt&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;tt&gt;deep_test test_server&lt;/tt&gt;
&lt;/p&gt;
&lt;p&gt;
 For this example configuration, let's use deeptest1 as the master server that keeps track of the rest
 of the test servers.  On deeptest1, start a master server process.
&lt;/p&gt;
&lt;pre&gt;
deep_test master_test_server \
           druby://deeptest1:4022/ \
           druby://deeptest2:4022/
&lt;/pre&gt;
&lt;p&gt;
 (the line continuations are just to look nice, you can put it all on one line)
&lt;/p&gt;
&lt;p&gt;
 Now change the test task in your rakefile to specify the distributed options for deeptest.
&lt;/p&gt;
&lt;pre&gt;
DeepTest::TestTask.new "task_name" do |t|
 t.pattern = "test/**/*_test.rb"
 t.number_of_workers = 2
 t.distributed_server = "druby://deeptest1:4021"

 # If you don't have a database you can leave this line out.
 # If you have a non-Mysql database, please see the documentation
 #   at rubyforge.
 t.worker_listener = "DeepTest::Database::MysqlSetupListener"

 t.sync_options = {
   # assumes Rakefile is in the root of your project
   :source =&amp;gt; File.expand_path(File.dirname(__FILE__)),

   # username on local machine that is accessible by deeptest1 and 2
   :username =&amp;gt; "developer"
 }
end
&lt;/pre&gt;
&lt;h4&gt;the big payoff&lt;/h4&gt;
&lt;p&gt;

DeepTest was conceived because our functional tests hurt, and hurt bad.  We
originally reported that we felt pain over the 2 minute mark.  Local
parallelization solved the problem for us temporarily, but we kept adding
functional tests.  Eventually it reached the point were functional tests took 6
1/2 minutes to run &lt;b&gt;using DeepTest&lt;/b&gt;.  It was time for a change.  By
distributing the tests to 3 machines, we brought our functional test run down
to 2 minutes again.  While we'll obviously keep growing, the higher
parallelization slows the growth.  But even better, we can
keep adding more machines to run test suites to scale the problem indefinitely.
&lt;/p&gt;
&lt;p&gt;
Now if only DeepTest would get a job and move out!
&lt;/p&gt;
</description>
      <pubDate>Sun, 01 Jun 2008 16:09:00 GMT</pubDate>
      <guid>http://www.somethingnimble.com/bliki/deep-test-1_2_0</guid>
      <author>anonymous z, Dan Manges</author>
    </item>
    <item>
      <title>radiator:&lt;br/&gt;all your build statuses in amazing 6 bit color</title>
      <link>http://www.somethingnimble.com/bliki/radiator</link>
      <description>&lt;h4&gt;brought to you by Hammer&lt;/h4&gt;
&lt;p&gt;(with a little help from &lt;a href="http://www.somethingnimble.com/collaborators/z"&gt;nonymous&lt;/a&gt;, &lt;a href ="http://www.somethingnimble.com/collaborators/david"&gt;David Vollbracht&lt;/a&gt;, and &lt;a href="http://www.dcmanges.com/blog"&gt;Dan Manges&lt;/a&gt;)&lt;/p&gt;

&lt;h4&gt;disciplined feedback &amp;amp; unceremonious essence&lt;/h4&gt;

&lt;p&gt;&lt;a href="http://memeagora.blogspot.com/"&gt;Neal Ford&lt;/a&gt;, a friend of ours, likes to ask people that he's interviewing to describe some intricate concept in just two words. the challenge is to articulately extract as much essence as possible&lt;/p&gt;

&lt;p&gt;a favorite is "describe agile programming in just two words". we like the answer "disciplined feedback". so much of the agile philosophy is about discipline. and so much of it is about feedback loops providing useful information. and then again about having the discipline to make appropriate corrections based on feedback. and so on....&lt;/p&gt;

&lt;h4&gt;visibility of feedback&lt;/h4&gt;

&lt;p&gt;as fans of feedback we use things like story walls and continuous integration* to give us feedback on the status of our work.&lt;/p&gt;

&lt;p&gt;story card walls are simple. and done right, they radiate information effortlessly throughout a dev room. you look up and you can see the status of all the important, trackable work being done. instant feedback. discipline is not working on tasks that aren't on the wall and moving cards appropriately through their wild life-cycle&lt;/p&gt;

&lt;p&gt;continuous integration** gives you feedback on your builds. it can quickly inform you if that last check in didn't play nicely with all the other code you've got. it also helps maintain discipline. nobody wants to be caught breaking the build. unfortunately, unlike a giant card wall, it can be hard to get room-wide visibility for the status or your builds.&lt;/p&gt;

&lt;p&gt;having to check a build page gets old. growl messages are only useful if you're in front of a computer. and they can be bothersome.&lt;/p&gt;

&lt;p&gt;on a recent project, we had such little visibility into the status of our various and splendid builds that we coerced a teammate into continually*** notifying us of their activity. unfortunately, he found the work so depressing that he began to drink heavily. occasionally he came to work drunk, affecting a fake Spanish accent, and wearing a large sombrero for no apparent reason.&lt;p&gt;

&lt;img src="/images/el_build_externals.jpg" style="width: 600px;"&gt;

&lt;p&gt;while we were happy to have a very visible build notification mechanism, we decided to do without the drunkenness and cultural insensitivity of the manual solution.&lt;/p&gt;

&lt;p&gt;but not before replacing it with a much more efficient, automated one....&lt;/p&gt;

&lt;h4&gt;introducing radiator&lt;/h4&gt;
&lt;br/&gt;
&lt;img src="/images/radiator_externals.jpg" style="width: 600px;"&gt;
&lt;br/&gt;
&lt;br/&gt;
&lt;p&gt;radiator is a ruby-based service for radiating messages with a USB beta brite. it includes a plugin for cruise.rb allowing you to radiate your build status messages without driving another teammate to drink. 
&lt;/p&gt;
	
&lt;p&gt;it's pretty sweet really.&lt;/p&gt;
&lt;img src="/images/radiator_success.jpg" style="width: 600px;"&gt;


&lt;h4&gt;I can has radiator?&lt;/h4&gt;
&lt;p&gt;yes, you can. get it anonymous style with &lt;/p&gt;
&lt;p&gt;	&lt;tt&gt;svn co http://hammersforge.com/svn/radiator/trunk&lt;/tt&gt;&lt;p&gt;

&lt;p&gt;the readme should be all you need to start radiating your project today.&lt;p/&gt;
&lt;p&gt;well, that and a &lt;a href="http://www.betabrite.com/"&gt;beta brite&lt;/a&gt;.&lt;/p&gt;

&lt;hr/&gt;
&lt;p&gt;&lt;font size="-2"&gt;*nonymous would annoyingly like to point out that it should be "continual integration"&lt;br/&gt;
	**nonymous would annoyingly like to point out that it should be "continual integration", again&lt;br/&gt;
*** are you happy nonymous?&lt;/font&gt;&lt;/p&gt;</description>
      <pubDate>Mon, 11 Feb 2008 20:09:00 GMT</pubDate>
      <guid>http://www.somethingnimble.com/bliki/radiator</guid>
      <author>anonymous z, Dan Manges</author>
    </item>
    <item>
      <title>mixology: the art of mixing and unmixing</title>
      <link>http://www.somethingnimble.com/bliki/mixology</link>
      <description>&lt;h4&gt;what&lt;/h4&gt;
&lt;p&gt;a gem that allows objects to effectively mix and unmix modules&lt;/p&gt;

&lt;h4&gt;who&lt;/h4&gt;
&lt;p&gt;&lt;a href="http://www.klankboomklang.com/"&gt;Pat Farley&lt;/a&gt;, &lt;a href="http://anonymousz.blogspot.com"&gt;anonymous z&lt;/a&gt;, &lt;a href="http://www.dcmanges.com/blog"&gt;Dan Manges&lt;/a&gt;, &lt;a href="http://www.somethingnimble.com/collaborators/clint"&gt;Clint Bishop&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;why&lt;/h4&gt;
&lt;p&gt;modifying an object's behavior by mixing in modules is very useful. thankfully, Ruby gives us this ability out of the box. but sometimes we want to &lt;b&gt;unmix&lt;/b&gt; behavior. however, mixing out a module is a bit clumsy in Ruby.&lt;/p&gt;

&lt;p&gt;enter Mixology.&lt;/p&gt;

&lt;p&gt;let's consider the interface for a door. it's pretty simple. doors basically have two states: open and closed. we knock on doors that are closed so someone will let us in. and if a door is open, we walk right on in.&lt;/p&gt;

&lt;p&gt;
we might model this like so:
&lt;/p&gt;

&lt;pre&gt;
class Door

  def initialize(open = false)
    if open
      extend Open
    else
      extend Closed
    end
    
    def closed?
      kind_of? Closed
    end
    
    def opened?
      kind_of? Open
    end
    
  end
  
  module Closed
    def knock
      puts "knock, knock"
    end

    def open
      extend Open
    end
  end
  
  module Open
    def knock
      raise "cannot knock on an open door, just come on in"
    end
    
    def close
      extend Closed
    end
  end
end
&lt;/pre&gt;

&lt;p&gt;let's write a few tests for our door states.&lt;/p&gt;
&lt;pre&gt;
class DoorTest &lt; Test::Unit::TestCase
  def test_an_open_door_is_opened_and_not_closed
    door = Door.new :open
    assert door.opened?
    assert !door.closed?
  end

  def test_a_closed_door_is_closed_and_not_opened
    door = Door.new
    assert door.closed?
    assert !door.opened?
  end

  def test_closing_an_open_door_makes_the_door_closed_but_not_opened
    door = Door.new :open
    door.close
    assert door.closed?
    assert !door.opened?
  end

  def test_opening_a_closed_door_makes_the_door_opened_but_not_closed
    door = Door.new
    door.open
    assert door.opened?
    assert !door.closed?
  end
end
&lt;/pre&gt;
&lt;p&gt;time to run the tests:&lt;/p&gt;
&lt;pre&gt;
Loaded suite door
Started
..FF
Finished in 0.006623 seconds.

  1) Failure:
test_closing_an_open_door_makes_the_door_closed_but_not_opened(DoorTest) [door.rb:67]:
&lt;false&gt; is not true.

  2) Failure:
test_opening_a_closed_door_makes_the_door_opened_but_not_closed(DoorTest) [door.rb:74]:
&lt;false&gt; is not true.

4 tests, 8 assertions, 2 failures, 0 errors
&lt;/pre&gt;
&lt;p&gt;when we instantiate a door and mixin the opened or closed state, our tests pass.  however, the tests for transitioning between states fail.  when we extend the door instance with the mixin for the new state, the old mixin is still there.  this gives us some undesired behavior. although ruby will use the behavior in the most recently included mixin, this can still be problematic.  we could change this example to work better for these tests, but then we would still have problems transitioning from open to closed and back.&lt;/p&gt;

&lt;p&gt;unfortunately, plain ol' ordinary ruby, or POOR, (Farleyism) does not give us a clean way to implement our state pattern this way. but Mixology does.&lt;/p&gt;

&lt;h4&gt;here's the code using Mixology:&lt;/h4&gt;
&lt;pre&gt;
require "rubygems"
require "mixology"
class Door
  def initialize(open = false)
    @open = open
    if open
      mixin Open
    else
      mixin Closed
    end
  end
  
  module Closed
    ...
    def open
      unmix Closed
      mixin Open
    end
    ...
  end
  
  module Open
    ...
    def close
      unmix Open
      mixin Closed
    end
    ...
  end
end
&lt;/pre&gt;
&lt;p&gt;and now our tests should pass.&lt;/p&gt;
&lt;pre&gt;
Loaded suite door
Started
....
Finished in 0.000793 seconds.

4 tests, 8 assertions, 0 failures, 0 errors
&lt;/pre&gt;
&lt;p&gt;ah, much better.&lt;/p&gt;

&lt;h4&gt;why not just use a more traditional state pattern approach?&lt;/h4&gt;
&lt;p&gt;because it's kind of a pain. essentially, &lt;a href="/bliki/extra/traditional_and_rubyish_state_pattern_impls.rhtml"&gt;traditional, and even non-traditional rubyish, state pattern implementations&lt;/a&gt; are laborious.&lt;/p&gt;

&lt;h4&gt;what else do we use Mixology for?&lt;/h4&gt;
&lt;p&gt;it's also handy for decorating objects that hang around in memory and need undecorating.&lt;/p&gt;

&lt;h4&gt;a word on implementation&lt;/h4&gt;
&lt;p&gt;when we (Clint, Dan, and Nonymous) started implementing mixology, we ran into a few problems with POOR. nonymous called Farley and asked him to take a look at our failing tests. as usual, we had started with failing tests. anyway, Farley had the next day off from work and in one day implemented much of Mixology all by his own self. the rest of us were, of course, busy toiling at our day jobs and contributing to society. so our sincere thanks to you, Farles.
&lt;/p&gt;

&lt;p&gt;oh, and speaking of Farley's hard work, a JRuby implementation is also available.&lt;/p&gt;
&lt;h4&gt;getting mixology&lt;/h4&gt; 

&lt;p&gt;you can get Mixology 10 Proof (the latest version) via &amp;nbsp;&lt;tt&gt;gem install mixology&lt;/tt&gt;&lt;/p&gt;
</description>
      <pubDate>Sat, 08 Sep 2007 10:09:00 GMT</pubDate>
      <guid>http://www.somethingnimble.com/bliki/mixology</guid>
      <author>anonymous z, Dan Manges</author>
    </item>
    <item>
      <title>deepTest. it's time for a quickie.</title>
      <link>http://www.somethingnimble.com/bliki/deep-test</link>
      <description>&lt;p&gt;(initial collaborators: &lt;a href="http://www.dcmanges.com/blog"&gt;Dan Manges&lt;/a&gt;, &lt;a href="http://www.somethingnimble.com/collaborators/zak"&gt;zak&lt;/a&gt;, &lt;a href ="http://www.somethingnimble.com/collaborators/david"&gt;David Vollbracht&lt;/a&gt;)&lt;/p&gt;

&lt;h4&gt;what&lt;/h4&gt;
&lt;p&gt;a gem that allows us to replace Rake::TestTask with DeepTest::TestTask, leveraging &lt;a href="http://www.ruby-doc.org/stdlib/libdoc/rinda/rdoc/index.html"&gt;Rinda&lt;/a&gt; to run tests in multiple processes&lt;/p&gt;

&lt;h4&gt;why&lt;/h4&gt;
&lt;p&gt;with the right hardware (starting with a dual core cpu), it significantly reduces the running time of tests. the more processors, the more significant&lt;/p&gt;

&lt;h4&gt;history&lt;/h4&gt;
&lt;p&gt;like many ideas, this one was born of frustration. our functional tests were getting too slow. for us this meant they had breached the two minute mark. this is simply too long when practicing tdd and checking in often.&lt;/p&gt;

&lt;p&gt;what to do? a colleague predictably repeated his mantra of "fix the longest running test". and though this is a perfectly valid strategy, we had done this last week. and the week before. we wanted a more semi-permanent solution.&lt;/p&gt;

&lt;p&gt;we could make individual tests faster, but we're only going to write more tests. eventually, in serial mode, even the fastest won't be fast enough.&lt;/p&gt;

&lt;p&gt;then Nonymous said "let's throw hardware at this problem".&lt;/p&gt;

&lt;p&gt;later that day, Nonymous and Manges created a simple (read: "hacky") processed-based Rake task that split the test files into groups which were then run in parallel.&lt;/p&gt;

&lt;p&gt;it worked well enough. it cut our functional build time on a two processor machine in half. but then Manges and Vollbracht came up with a much better and cleaner solution. using Rinda. essentially deep_test throws all the tests onto a tuple space.  workers take the tests and write results back. simple.&lt;/p&gt;

&lt;h4&gt;caveats&lt;/h4&gt;

&lt;p&gt;some tests that use ActiveRecord against a MySQL database may throw an ActiveRecord::StatementInvalid exception with a message "Deadlock found when trying to get lock...".  we're not sure why this happens yet. and it happens randomly. but for now, when this occurs, we run the test again.  if it deadlocks a second time, we print out "-deadlock" and skip it.  after a month of using this approach and over 1,500 check-ins, we haven't had a single broken build due to skipping a test that has deadlocked. also, our cruise build runs tests serialially so this is not an issue for our CI environment&lt;/p&gt;

&lt;h4&gt;sayonara fixtures&lt;/h4&gt;

&lt;p&gt;because the tests run in separate processes, each processes establishes a separate database connection.  because Rails tests run in transactions, this is fine.  a test can insert records into the database, and a test running in another process cannot see that data.  however, if you're using fixtures you won't be able to take advantage of deeptest to run your tests twice as fast.  data from fixtures is loaded outside the transaction. therefore, loading fixtures in one process will mess up tests running in another.  if you want to get rid of fixtures, consider &lt;a href="http://www.dcmanges.com/blog/38"&gt;using a factory&lt;/a&gt; instead&lt;/p&gt;

&lt;h4&gt;getting started&lt;/h4&gt; 

&lt;p&gt;it won't take long (unless you need to remove fixtures)&lt;/p&gt;

&lt;p&gt;&lt;tt&gt;gem install deep_test&lt;/tt&gt;&lt;/p&gt;

&lt;p&gt;In your Rakefile:&lt;/p&gt;
&lt;pre&gt;
  require "rubygems"
  require "deep_test/rake_tasks"

  # sample DeepTest task
  DeepTest::TestTask.new "task_name" do |t|
    t.pattern = "test/**/*_test.rb"
    t.processes = 2 # optional, defaults to 2
  end
&lt;/pre&gt;
</description>
      <pubDate>Thu, 06 Sep 2007 06:09:00 GMT</pubDate>
      <guid>http://www.somethingnimble.com/bliki/deep-test</guid>
      <author>anonymous z, Dan Manges</author>
    </item>
    <item>
      <title>Rome wasn't built in a day....</title>
      <link>http://www.somethingnimble.com/bliki/hello-world</link>
      <description>&lt;p&gt;neither was its website.&lt;/p&gt;
</description>
      <pubDate>Fri, 24 Aug 2007 22:42:15 GMT</pubDate>
      <guid>http://www.somethingnimble.com/bliki/hello-world</guid>
      <author>anonymous z, Dan Manges</author>
    </item>
  <feedburner:awareness xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://api.feedburner.com/awareness/1.0/GetFeedData?uri=somethingnimble</feedburner:awareness></channel>
</rss>
