


<?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>CantRemembrances &#187; bdd</title>
	<atom:link href="http://blog.cantremember.com/tag/bdd/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.cantremember.com</link>
	<description>Memes of a technical vein discovered during CantRemember.com implementation</description>
	<lastBuildDate>Tue, 16 Feb 2010 06:36:02 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Twitter4R shifts RSpec onto my Front Burner</title>
		<link>http://blog.cantremember.com/twitter4r-shifts-rspec-onto-my-front-burner/</link>
		<comments>http://blog.cantremember.com/twitter4r-shifts-rspec-onto-my-front-burner/#comments</comments>
		<pubDate>Thu, 05 Feb 2009 09:00:33 +0000</pubDate>
		<dc:creator>dfoley</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[bdd]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://blog.cantremember.com/?p=94</guid>
		<description><![CDATA[As usual, my day did not pan out as expected.  But, also as usual, I learned a lot!
Coming Up To Speed on Rspec
So, learning rspec has been on my list for a while.  I finally got around to it.  Nice framework.  I am familiar with EasyMock, and am aware of JMock. [...]]]></description>
			<content:encoded><![CDATA[<p>As usual, my day did not pan out as expected.  But, also as usual, I learned a lot!</p>
<h3>Coming Up To Speed on Rspec</h3>
<p>So, learning <a href="http://rspec.info/"><strong>rspec</strong></a> has been on my list for a while.  I finally got around to it.  Nice framework.  I am familiar with <a href="http://www.easymock.org/">EasyMock</a>, and am aware of <a href="http://www.jmock.org/">JMock</a>.  I never had an opportunity to get into <a href="http://code.google.com/p/mockito/">Mockito</a>, but I&#8217;d give it a glance next time I put on my Java hat.</p>
<p>There is some decent documentation on it out there.  I found these links particularly helpful:</p>
<ul>
<li>The <a href="http://rspec.info/documentation/">formal documentation</a>.</li>
<li>David Chelimsky&#8217;s <a href="http://blog.davidchelimsky.net/articles/2007/05/14/an-introduction-to-rspec-part-i">from-the-ground-up description</a></li>
<li>rspec.info&#8217;s drill-down into <a href="http://rspec.info/documentation/mocks/">Mocks and Stubs</a></li>
<li>Luke Redpath&#8217;s cross-over into <a href="http://www.lukeredpath.co.uk/blog/developing-a-rails-model-using-bdd-and-rspec-part-1.html">usage under Rails</a></li>
</ul>
<p>During my ramping-up, I took the <a href="http://blog.cantremember.com/learning-ruby-through-assertions-and-podcasts/">usual meta-approach</a> of creating a test suite &#8212; and <em>yaaay</em>, that&#8217;s what <code>rspec</code> is meant for! &#8212; which I then used to test out its own range of capabilities.  The <a href="http://rspec.rubyforge.org/rspec/1.1.12/">Modules in the rdoc</a> which I&#8217;ve found to provide the most value are:</p>
<ul>
<li><strong>Spec::Expectations::ObjectExpectations</strong> for conditionals (eg. <code>should</code> &#038; <code>should_not</code>)</li>
<li><strong>Spec::Matchers</strong> for expectations (eg. <code>equal(<em>value</em>)</code>, <code>be_a(<em>class</em>)</code>, <code>respond_to(<em>method_sym</em>)</code>, <code>raise_error</code>)</li>
<li><strong>Spec::Mocks::Methods</strong> for mock method definition (eg. <code>should_receive(<em>method_sym</em>)</code>)</li>
<li><strong>Spec::Mocks::MessageExpectation</strong> for mock behaviour (eg. <code>with(<em>*args</em>)</code>, <code>once</code>, <code>exactly(<em>n</em>).times</code>, <code>any_number_of_times</code>)</li>
<li><strong>Spec::Mocks::ArgumentConstraints</strong> for mock arguments (eg. <code>an_instance_of(<em>class</em>)</code>, <code>anything</code>)</li>
<li><strong>Spec::Mocks::BaseExpectation</strong> for mock responses (eg. <code>and_return(<em>value</em>)</code>, <code>and_yield(<em>&#038;block</em>)</code>)</li>
</ul>
<p>I won&#8217;t got into the deep details, but here are some examples of conditionals and expectations that I paraphrased into my meta-test:</p>
<div class="pre_wrap">
<pre><code>	specify "knowledge of nil" do
		''.should_not be_nil
	end

	specify "numeric calculations" do
		(355.0 / 113).should be_close(Math::PI, 0.1)
	end

	specify "changes made by a closure" do
		array = []
		lambda {
			array << :a
		}.should change(array, :size)
	end

	specify "equality" do
		5.should eql 5
		5.should equal 5
		[:a].should_not equal [:a]
	end

	specify "raising of errors" do
		#	always construct fresh!!!
		#		otherwise it won't be re-wrappable
		def raiser(s=nil)
			lambda { raise(RuntimeError, s) if s }
		end

		raiser('x').should raise_error
		raiser('y').should raise_error(RuntimeError, 'y')
	end

	specify "closure satisfaction" do
		5.should satisfy {|n| (4..6).include?(n) }
	end

	specify "what lists do" do
		[].should respond_to(:each, :find, :size)
	end</code></code></pre>
</div>
<p>And here&#8217;s a little bit of silly mocking:</p>
<div class="pre_wrap">
<pre><code>	def expect_raise(type=Spec::Mocks::MockExpectationError, &#038;block)
		abort 'block must be provided' unless block_given?
		block.should raise_error(type)
	end

	specify "the basics" do
		@mock.should_receive :hello
		@mock.should_not_receive :goodbye

		@mock.hello
		expect_raise { @mock.stay }
		expect_raise { @mock.goodbye }
	end

	specify "how many times, and with what" do
		@mock.should_receive(:one).once.with(1)
		@mock.one 1

		@mock.should_receive(:string).exactly(1).times.with(an_instance_of(String))
		@mock.string 'a string'

		@mock.should_receive(:anything).exactly(3).times.with(any_args())
		@mock.anything
		@mock.anything :again
		@mock.anything :third, 'time'

		@mock.should_receive(:array_ish).with(duck_type(:each, :find, :size))
		@mock.array_ish [:item]
	end

	specify "what i return, raise or throw" do
		@mock.should_receive(:get_one).and_return(1)
		@mock.should_receive(:put_one).with(1)
		@mock.put_one @mock.get_one

		@mock.should_receive(:increment).any_number_of_times.with(instance_of(Fixnum)).and_return {|i| i + 1 }
		@mock.increment(1).should equal(2)

		@mock.should_receive(:raises_string).and_raise('something runtime')
		expect_raise(RuntimeError) { @mock.raises_string }

		@mock.should_receive(:pitch).and_throw(:ball)
		lambda { @mock.pitch }.should throw_symbol(:ball)
	end

	specify "yielding in a complex fashion" do
		@mock.should_receive(:gimmee).exactly(3).times.and_yield(:x)

		holder = []
		@mock.gimmee {|value| holder << value }
		holder.should eql([:x])
		2.times { @mock.gimmee {|value| holder << value } }
		holder.should eql([:x, :x, :x])
	end

	specify "validation via closure" do
		(@mock.should_receive(:threely) do |value|
			value.to_s.size.should eql(3)
		end).exactly(3).times

		@mock.threely 'x' * 3
		@mock.threely :key
		@mock.threely 333
	end</code></code></pre>
</div>
<p>These are just ways I thought of to exercise the width and breadth of the library.  Very nice.  I hope that these are useful examples for people new to this gem.</p>
<p>I recommend the other references from above for filling in the missing details.  Once you have a <code>context / specify</code> or a <code>describe / it</code> specification set up, you&#8217;ll be good to go.  There&#8217;s much more to the library &#8212; Stories, for instance &#8212; but that&#8217;s <a href="http://blog.emson.co.uk/2008/06/understanding-rspec-stories-a-tutorial/">for another day</a>.</p>
<h3>An Informative Walk through Twitter4R</h3>
<p>No, I didn&#8217;t really <em>want</em> to spend time learning <code>rspec</code> &#8212; I mean heck, I&#8217;m busy &#8212; but I had a personal need to expand the <a href="http://twitter4r.rubyforge.org/"><strong>Twitter4R</strong></a> gem.  Specifically, I wanted to add on some <a href="http://apiwiki.twitter.com/Search+API+Documentation">Twitter search</a> features, and I was very impressed with how this library has been built.  Contribution-wise, the final step that <a href="http://susanpotter.net/">Susan Potter</a> recommends is to craft up some rspec tests.</p>
<p>Of course, mock testing is only as good as the framework you&#8217;re built upon.  The assumption is that <code>Net::HTTP</code> is going to do it&#8217;s job, so mock it up and you can even test your Twitter features offline.  When I built <a href="http://wiki.cantremember.com/Bitly4R"><strong>Bitly4R</strong></a> (given that name, my thinking has clearly been <em>influenced</em>), I did everything as full-on functional tests.  It was easy; <a href="http://bit.ly/">bit.ly</a> has both <code>shorten</code> and <code>expand</code> commands, so I could reverse-test real values without having any fixed expectations.</p>
<p>However, Twitter is <a href="http://twitter.com/public_timeline">live</a> and user-generated, so who knows <em>what</em> you&#8217;ll find.  Mocking covers that for you.  And of course not having to hit the service itself shortest testing time dramatically.</p>
<p>Here&#8217;s one of my tests, again foreshortened:</p>
<div class="pre_wrap">
<pre><code>	before(:each) do
		Twitter::Client.send :public, :create_http_get_request

		@client = Twitter::Client.new
		@client_clone = Twitter::Client.new
	end

	it "produces a querystring with all the crazy stuff Twitter imagined" do
		the_params = nil

		@client.should_receive(:create_http_get_request).and_return {|uri, params|
			the_params = params
			@client_clone.create_http_get_request(uri, params)
		}
		@client.should_receive(:http_connect).and_return Net::HTTPNotFound.mock(:code => '404')

		#	pass through a few we can pick back out
		#	also, side-effect ... nil on invalid response
		@client.search('query_value', :rpp => 3).should be_nil

		the_params.should_not be_nil
		the_params[:q].should eql('query_value')
		the_params[:rpp].should eql(3)
	end</code></code></pre>
</div>
<p>Plus a little mocking of <code>Net::HTTPResponse</code>:</p>
<div class="pre_wrap">
<pre><code>class Net::HTTPResponse
	def self.mock(ops={})
		#	defaults
		ops = {
			:http_version => '1.1',
			:code => '200',
			:message => 'OK',
			:body => nil,
		}.merge(ops || {})

		#	construct
		###clazz = CODE_TO_OBJ[ops[:code]]
		clazz = self
		response = clazz.new(ops[:http_version], ops[:code], ops[:message])

		#	inject
		ops.each do |k, v|
			response.instance_variable_set "@#{k}".to_sym, v
		end

		#	mockulate
		response.instance_eval %q{
			def body; @body; end
		}

		response
	end
end</code></code></pre>
</div>
<p>Nothing like having some good inspiration to get you thinking about maintainability.  I&#8217;m a not a strong adherent to any of the <a href="http://en.wikipedia.org/wiki/Test-driven_development">TDD</a> or <a href="http://en.wikipedia.org/wiki/Behavior_driven_development">BDD</a> denominations, but testability itself is close to my heart.  Just ask the folks who&#8217;ll be looking at the micro-assertion Module that I wrote for my <a href="http://www.facebook.com/jobs_puzzles/">Facebook Puzzle</a> submissions (which work locally under test conditions but fail <em>miserably</em> once thrown over their wall).  Then again, I won&#8217;t need to write that (and test that) from scratch again.</p>
<p>So, back to talking glowingly about the <code>Twitter4R</code> architecture.  Yes, I used <strong>that</strong> word.  Yet regardless of that term&#8217;s heavyweightedness, it&#8217;s simply the result of carefully thinking out the formalization of a complex design.  And once a non-author delves into extending an existing implementation, that impl&#8217;s demeanor becomes readily clear :)</p>
<p>Some of the interesting things I saw:</p>
<ul>
<li>An inner <code>bless</code>-ish strategy, to inject the <code>Twitter::Client</code> into instanciated result classes.  I&#8217;ve seen blessing as an OO-Perl-ism, for self-ication, and that metaphor carries over very nicely to this context.</li>
<li>Generous use of blocks / lambdas / closures in methods, for contextual iteration (eg. iterate through each <code>Twitter::Message</code> in a <code>timeline</code> response).  Unnecessary, but an excellent convenience for a language that offers that optional capability in a very disposable fashion (from the caller&#8217;s perspective).</li>
<li>Retroactive sub-object population after construction.  <code>Twitter4R</code> relies upon the <a href="http://json.rubyforge.org/">json</a> gem, which deals primarily in Hashes.  Post-injection, the library itereates through Arrays of Hashes and transforms them into suitable <code>Twiltter::User</code> containers, etc.  A great place to put such logic in the construction chain, and it doesn&#8217;t take long to get really tired of Hash hierarchies.</li>
</ul>
<p>Good stuff, and learning with in a Ruby-centric mindset was invaluable for me.  We all have to start somewhere, eh.</p>
<h3>The Acute Long-Term Pain of Staticness</h3>
<p>There was one issue that I ran into; <em>static configuration</em>.  During my years of using the <a href="http://www.springsource.org/">Spring Framework</a>, my <a href="http://en.wikipedia.org/wiki/Inversion_of_Control">IOC</a>-addled brain started thinking of everything in terms of instances &#8212; Factory Beans, POJOs, Observers &#038; Listeners, Chain-of-Responsibility wrappers.  Static configuration is a common metaphor, and in this case, there&#8217;s a static <code>Twitter::Config</code> instance.  Convenient and centralized.  Makes perfect sense.</p>
<p>I mean, the fact that it was a configurable library <em>at all</em> was awesome.  I was able to easily set up a <code>Twitter::Client</code> to reference <a href="http://search.twitter.com">search.twitter.com</a>.  However, of course as soon as I did that, I whacked the ability for clients to talk to <code>twitter.com</code> in the process.  <em>Oops!</em></p>
<p>On GPs, I refused to modify the original code.  And I wanted to make sure that my superficial tweaks to the library would be thread-safe &#8212; temporarily swaping out the global <code>Twitter::Config</code> in mid-operation would be an issue.  Using <code>Mutex.synchronize</code> seemed like the perfect choice.  After finding that the same thread can&#8217;t lock a <code>Mutex</code> instance twice &#8212; grr!, that&#8217;s a great trick if you can work it &#8212; I overrode the one method that cared the most about <code>@@config</code>:</p>
<div class="pre_wrap">
<pre><code>	@@config_mutex = Mutex.new
	def configuration_mutex
		@@config_mutex
	end

	alias :raw_http_connect :http_connect
	def <strong>http_connect</strong>(*args, &#038;block)
		ops = (Hash === args.last) ? args.pop : {}

		result = nil
		self.configuration_mutex.synchronize do
			ops[:call_before].call if ops[:call_before]
			result = raw_http_connect *args, &#038;block
			ops[:call_after].call if ops[:call_after]
		end

		result
	end

	#
	#	...
	#

	@@SEARCH_CONNECT_HOOKS = {
		:call_before => lambda { self.configure_apply(:search) },
		:call_after => lambda { self.configure_apply(:default) },
	}

	#
	#	...
	#

	#	broken out of closure for mocking
	req = create_http_get_request(uri, params)
	response = http_connect(@@SEARCH_CONNECT_HOOKS) {|conn|	req }
	return nil unless Net::HTTPOK === response

	model = bless_model(Twitter::Search.unmarshal(response.body))</code></code></pre>
</div>
<p>It works like a charm.  Please, everyone just line up to tell me how I could have done it better.  And I don&#8217;t mean <em>quicker</em> or <em>cheaper</em>, I mean better.  Believe me, I would not have sunk the time into this end-around approach, if not for the fact that:</p>
<ol>
<li>I don&#8217;t want to maintain a local gem code modification (even though my impl is closely coupled to the gem impl already)</li>
<li>I intend to follow that practice, so every opportunity to pull and end-around is a Valuable Learning Experience.</li>
</ol>
<p>So, now my local <code>Twitter4R</code> has search capability gracefully latched onto it (and implemented much in the flavor of the library itself).  I have a mass of <code>rspec</code> examples to work off in the future.</p>
<p>Now, I haven&#8217;t spent a great amount of time testing the thread-safeness &#8212; no one in their right mind <em>wants</em> to do that &#8212; but my sundry <code>Twitter::Client</code> instances play nicely together in between searches and normal status operations.</p>
<p>And I had something useful to blog about!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.cantremember.com/twitter4r-shifts-rspec-onto-my-front-burner/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
