<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.floehopper.org/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en-US">
  <title>Floehopper</title>
  <subtitle type="html">thoughts on the bergy bits of life</subtitle>
  <id>tag:blog.floehopper.org,2005:Typo</id>
  <generator uri="http://www.typosphere.org" version="4.0">Typo</generator>
  
  <link href="http://blog.floehopper.org/" rel="alternate" type="text/html" />
  <updated>2010-08-24T13:03:01+00:00</updated>
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.floehopper.org/floehopper-blog" /><feedburner:info uri="floehopper-blog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
    <author>
      <name>James Mead</name>
    </author>
    <id>urn:uuid:865a65c7-638c-4751-aea6-f2b2e5e9d554</id>
    <published>2010-08-19T21:23:00+00:00</published>
    <updated>2010-08-24T13:03:01+00:00</updated>
    <title type="html">Ruby Acceptance Testing</title>
    <link href="http://feeds.floehopper.org/~r/floehopper-blog/~3/fVKQiY3sy34/ruby-acceptance-testing" rel="alternate" type="text/html" />
    <category term="cucumber" scheme="http://blog.floehopper.org/articles/tag/cucumber" />
    <category term="gherkin" scheme="http://blog.floehopper.org/articles/tag/gherkin" />
    <category term="acceptance" scheme="http://blog.floehopper.org/articles/tag/acceptance" />
    <category term="testing" scheme="http://blog.floehopper.org/articles/tag/testing" />
    <category term="natural" scheme="http://blog.floehopper.org/articles/tag/natural" />
    <category term="language" scheme="http://blog.floehopper.org/articles/tag/language" />
    <category term="abstraction" scheme="http://blog.floehopper.org/articles/tag/abstraction" />
    <category term="readability" scheme="http://blog.floehopper.org/articles/tag/readability" />
    <summary type="html">&lt;p&gt;In his recent article &lt;a href="http://elabs.se/blog/15-you-re-cuking-it-wrong"&gt;You&amp;#8217;re Cuking It Wrong&lt;/a&gt;, Jonas Nicklas compares the following scenario which was submitted in a &lt;a href="http://cukes.info/"&gt;Cucumber&lt;/a&gt; issue :-&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;Scenario: Adding a subpage
  Given I am logged in
  Given a microsite with a Home page
  When I click the Add Subpage button
  And I fill in &amp;quot;Gallery&amp;quot; for &amp;quot;Title&amp;quot; within &amp;quot;#document_form_container&amp;quot;
  And I press &amp;quot;Ok&amp;quot; within &amp;quot;.ui-dialog-buttonpane&amp;quot;
  Then I should see /Gallery/ within &amp;quot;#documents&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;With an improved version which he has written :-&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;Scenario: Adding a subpage
  Given I am logged in
  Given a microsite with a home page
  When I press &amp;quot;Add subpage&amp;quot;
  And I fill in &amp;quot;Title&amp;quot; with &amp;quot;Gallery&amp;quot;
  And I press &amp;quot;Ok&amp;quot;
  Then I should see a document called &amp;quot;Gallery&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;h3&gt;Levels of Abstraction&lt;/h3&gt;


	&lt;p&gt;Jonas says :-&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;there&amp;#8217;s one crucial difference: the first feature is code, the second isn&amp;#8217;t&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;Although I see what Jonas is getting at, neither of them are actually Ruby code &amp;#8211; both are written in Cucumber&amp;#8217;s &lt;a href="http://wiki.github.com/aslakhellesoy/cucumber/gherkin"&gt;Gherkin&lt;/a&gt; DSL. The key difference is really the level of abstraction &amp;#8211; the first version has a test that is less abstracted from the implementation than the second version. As Jonas correctly points out, the test in the second version is consequently more readable and is less coupled to the underlying implementation.&lt;/p&gt;


	&lt;h3&gt;Readability&lt;/h3&gt;


	&lt;p&gt;Jonas also says :-&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;The argument against cucumber that&amp;#8217;s often presented is that as a programmer, plain text is unnecessary, because we can all read code.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;However, it&amp;#8217;s a mistake to think that making a test readable &lt;em&gt;necessarily&lt;/em&gt; means that it has to be written in a &lt;a href="http://en.wikipedia.org/wiki/Natural_language"&gt;natural language&lt;/a&gt;. We could equally well write something like this :-&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;scenario&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;adding a subpage&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;
  &lt;span class="ident"&gt;given&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;
    &lt;span class="ident"&gt;i_am_logged_in&lt;/span&gt;
    &lt;span class="ident"&gt;a_microsite_with_a_home_page&lt;/span&gt;
  &lt;span class="punct"&gt;}&lt;/span&gt;
  &lt;span class="keyword"&gt;when&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;
    &lt;span class="ident"&gt;i_press&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Add subpage&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="ident"&gt;i_fill_in&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Title&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt;&lt;span class="symbol"&gt;:with=&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Gallery&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="ident"&gt;i_press&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Ok&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="punct"&gt;}&lt;/span&gt;
  &lt;span class="keyword"&gt;then&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;
    &lt;span class="ident"&gt;i_should_see_a_document_called&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Gallery&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span class="punct"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;While I would agree that my version isn&amp;#8217;t as pretty as Jonas&amp;#8217; version, I&amp;#8217;d suggest it&amp;#8217;s almost as &lt;em&gt;readable&lt;/em&gt;. The difference being this is all valid Ruby code. I once saw someone (&lt;a href="http://www.natpryce.com/"&gt;Nat Pryce&lt;/a&gt; or &lt;a href="http://www.m3p.co.uk/"&gt;Steve Freeman&lt;/a&gt;, I think) do a neat trick where they changed the syntax highlighting in an editor to make some characters invisible and as a result made the code more readable. We could probably do something similar to make braces, underscores, etc invisible, and end up with something as good as Jonas&amp;#8217; version :-&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;scenario &amp;quot;adding a subpage&amp;quot;
  given
    i am logged in
    a microsite with a home page

  when 
    i press &amp;quot;Add subpage&amp;quot;
    i fill in &amp;quot;Title&amp;quot;  with  &amp;quot;Gallery&amp;quot;
    i press &amp;quot;Ok&amp;quot;

  then 
    i should see a document called &amp;quot;Gallery&amp;quot;
  &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;h3&gt;Overhead&lt;/h3&gt;


	&lt;p&gt;It seems obvious to me that Cucumber adds an overhead in writing tests. It requires me to use regular expressions to convert natural language into code. While I recognise that the overhead is often small, it does still exist and I&amp;#8217;ve definitely spent time debugging this aspect of tests. Given that I think it&amp;#8217;s possible to write nicely abstracted readable tests in Ruby, it&amp;#8217;s not obvious to me that the overhead of using Cucumber is worthwhile.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;m going to try and find the time to look at frameworks like &lt;a href="http://github.com/elight/coulda"&gt;Coulda&lt;/a&gt; and &lt;a href="http://github.com/cavalle/steak"&gt;Steak&lt;/a&gt; which seem to be more in line with my favoured approach.&lt;/p&gt;


	&lt;h4&gt;Update&lt;/h4&gt;


	&lt;p&gt;I thought it might be useful to include a quote from and a link to James Shore&amp;#8217;s article on &lt;a href="http://jamesshore.com/Blog/The-Problems-With-Acceptance-Testing.html"&gt;The Problems of Acceptance Testing&lt;/a&gt;&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;My experience with Fit and other agile acceptance testing tools is that they cost more than they&amp;#8217;re worth. There&amp;#8217;s a lot of value in getting concrete examples from real customers and business experts; not so much value in using &amp;#8220;natural language&amp;#8221; tools like Fit and similar.&lt;/p&gt;
	&lt;/blockquote&gt;</summary>
    <content type="html">&lt;p&gt;In his recent article &lt;a href="http://elabs.se/blog/15-you-re-cuking-it-wrong"&gt;You&amp;#8217;re Cuking It Wrong&lt;/a&gt;, Jonas Nicklas compares the following scenario which was submitted in a &lt;a href="http://cukes.info/"&gt;Cucumber&lt;/a&gt; issue :-&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;Scenario: Adding a subpage
  Given I am logged in
  Given a microsite with a Home page
  When I click the Add Subpage button
  And I fill in &amp;quot;Gallery&amp;quot; for &amp;quot;Title&amp;quot; within &amp;quot;#document_form_container&amp;quot;
  And I press &amp;quot;Ok&amp;quot; within &amp;quot;.ui-dialog-buttonpane&amp;quot;
  Then I should see /Gallery/ within &amp;quot;#documents&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;With an improved version which he has written :-&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;Scenario: Adding a subpage
  Given I am logged in
  Given a microsite with a home page
  When I press &amp;quot;Add subpage&amp;quot;
  And I fill in &amp;quot;Title&amp;quot; with &amp;quot;Gallery&amp;quot;
  And I press &amp;quot;Ok&amp;quot;
  Then I should see a document called &amp;quot;Gallery&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;h3&gt;Levels of Abstraction&lt;/h3&gt;


	&lt;p&gt;Jonas says :-&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;there&amp;#8217;s one crucial difference: the first feature is code, the second isn&amp;#8217;t&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;Although I see what Jonas is getting at, neither of them are actually Ruby code &amp;#8211; both are written in Cucumber&amp;#8217;s &lt;a href="http://wiki.github.com/aslakhellesoy/cucumber/gherkin"&gt;Gherkin&lt;/a&gt; DSL. The key difference is really the level of abstraction &amp;#8211; the first version has a test that is less abstracted from the implementation than the second version. As Jonas correctly points out, the test in the second version is consequently more readable and is less coupled to the underlying implementation.&lt;/p&gt;


	&lt;h3&gt;Readability&lt;/h3&gt;


	&lt;p&gt;Jonas also says :-&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;The argument against cucumber that&amp;#8217;s often presented is that as a programmer, plain text is unnecessary, because we can all read code.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;However, it&amp;#8217;s a mistake to think that making a test readable &lt;em&gt;necessarily&lt;/em&gt; means that it has to be written in a &lt;a href="http://en.wikipedia.org/wiki/Natural_language"&gt;natural language&lt;/a&gt;. We could equally well write something like this :-&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;scenario&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;adding a subpage&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;
  &lt;span class="ident"&gt;given&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;
    &lt;span class="ident"&gt;i_am_logged_in&lt;/span&gt;
    &lt;span class="ident"&gt;a_microsite_with_a_home_page&lt;/span&gt;
  &lt;span class="punct"&gt;}&lt;/span&gt;
  &lt;span class="keyword"&gt;when&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;
    &lt;span class="ident"&gt;i_press&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Add subpage&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="ident"&gt;i_fill_in&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Title&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt;&lt;span class="symbol"&gt;:with=&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Gallery&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="ident"&gt;i_press&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Ok&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="punct"&gt;}&lt;/span&gt;
  &lt;span class="keyword"&gt;then&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;
    &lt;span class="ident"&gt;i_should_see_a_document_called&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Gallery&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span class="punct"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;While I would agree that my version isn&amp;#8217;t as pretty as Jonas&amp;#8217; version, I&amp;#8217;d suggest it&amp;#8217;s almost as &lt;em&gt;readable&lt;/em&gt;. The difference being this is all valid Ruby code. I once saw someone (&lt;a href="http://www.natpryce.com/"&gt;Nat Pryce&lt;/a&gt; or &lt;a href="http://www.m3p.co.uk/"&gt;Steve Freeman&lt;/a&gt;, I think) do a neat trick where they changed the syntax highlighting in an editor to make some characters invisible and as a result made the code more readable. We could probably do something similar to make braces, underscores, etc invisible, and end up with something as good as Jonas&amp;#8217; version :-&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;scenario &amp;quot;adding a subpage&amp;quot;
  given
    i am logged in
    a microsite with a home page

  when 
    i press &amp;quot;Add subpage&amp;quot;
    i fill in &amp;quot;Title&amp;quot;  with  &amp;quot;Gallery&amp;quot;
    i press &amp;quot;Ok&amp;quot;

  then 
    i should see a document called &amp;quot;Gallery&amp;quot;
  &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;h3&gt;Overhead&lt;/h3&gt;


	&lt;p&gt;It seems obvious to me that Cucumber adds an overhead in writing tests. It requires me to use regular expressions to convert natural language into code. While I recognise that the overhead is often small, it does still exist and I&amp;#8217;ve definitely spent time debugging this aspect of tests. Given that I think it&amp;#8217;s possible to write nicely abstracted readable tests in Ruby, it&amp;#8217;s not obvious to me that the overhead of using Cucumber is worthwhile.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;m going to try and find the time to look at frameworks like &lt;a href="http://github.com/elight/coulda"&gt;Coulda&lt;/a&gt; and &lt;a href="http://github.com/cavalle/steak"&gt;Steak&lt;/a&gt; which seem to be more in line with my favoured approach.&lt;/p&gt;


	&lt;h4&gt;Update&lt;/h4&gt;


	&lt;p&gt;I thought it might be useful to include a quote from and a link to James Shore&amp;#8217;s article on &lt;a href="http://jamesshore.com/Blog/The-Problems-With-Acceptance-Testing.html"&gt;The Problems of Acceptance Testing&lt;/a&gt;&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;My experience with Fit and other agile acceptance testing tools is that they cost more than they&amp;#8217;re worth. There&amp;#8217;s a lot of value in getting concrete examples from real customers and business experts; not so much value in using &amp;#8220;natural language&amp;#8221; tools like Fit and similar.&lt;/p&gt;
	&lt;/blockquote&gt;&lt;img src="http://feeds.feedburner.com/~r/floehopper-blog/~4/fVKQiY3sy34" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://blog.floehopper.org/articles/2010/08/19/ruby-acceptance-testing</feedburner:origLink></entry>
  <entry>
    <author>
      <name>James Mead</name>
    </author>
    <id>urn:uuid:727f29a0-185e-4f65-8c4a-263aa1d1acf7</id>
    <published>2010-01-25T20:33:49+00:00</published>
    <updated>2010-01-25T20:37:02+00:00</updated>
    <title type="html">Converting S5 slides to a single PDF on Mac OSX</title>
    <link href="http://feeds.floehopper.org/~r/floehopper-blog/~3/Zdgrd-DHX9o/converting-s5-slides-to-a-single-pdf-on-mac-osx" rel="alternate" type="text/html" />
    <category term="s5" scheme="http://blog.floehopper.org/articles/tag/s5" />
    <category term="slide" scheme="http://blog.floehopper.org/articles/tag/slide" />
    <category term="pdf" scheme="http://blog.floehopper.org/articles/tag/pdf" />
    <category term="mac" scheme="http://blog.floehopper.org/articles/tag/mac" />
    <category term="osx" scheme="http://blog.floehopper.org/articles/tag/osx" />
    <category term="automator" scheme="http://blog.floehopper.org/articles/tag/automator" />
    <category term="webkit" scheme="http://blog.floehopper.org/articles/tag/webkit" />
    <category term="png" scheme="http://blog.floehopper.org/articles/tag/png" />
    <summary type="html">&lt;p&gt;I used &lt;a href="http://meyerweb.com/eric/tools/s5/"&gt;S5&lt;/a&gt; in combination with &lt;a href="http://webby.rubyforge.org/"&gt;Webby&lt;/a&gt; for my &lt;a href="/presentations/ruby-and-cocoa-ruby-manor-2009-12-14/"&gt;Ruby &amp;#38; Cocoa presentation&lt;/a&gt; at &lt;a href="http://rubymanor.org/harder/"&gt;RubyManor&lt;/a&gt;. I hate PowerPoint with a passion and haven&amp;#8217;t done enough presentations to be bothered to learn KeyNote. So I was much happier generating my slides from a plain text file marked up in &lt;a href="http://redcloth.org/textile"&gt;Textile&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;However, like &lt;a href="http://po-ru.com/diary/how-to-convert-an-s5-presentation-to-images/"&gt;Paul Battley&lt;/a&gt;, I found that S5 doesn&amp;#8217;t work so well when someone wants to take those slides and put them in a video. Anyway, I&amp;#8217;ve managed to convert my S5 slides into a single &lt;span class="caps"&gt;PDF&lt;/span&gt; using a combination of &lt;a href="http://www.paulhammond.org/webkit2png/"&gt;&lt;code&gt;webkit2png&lt;/code&gt;&lt;/a&gt; and a custom &lt;a href="http://www.apple.com/macosx/what-is-macosx/apps-and-utilities.html#automator"&gt;Automator&lt;/a&gt; workflow :-&lt;/p&gt;


	&lt;h3&gt;Ruby Script using &lt;code&gt;webkit2png&lt;/code&gt;&lt;/h3&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="comment"&gt;#!/usr/bin/env ruby&lt;/span&gt;

&lt;span class="constant"&gt;NUMBER_OF_SLIDES&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="number"&gt;94&lt;/span&gt;
&lt;span class="constant"&gt;SEQUENCE_FORMAT&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;%0&lt;span class="expr"&gt;#{Math.log10(NUMBER_OF_SLIDES).to_i}&lt;/span&gt;d&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="constant"&gt;HOST&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;jamesmead.local&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="constant"&gt;PATH&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;/presentations/ruby-and-cocoa-ruby-manor-2009-12-14/&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="constant"&gt;BASE_URL&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;http://&lt;span class="expr"&gt;#{HOST}#{PATH}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;...&lt;/span&gt;&lt;span class="constant"&gt;NUMBER_OF_SLIDES&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;index&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
  &lt;span class="ident"&gt;anchor&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;#slide&lt;span class="expr"&gt;#{index}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="ident"&gt;url&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;span class="expr"&gt;#{BASE_URL}#{anchor}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="ident"&gt;sequence&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;SEQUENCE_FORMAT&lt;/span&gt; &lt;span class="punct"&gt;%&lt;/span&gt; &lt;span class="ident"&gt;index&lt;/span&gt;
  &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;%x[&lt;/span&gt;&lt;span class="string"&gt;webkit2png --fullsize --filename=slide-&lt;span class="expr"&gt;#{sequence}&lt;/span&gt; &lt;span class="expr"&gt;#{url}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
  &lt;span class="keyword"&gt;raise&lt;/span&gt; &lt;span class="keyword"&gt;unless&lt;/span&gt; &lt;span class="global"&gt;$?&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;success?&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;h3&gt;Custom Automator Workflow&lt;/h3&gt;


	&lt;p&gt;&lt;img src="http://farm3.static.flickr.com/2695/4304744036_21d9db8986.jpg" alt="" /&gt;&lt;/p&gt;</summary>
    <content type="html">&lt;p&gt;I used &lt;a href="http://meyerweb.com/eric/tools/s5/"&gt;S5&lt;/a&gt; in combination with &lt;a href="http://webby.rubyforge.org/"&gt;Webby&lt;/a&gt; for my &lt;a href="/presentations/ruby-and-cocoa-ruby-manor-2009-12-14/"&gt;Ruby &amp;#38; Cocoa presentation&lt;/a&gt; at &lt;a href="http://rubymanor.org/harder/"&gt;RubyManor&lt;/a&gt;. I hate PowerPoint with a passion and haven&amp;#8217;t done enough presentations to be bothered to learn KeyNote. So I was much happier generating my slides from a plain text file marked up in &lt;a href="http://redcloth.org/textile"&gt;Textile&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;However, like &lt;a href="http://po-ru.com/diary/how-to-convert-an-s5-presentation-to-images/"&gt;Paul Battley&lt;/a&gt;, I found that S5 doesn&amp;#8217;t work so well when someone wants to take those slides and put them in a video. Anyway, I&amp;#8217;ve managed to convert my S5 slides into a single &lt;span class="caps"&gt;PDF&lt;/span&gt; using a combination of &lt;a href="http://www.paulhammond.org/webkit2png/"&gt;&lt;code&gt;webkit2png&lt;/code&gt;&lt;/a&gt; and a custom &lt;a href="http://www.apple.com/macosx/what-is-macosx/apps-and-utilities.html#automator"&gt;Automator&lt;/a&gt; workflow :-&lt;/p&gt;


	&lt;h3&gt;Ruby Script using &lt;code&gt;webkit2png&lt;/code&gt;&lt;/h3&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="comment"&gt;#!/usr/bin/env ruby&lt;/span&gt;

&lt;span class="constant"&gt;NUMBER_OF_SLIDES&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="number"&gt;94&lt;/span&gt;
&lt;span class="constant"&gt;SEQUENCE_FORMAT&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;%0&lt;span class="expr"&gt;#{Math.log10(NUMBER_OF_SLIDES).to_i}&lt;/span&gt;d&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="constant"&gt;HOST&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;jamesmead.local&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="constant"&gt;PATH&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;/presentations/ruby-and-cocoa-ruby-manor-2009-12-14/&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="constant"&gt;BASE_URL&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;http://&lt;span class="expr"&gt;#{HOST}#{PATH}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;...&lt;/span&gt;&lt;span class="constant"&gt;NUMBER_OF_SLIDES&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;index&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
  &lt;span class="ident"&gt;anchor&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;#slide&lt;span class="expr"&gt;#{index}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="ident"&gt;url&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;span class="expr"&gt;#{BASE_URL}#{anchor}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="ident"&gt;sequence&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;SEQUENCE_FORMAT&lt;/span&gt; &lt;span class="punct"&gt;%&lt;/span&gt; &lt;span class="ident"&gt;index&lt;/span&gt;
  &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;%x[&lt;/span&gt;&lt;span class="string"&gt;webkit2png --fullsize --filename=slide-&lt;span class="expr"&gt;#{sequence}&lt;/span&gt; &lt;span class="expr"&gt;#{url}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
  &lt;span class="keyword"&gt;raise&lt;/span&gt; &lt;span class="keyword"&gt;unless&lt;/span&gt; &lt;span class="global"&gt;$?&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;success?&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;h3&gt;Custom Automator Workflow&lt;/h3&gt;


	&lt;p&gt;&lt;img src="http://farm3.static.flickr.com/2695/4304744036_21d9db8986.jpg" alt="" /&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/floehopper-blog/~4/Zdgrd-DHX9o" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://blog.floehopper.org/articles/2010/01/25/converting-s5-slides-to-a-single-pdf-on-mac-osx</feedburner:origLink></entry>
  <entry>
    <author>
      <name>James Mead</name>
    </author>
    <id>urn:uuid:de0c133b-66e4-42f2-89a1-203100258108</id>
    <published>2010-01-19T10:53:00+00:00</published>
    <updated>2010-01-19T11:19:09+00:00</updated>
    <title type="html">Mocha on Bacon</title>
    <link href="http://feeds.floehopper.org/~r/floehopper-blog/~3/80T_JyUTBOQ/mocha-on-bacon" rel="alternate" type="text/html" />
    <category term="mocha" scheme="http://blog.floehopper.org/articles/tag/mocha" />
    <category term="bacon" scheme="http://blog.floehopper.org/articles/tag/bacon" />
    <category term="testing" scheme="http://blog.floehopper.org/articles/tag/testing" />
    <category term="spec" scheme="http://blog.floehopper.org/articles/tag/spec" />
    <category term="should" scheme="http://blog.floehopper.org/articles/tag/should" />
    <category term="adapter" scheme="http://blog.floehopper.org/articles/tag/adapter" />
    <category term="mock" scheme="http://blog.floehopper.org/articles/tag/mock" />
    <summary type="html">&lt;p&gt;Some time ago, I &lt;a href="http://github.com/floehopper/mocha/commit/da24f9e93640381973b1604b8a1ff3214b0831c9"&gt;removed Bacon integration from Mocha&lt;/a&gt; after &lt;a href="http://groups.google.com/group/mocha-developer/msg/fd008b21e34638df"&gt;deciding&lt;/a&gt; to only maintain integration with 
&lt;a href="http://www.ruby-doc.org/stdlib/libdoc/test/unit/rdoc/classes/Test/Unit.html"&gt;Test::Unit&lt;/a&gt; and &lt;a href="http://blog.zenspider.com/minitest/"&gt;MiniTest&lt;/a&gt; which are both Ruby standard libraries.&lt;/p&gt;


	&lt;p&gt;Happily &lt;a href="http://superalloy.nl/"&gt;Eloy Duran&lt;/a&gt; has just &lt;a href="http://github.com/alloy/mocha-on-bacon"&gt;re-incarnated the Mocha adapter for Bacon&lt;/a&gt;. He&amp;#8217;s updated the code a bit and re-written the tests. Thanks, Eloy.&lt;/p&gt;


	&lt;p&gt;Here&amp;#8217;s an example of what you can do with &lt;a href="http://gemcutter.org/gems/bacon"&gt;Bacon&lt;/a&gt; and &lt;a href="http://mocha.rubyforge.org/"&gt;Mocha&lt;/a&gt; :-&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;expand_path&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;../spec_helper&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="constant"&gt;__FILE__&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

&lt;span class="ident"&gt;describe&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Bacon specs using Mocha, with a mock&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;

  &lt;span class="ident"&gt;extend&lt;/span&gt; &lt;span class="constant"&gt;MochaBaconHelper&lt;/span&gt;

  &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;passes when all expectations were fulfilled&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="ident"&gt;mockee&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;mock&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
    &lt;span class="ident"&gt;lambda&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
      &lt;span class="ident"&gt;mockee&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;expects&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:blah&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="ident"&gt;mockee&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;blah&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;be&lt;/span&gt; &lt;span class="ident"&gt;satisfied&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</summary>
    <content type="html">&lt;p&gt;Some time ago, I &lt;a href="http://github.com/floehopper/mocha/commit/da24f9e93640381973b1604b8a1ff3214b0831c9"&gt;removed Bacon integration from Mocha&lt;/a&gt; after &lt;a href="http://groups.google.com/group/mocha-developer/msg/fd008b21e34638df"&gt;deciding&lt;/a&gt; to only maintain integration with 
&lt;a href="http://www.ruby-doc.org/stdlib/libdoc/test/unit/rdoc/classes/Test/Unit.html"&gt;Test::Unit&lt;/a&gt; and &lt;a href="http://blog.zenspider.com/minitest/"&gt;MiniTest&lt;/a&gt; which are both Ruby standard libraries.&lt;/p&gt;


	&lt;p&gt;Happily &lt;a href="http://superalloy.nl/"&gt;Eloy Duran&lt;/a&gt; has just &lt;a href="http://github.com/alloy/mocha-on-bacon"&gt;re-incarnated the Mocha adapter for Bacon&lt;/a&gt;. He&amp;#8217;s updated the code a bit and re-written the tests. Thanks, Eloy.&lt;/p&gt;


	&lt;p&gt;Here&amp;#8217;s an example of what you can do with &lt;a href="http://gemcutter.org/gems/bacon"&gt;Bacon&lt;/a&gt; and &lt;a href="http://mocha.rubyforge.org/"&gt;Mocha&lt;/a&gt; :-&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;expand_path&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;../spec_helper&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="constant"&gt;__FILE__&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

&lt;span class="ident"&gt;describe&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Bacon specs using Mocha, with a mock&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;

  &lt;span class="ident"&gt;extend&lt;/span&gt; &lt;span class="constant"&gt;MochaBaconHelper&lt;/span&gt;

  &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;passes when all expectations were fulfilled&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="ident"&gt;mockee&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;mock&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
    &lt;span class="ident"&gt;lambda&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
      &lt;span class="ident"&gt;mockee&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;expects&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:blah&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="ident"&gt;mockee&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;blah&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;be&lt;/span&gt; &lt;span class="ident"&gt;satisfied&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/floehopper-blog/~4/80T_JyUTBOQ" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://blog.floehopper.org/articles/2010/01/19/mocha-on-bacon</feedburner:origLink></entry>
  <entry>
    <author>
      <name>James Mead</name>
    </author>
    <id>urn:uuid:e29f4b8e-28ad-4169-827b-3bf802c7f9c2</id>
    <published>2010-01-16T17:04:00+00:00</published>
    <updated>2010-01-16T17:12:50+00:00</updated>
    <title type="html">Ruby scripting in the Webby &amp;quot;environment&amp;quot;</title>
    <link href="http://feeds.floehopper.org/~r/floehopper-blog/~3/89wpThqWb2o/ruby-scripting-in-the-webby-environment" rel="alternate" type="text/html" />
    <category term="ruby" scheme="http://blog.floehopper.org/articles/tag/ruby" />
    <category term="webby" scheme="http://blog.floehopper.org/articles/tag/webby" />
    <category term="page" scheme="http://blog.floehopper.org/articles/tag/page" />
    <category term="environment" scheme="http://blog.floehopper.org/articles/tag/environment" />
    <category term="resource" scheme="http://blog.floehopper.org/articles/tag/resource" />
    <summary type="html">&lt;p&gt;As I mentioned in my &lt;a href="/articles/2010/01/14/ruby-wrapper-for-the-delicious-v2-api-using-the-oauth-gem"&gt;previous post&lt;/a&gt;, I&amp;#8217;m in the process of converting my blog from being a Rails app using &lt;a href="http://www.typosphere.org/"&gt;Typo&lt;/a&gt; to being a static site generated by &lt;a href="http://webby.rubyforge.org/"&gt;Webby&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;ve found myself wanting to be able to write Ruby scripts with access to the Webby &amp;#8220;environment&amp;#8221; e.g. the &lt;code&gt;@pages&lt;/code&gt; instance variable.&lt;/p&gt;


	&lt;p&gt;I couldn&amp;#8217;t find any documentation about this, so with a bit of delving into the source code and a bit of experimentation, I came up with the following code. I thought I&amp;#8217;d share it here in case it was of use to anyone else. And if anyone knows a better way of doing it, please let me know.&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;Note that I think this script has to run at the top level of the project.&lt;/em&gt;&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;webby&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="comment"&gt;# load Sitefile, setup load path&lt;/span&gt;
&lt;span class="ident"&gt;main&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Webby&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Apps&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Main&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;
&lt;span class="ident"&gt;main&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;init&lt;/span&gt;&lt;span class="punct"&gt;([])&lt;/span&gt;
&lt;span class="ident"&gt;main&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;app&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;init&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;webby&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;main&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;app&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;load_rakefile&lt;/span&gt;

&lt;span class="comment"&gt;# load helpers&lt;/span&gt;
&lt;span class="ident"&gt;include&lt;/span&gt; &lt;span class="constant"&gt;BlogHelper&lt;/span&gt;
&lt;span class="ident"&gt;include&lt;/span&gt; &lt;span class="constant"&gt;UrlHelper&lt;/span&gt;

&lt;span class="comment"&gt;# load pages, layouts, etc.&lt;/span&gt;
&lt;span class="ident"&gt;builder&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Webby&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Builder&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;
&lt;span class="ident"&gt;builder&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;load_files&lt;/span&gt;
&lt;span class="attribute"&gt;@pages&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Webby&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Resources&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;pages&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</summary>
    <content type="html">&lt;p&gt;As I mentioned in my &lt;a href="/articles/2010/01/14/ruby-wrapper-for-the-delicious-v2-api-using-the-oauth-gem"&gt;previous post&lt;/a&gt;, I&amp;#8217;m in the process of converting my blog from being a Rails app using &lt;a href="http://www.typosphere.org/"&gt;Typo&lt;/a&gt; to being a static site generated by &lt;a href="http://webby.rubyforge.org/"&gt;Webby&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;ve found myself wanting to be able to write Ruby scripts with access to the Webby &amp;#8220;environment&amp;#8221; e.g. the &lt;code&gt;@pages&lt;/code&gt; instance variable.&lt;/p&gt;


	&lt;p&gt;I couldn&amp;#8217;t find any documentation about this, so with a bit of delving into the source code and a bit of experimentation, I came up with the following code. I thought I&amp;#8217;d share it here in case it was of use to anyone else. And if anyone knows a better way of doing it, please let me know.&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;Note that I think this script has to run at the top level of the project.&lt;/em&gt;&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;webby&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="comment"&gt;# load Sitefile, setup load path&lt;/span&gt;
&lt;span class="ident"&gt;main&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Webby&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Apps&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Main&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;
&lt;span class="ident"&gt;main&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;init&lt;/span&gt;&lt;span class="punct"&gt;([])&lt;/span&gt;
&lt;span class="ident"&gt;main&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;app&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;init&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;webby&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;main&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;app&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;load_rakefile&lt;/span&gt;

&lt;span class="comment"&gt;# load helpers&lt;/span&gt;
&lt;span class="ident"&gt;include&lt;/span&gt; &lt;span class="constant"&gt;BlogHelper&lt;/span&gt;
&lt;span class="ident"&gt;include&lt;/span&gt; &lt;span class="constant"&gt;UrlHelper&lt;/span&gt;

&lt;span class="comment"&gt;# load pages, layouts, etc.&lt;/span&gt;
&lt;span class="ident"&gt;builder&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Webby&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Builder&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;
&lt;span class="ident"&gt;builder&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;load_files&lt;/span&gt;
&lt;span class="attribute"&gt;@pages&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Webby&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Resources&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;pages&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/floehopper-blog/~4/89wpThqWb2o" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://blog.floehopper.org/articles/2010/01/16/ruby-scripting-in-the-webby-environment</feedburner:origLink></entry>
  <entry>
    <author>
      <name>James Mead</name>
    </author>
    <id>urn:uuid:333620d4-f811-41d1-bed5-21b44365c61f</id>
    <published>2010-01-14T13:56:00+00:00</published>
    <updated>2010-01-14T13:57:03+00:00</updated>
    <title type="html">Ruby wrapper for the Delicious v2 API using the OAuth gem</title>
    <link href="http://feeds.floehopper.org/~r/floehopper-blog/~3/UNGvX9Eo6Ko/ruby-wrapper-for-the-delicious-v2-api-using-the-oauth-gem" rel="alternate" type="text/html" />
    <category term="ruby" scheme="http://blog.floehopper.org/articles/tag/ruby" />
    <category term="delicious" scheme="http://blog.floehopper.org/articles/tag/delicious" />
    <category term="api" scheme="http://blog.floehopper.org/articles/tag/api" />
    <category term="v2" scheme="http://blog.floehopper.org/articles/tag/v2" />
    <category term="oauth" scheme="http://blog.floehopper.org/articles/tag/oauth" />
    <category term="yahoo" scheme="http://blog.floehopper.org/articles/tag/yahoo" />
    <category term="bookmark" scheme="http://blog.floehopper.org/articles/tag/bookmark" />
    <summary type="html">&lt;p&gt;I&amp;#8217;ve got a bit sidetracked recently while trying to convert my blog from using &lt;a href="http://www.typosphere.org/"&gt;Typo&lt;/a&gt; to a static site using &lt;a href="http://webby.rubyforge.org/"&gt;Webby&lt;/a&gt;. Typo provides a facility to tag your blog posts. This allows visitors to find &lt;a href="http://blog.floehopper.org/articles/tag/mocha"&gt;all the articles tagged e.g. mocha&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Generating these tag pages becomes more awkward with the Webby-based site which is generated at deploy-time. I decided I liked the approach that Chris Roos took which was &lt;a href="http://chrisroos.co.uk/tags"&gt;to tag his blog posts in del.icio.us&lt;/a&gt; so that visitors can use a del.icio.us &lt;span class="caps"&gt;URL&lt;/span&gt; to find &lt;a href="http://delicious.com/chrisjroos/blog.seagul.co.uk+cool"&gt;all the articles with a particular tag&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Initially I used &lt;a href="http://github.com/weppos/www-delicious"&gt;&lt;span class="caps"&gt;WWW&lt;/span&gt;::Delicious&lt;/a&gt; which worked well enough with &lt;a href="http://delicious.com/jamesthecat/"&gt;my main del.icio.us account&lt;/a&gt;. But then I decided I didn&amp;#8217;t want to clutter up this account with bookmarks to all my blog posts, so I created a new account. Unfortunately since this is a new account, I have to use the v2 &lt;span class="caps"&gt;API&lt;/span&gt; with OAuth if I want to programmatically add bookmarks :-&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;To access data from accounts created using a Yahoo! ID, use the same &lt;span class="caps"&gt;API&lt;/span&gt;&amp;#8217;s as below, but change the path to /v2, and make &lt;span class="caps"&gt;HTTP&lt;/span&gt; requests using OAuth as provided by the &lt;a href="http://developer.yahoo.com/oauth/"&gt;Yahoo! Developer Network&lt;/a&gt;.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;I couldn&amp;#8217;t find any examples of anyone doing this using Ruby, so I decided to have a go using the &lt;a href="http://oauth.rubyforge.org/"&gt;OAuth gem&lt;/a&gt;. It was a bit of a painful process due to a lack of decent documentation, but I got there in the end. I thought I&amp;#8217;d &lt;a href="http://github.com/floehopper/delicious-api-via-oauth"&gt;share the code&lt;/a&gt; in case it saves anyone else a bit of time.&lt;/p&gt;


	&lt;p&gt;The code probably isn&amp;#8217;t very robust since it&amp;#8217;s lacking tests and it currently only offers the ability to add bookmarks which was all I needed. Probably what I should do next is integrate this code with something like &lt;span class="caps"&gt;WWW&lt;/span&gt;:Delicious to offer access to both v1 and v2 APIs, but since I can now do what I wanted, this is unlikely to happen in the near future.&lt;/p&gt;


	&lt;p&gt;In order to get the example code to work, you&amp;#8217;ll need to login to a Yahoo! ID based del.icio.us account and go to your &lt;a href="https://developer.apps.yahoo.com/projects"&gt;My Projects page&lt;/a&gt; :-&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://farm5.static.flickr.com/4012/4274176876_4aa9366840.jpg" alt="" /&gt;&lt;/p&gt;


	&lt;p&gt;There you need to add a project and grant it read/write access to del.icio.us :-&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://farm3.static.flickr.com/2765/4274199394_8408d3f2fc.jpg" alt="" /&gt;&lt;/p&gt;


	&lt;p&gt;Granting access to your project will generate a Consumer Key and a Consumer Secret. These values should be used to define the &lt;code&gt;API_KEY&lt;/code&gt; and &lt;code&gt;SHARED_SECRET&lt;/code&gt; constants respectively. The &lt;code&gt;example.rb&lt;/code&gt; code does this by requiring a &lt;code&gt;constants.rb&lt;/code&gt; file which you could add.&lt;/p&gt;


	&lt;p&gt;Here&amp;#8217;s the example code which creates a single bookmark. Note that the first time this is run, it will open a browser and require you to login to obtain an &lt;code&gt;oauth_verifier&lt;/code&gt; code :-&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://farm3.static.flickr.com/2744/4274208592_0066d8e0f2_o.png" alt="" /&gt;&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://farm5.static.flickr.com/4010/4274217158_e0b472a781_o.png" alt="" /&gt;&lt;/p&gt;


	&lt;p&gt;You will need to copy and paste this code into the terminal window :-&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://farm3.static.flickr.com/2720/4273475533_0d2e7eca8c.jpg" alt="" /&gt;&lt;/p&gt;


	&lt;p&gt;All the relevant tokens are saved to &lt;span class="caps"&gt;YAML&lt;/span&gt; files, so that subsequent calls to the &lt;span class="caps"&gt;API&lt;/span&gt; will work without user interaction. However, you should note that an access token expires after 1 hour. It ought to be possible to refresh this token without user interaction, but I haven&amp;#8217;t been able to get that working yet, so in this case you&amp;#8217;ll probably need to delete &lt;code&gt;request_token.yml&lt;/code&gt; and &lt;code&gt;access_token.yml&lt;/code&gt; and re-run the script.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="global"&gt;$LOAD_PATH&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;dirname&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;__FILE__&lt;/span&gt;&lt;span class="punct"&gt;),&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;oauth-extensions&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;
&lt;span class="global"&gt;$LOAD_PATH&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;dirname&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;__FILE__&lt;/span&gt;&lt;span class="punct"&gt;),&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;delicious&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;

&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;delicious/api&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;constants&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="ident"&gt;api&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Delicious&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;API&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;API_KEY&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="constant"&gt;SHARED_SECRET&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
&lt;span class="ident"&gt;api&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;posts_add!&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;
  &lt;span class="symbol"&gt;:url&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;http://www.google.com/&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt;
  &lt;span class="symbol"&gt;:description&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Testing 1 2 3&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt;
  &lt;span class="symbol"&gt;:extended&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Blah blah blah&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt;
  &lt;span class="symbol"&gt;:tags&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;testing google blah&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="punct"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Finally, here&amp;#8217;s the bookmark successfully added to my account :-&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://farm5.static.flickr.com/4054/4273486847_d685d9f56b.jpg" alt="" /&gt;&lt;/p&gt;</summary>
    <content type="html">&lt;p&gt;I&amp;#8217;ve got a bit sidetracked recently while trying to convert my blog from using &lt;a href="http://www.typosphere.org/"&gt;Typo&lt;/a&gt; to a static site using &lt;a href="http://webby.rubyforge.org/"&gt;Webby&lt;/a&gt;. Typo provides a facility to tag your blog posts. This allows visitors to find &lt;a href="http://blog.floehopper.org/articles/tag/mocha"&gt;all the articles tagged e.g. mocha&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Generating these tag pages becomes more awkward with the Webby-based site which is generated at deploy-time. I decided I liked the approach that Chris Roos took which was &lt;a href="http://chrisroos.co.uk/tags"&gt;to tag his blog posts in del.icio.us&lt;/a&gt; so that visitors can use a del.icio.us &lt;span class="caps"&gt;URL&lt;/span&gt; to find &lt;a href="http://delicious.com/chrisjroos/blog.seagul.co.uk+cool"&gt;all the articles with a particular tag&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Initially I used &lt;a href="http://github.com/weppos/www-delicious"&gt;&lt;span class="caps"&gt;WWW&lt;/span&gt;::Delicious&lt;/a&gt; which worked well enough with &lt;a href="http://delicious.com/jamesthecat/"&gt;my main del.icio.us account&lt;/a&gt;. But then I decided I didn&amp;#8217;t want to clutter up this account with bookmarks to all my blog posts, so I created a new account. Unfortunately since this is a new account, I have to use the v2 &lt;span class="caps"&gt;API&lt;/span&gt; with OAuth if I want to programmatically add bookmarks :-&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;To access data from accounts created using a Yahoo! ID, use the same &lt;span class="caps"&gt;API&lt;/span&gt;&amp;#8217;s as below, but change the path to /v2, and make &lt;span class="caps"&gt;HTTP&lt;/span&gt; requests using OAuth as provided by the &lt;a href="http://developer.yahoo.com/oauth/"&gt;Yahoo! Developer Network&lt;/a&gt;.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;I couldn&amp;#8217;t find any examples of anyone doing this using Ruby, so I decided to have a go using the &lt;a href="http://oauth.rubyforge.org/"&gt;OAuth gem&lt;/a&gt;. It was a bit of a painful process due to a lack of decent documentation, but I got there in the end. I thought I&amp;#8217;d &lt;a href="http://github.com/floehopper/delicious-api-via-oauth"&gt;share the code&lt;/a&gt; in case it saves anyone else a bit of time.&lt;/p&gt;


	&lt;p&gt;The code probably isn&amp;#8217;t very robust since it&amp;#8217;s lacking tests and it currently only offers the ability to add bookmarks which was all I needed. Probably what I should do next is integrate this code with something like &lt;span class="caps"&gt;WWW&lt;/span&gt;:Delicious to offer access to both v1 and v2 APIs, but since I can now do what I wanted, this is unlikely to happen in the near future.&lt;/p&gt;


	&lt;p&gt;In order to get the example code to work, you&amp;#8217;ll need to login to a Yahoo! ID based del.icio.us account and go to your &lt;a href="https://developer.apps.yahoo.com/projects"&gt;My Projects page&lt;/a&gt; :-&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://farm5.static.flickr.com/4012/4274176876_4aa9366840.jpg" alt="" /&gt;&lt;/p&gt;


	&lt;p&gt;There you need to add a project and grant it read/write access to del.icio.us :-&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://farm3.static.flickr.com/2765/4274199394_8408d3f2fc.jpg" alt="" /&gt;&lt;/p&gt;


	&lt;p&gt;Granting access to your project will generate a Consumer Key and a Consumer Secret. These values should be used to define the &lt;code&gt;API_KEY&lt;/code&gt; and &lt;code&gt;SHARED_SECRET&lt;/code&gt; constants respectively. The &lt;code&gt;example.rb&lt;/code&gt; code does this by requiring a &lt;code&gt;constants.rb&lt;/code&gt; file which you could add.&lt;/p&gt;


	&lt;p&gt;Here&amp;#8217;s the example code which creates a single bookmark. Note that the first time this is run, it will open a browser and require you to login to obtain an &lt;code&gt;oauth_verifier&lt;/code&gt; code :-&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://farm3.static.flickr.com/2744/4274208592_0066d8e0f2_o.png" alt="" /&gt;&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://farm5.static.flickr.com/4010/4274217158_e0b472a781_o.png" alt="" /&gt;&lt;/p&gt;


	&lt;p&gt;You will need to copy and paste this code into the terminal window :-&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://farm3.static.flickr.com/2720/4273475533_0d2e7eca8c.jpg" alt="" /&gt;&lt;/p&gt;


	&lt;p&gt;All the relevant tokens are saved to &lt;span class="caps"&gt;YAML&lt;/span&gt; files, so that subsequent calls to the &lt;span class="caps"&gt;API&lt;/span&gt; will work without user interaction. However, you should note that an access token expires after 1 hour. It ought to be possible to refresh this token without user interaction, but I haven&amp;#8217;t been able to get that working yet, so in this case you&amp;#8217;ll probably need to delete &lt;code&gt;request_token.yml&lt;/code&gt; and &lt;code&gt;access_token.yml&lt;/code&gt; and re-run the script.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="global"&gt;$LOAD_PATH&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;dirname&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;__FILE__&lt;/span&gt;&lt;span class="punct"&gt;),&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;oauth-extensions&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;
&lt;span class="global"&gt;$LOAD_PATH&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;dirname&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;__FILE__&lt;/span&gt;&lt;span class="punct"&gt;),&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;delicious&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;

&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;delicious/api&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;constants&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="ident"&gt;api&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Delicious&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;API&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;API_KEY&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="constant"&gt;SHARED_SECRET&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
&lt;span class="ident"&gt;api&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;posts_add!&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;
  &lt;span class="symbol"&gt;:url&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;http://www.google.com/&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt;
  &lt;span class="symbol"&gt;:description&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Testing 1 2 3&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt;
  &lt;span class="symbol"&gt;:extended&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Blah blah blah&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt;
  &lt;span class="symbol"&gt;:tags&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;testing google blah&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="punct"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Finally, here&amp;#8217;s the bookmark successfully added to my account :-&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://farm5.static.flickr.com/4054/4273486847_d685d9f56b.jpg" alt="" /&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/floehopper-blog/~4/UNGvX9Eo6Ko" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://blog.floehopper.org/articles/2010/01/14/ruby-wrapper-for-the-delicious-v2-api-using-the-oauth-gem</feedburner:origLink></entry>
  <entry>
    <author>
      <name>James Mead</name>
    </author>
    <id>urn:uuid:7b0e92a9-fcaf-4afe-990c-d1e037363958</id>
    <published>2009-12-14T11:59:46+00:00</published>
    <updated>2009-12-14T11:59:46+00:00</updated>
    <title type="html">Ruby and Cocoa talk at Ruby Manor</title>
    <link href="http://feeds.floehopper.org/~r/floehopper-blog/~3/1uoWWBIQPxE/ruby-and-cocoa-talk-at-ruby-manor" rel="alternate" type="text/html" />
    <category term="ruby" scheme="http://blog.floehopper.org/articles/tag/ruby" />
    <category term="cocoa" scheme="http://blog.floehopper.org/articles/tag/cocoa" />
    <category term="macruby" scheme="http://blog.floehopper.org/articles/tag/macruby" />
    <category term="testing" scheme="http://blog.floehopper.org/articles/tag/testing" />
    <category term="acceptance" scheme="http://blog.floehopper.org/articles/tag/acceptance" />
    <category term="unit" scheme="http://blog.floehopper.org/articles/tag/unit" />
    <category term="accessibility" scheme="http://blog.floehopper.org/articles/tag/accessibility" />
    <summary type="html">&lt;p&gt;Here are the &lt;a href="http://blog.floehopper.org/presentations/ruby-and-cocoa-ruby-manor-2009-12-14/"&gt;slides&lt;/a&gt; from my recent talk at &lt;a href="http://rubymanor.org/harder/"&gt;Ruby Manor 2&lt;/a&gt; on &amp;#8220;Ruby and Cocoa&amp;#8221;.&lt;/p&gt;


	&lt;p&gt;And here&amp;#8217;s the &lt;a href="http://github.com/floehopper/hotcocoa-calculator"&gt;code&lt;/a&gt; for my demo of acceptance testing the &lt;a href="http://www.macruby.org/"&gt;MacRuby&lt;/a&gt; &lt;a href="http://www.macruby.org/trac/wiki/HotCocoa"&gt;HotCocoa&lt;/a&gt; Calculator example app using the &lt;a href="http://developer.apple.com/ue/accessibility/"&gt;&lt;span class="caps"&gt;OSX&lt;/span&gt; Accessibility &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;</summary>
    <content type="html">&lt;p&gt;Here are the &lt;a href="http://blog.floehopper.org/presentations/ruby-and-cocoa-ruby-manor-2009-12-14/"&gt;slides&lt;/a&gt; from my recent talk at &lt;a href="http://rubymanor.org/harder/"&gt;Ruby Manor 2&lt;/a&gt; on &amp;#8220;Ruby and Cocoa&amp;#8221;.&lt;/p&gt;


	&lt;p&gt;And here&amp;#8217;s the &lt;a href="http://github.com/floehopper/hotcocoa-calculator"&gt;code&lt;/a&gt; for my demo of acceptance testing the &lt;a href="http://www.macruby.org/"&gt;MacRuby&lt;/a&gt; &lt;a href="http://www.macruby.org/trac/wiki/HotCocoa"&gt;HotCocoa&lt;/a&gt; Calculator example app using the &lt;a href="http://developer.apple.com/ue/accessibility/"&gt;&lt;span class="caps"&gt;OSX&lt;/span&gt; Accessibility &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/floehopper-blog/~4/1uoWWBIQPxE" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://blog.floehopper.org/articles/2009/12/14/ruby-and-cocoa-talk-at-ruby-manor</feedburner:origLink></entry>
  <entry>
    <author>
      <name>James Mead</name>
    </author>
    <id>urn:uuid:241da9d4-d57a-4197-bc68-74dfa03cc09c</id>
    <published>2009-11-02T16:21:44+00:00</published>
    <updated>2009-11-02T16:23:13+00:00</updated>
    <title type="html">ActiveRecord Model Class Name Clash</title>
    <link href="http://feeds.floehopper.org/~r/floehopper-blog/~3/BBCWIIYBaHA/activerecord-model-class-name-clash" rel="alternate" type="text/html" />
    <category term="activerecord" scheme="http://blog.floehopper.org/articles/tag/activerecord" />
    <category term="model" scheme="http://blog.floehopper.org/articles/tag/model" />
    <category term="class" scheme="http://blog.floehopper.org/articles/tag/class" />
    <category term="validation" scheme="http://blog.floehopper.org/articles/tag/validation" />
    <category term="twice" scheme="http://blog.floehopper.org/articles/tag/twice" />
    <category term="callback" scheme="http://blog.floehopper.org/articles/tag/callback" />
    <category term="collision" scheme="http://blog.floehopper.org/articles/tag/collision" />
    <category term="clash" scheme="http://blog.floehopper.org/articles/tag/clash" />
    <summary type="html">&lt;p&gt;I&amp;#8217;ve just spent way too long trying to work out why the validation callbacks were getting called twice on one of my &lt;a href="http://api.rubyonrails.org/classes/ActiveRecord/Base.html"&gt;ActiveRecord&lt;/a&gt; models. I thought I&amp;#8217;d write this up in case it saves someone else some pain.&lt;/p&gt;


	&lt;p&gt;In the end, I narrowed the problem down to the name of the model class which is &lt;code&gt;Sync&lt;/code&gt;. I should&amp;#8217;ve thought of this sooner, but it turns out there is a Ruby standard library class called &lt;a href="http://ruby-doc.org/stdlib/libdoc/sync/rdoc/index.html"&gt;&lt;code&gt;Sync&lt;/code&gt;&lt;/a&gt;. I haven&amp;#8217;t delved any further into why validation was being called twice. As far as I&amp;#8217;m concerned, once you re-open an existing Ruby class like this, it makes sense that all bets are off.&lt;/p&gt;


	&lt;p&gt;However, I am a bit confused why the original Sync model class definition didn&amp;#8217;t give a &amp;#8220;superclass mismatch&amp;#8221; &lt;a href="http://ruby-doc.org/core/classes/TypeError.html"&gt;&lt;code&gt;TypeError&lt;/code&gt;&lt;/a&gt;, which is what happens if I do :-&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="ident"&gt;script&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="ident"&gt;runner&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;class Sync &amp;lt; ActiveRecord::Base; end&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;It must be a load order issue, since if I put the class definition in a file in app/models, I don&amp;#8217;t see the &lt;code&gt;TypeError&lt;/code&gt;. It would&amp;#8217;ve saved a lot of time if my &lt;code&gt;Sync&lt;/code&gt; model class definition had failed fast in this way. I might see if there&amp;#8217;s a way to make that happen.&lt;/p&gt;</summary>
    <content type="html">&lt;p&gt;I&amp;#8217;ve just spent way too long trying to work out why the validation callbacks were getting called twice on one of my &lt;a href="http://api.rubyonrails.org/classes/ActiveRecord/Base.html"&gt;ActiveRecord&lt;/a&gt; models. I thought I&amp;#8217;d write this up in case it saves someone else some pain.&lt;/p&gt;


	&lt;p&gt;In the end, I narrowed the problem down to the name of the model class which is &lt;code&gt;Sync&lt;/code&gt;. I should&amp;#8217;ve thought of this sooner, but it turns out there is a Ruby standard library class called &lt;a href="http://ruby-doc.org/stdlib/libdoc/sync/rdoc/index.html"&gt;&lt;code&gt;Sync&lt;/code&gt;&lt;/a&gt;. I haven&amp;#8217;t delved any further into why validation was being called twice. As far as I&amp;#8217;m concerned, once you re-open an existing Ruby class like this, it makes sense that all bets are off.&lt;/p&gt;


	&lt;p&gt;However, I am a bit confused why the original Sync model class definition didn&amp;#8217;t give a &amp;#8220;superclass mismatch&amp;#8221; &lt;a href="http://ruby-doc.org/core/classes/TypeError.html"&gt;&lt;code&gt;TypeError&lt;/code&gt;&lt;/a&gt;, which is what happens if I do :-&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="ident"&gt;script&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="ident"&gt;runner&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;class Sync &amp;lt; ActiveRecord::Base; end&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;It must be a load order issue, since if I put the class definition in a file in app/models, I don&amp;#8217;t see the &lt;code&gt;TypeError&lt;/code&gt;. It would&amp;#8217;ve saved a lot of time if my &lt;code&gt;Sync&lt;/code&gt; model class definition had failed fast in this way. I might see if there&amp;#8217;s a way to make that happen.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/floehopper-blog/~4/BBCWIIYBaHA" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://blog.floehopper.org/articles/2009/11/02/activerecord-model-class-name-clash</feedburner:origLink></entry>
  <entry>
    <author>
      <name>James Mead</name>
    </author>
    <id>urn:uuid:b23f8cdd-771f-46c1-a4bf-bacf541a1291</id>
    <published>2009-09-18T11:35:40+00:00</published>
    <updated>2009-09-18T11:35:40+00:00</updated>
    <title type="html">Mocha NoMethodError / Load order since version 0.9.6</title>
    <link href="http://feeds.floehopper.org/~r/floehopper-blog/~3/ZPXS8KRZxoA/mocha-nomethoderror-load-order-since-version-0-9-6" rel="alternate" type="text/html" />
    <category term="mocha" scheme="http://blog.floehopper.org/articles/tag/mocha" />
    <category term="mock" scheme="http://blog.floehopper.org/articles/tag/mock" />
    <category term="stub" scheme="http://blog.floehopper.org/articles/tag/stub" />
    <category term="ruby" scheme="http://blog.floehopper.org/articles/tag/ruby" />
    <category term="testing" scheme="http://blog.floehopper.org/articles/tag/testing" />
    <category term="tdd" scheme="http://blog.floehopper.org/articles/tag/tdd" />
    <category term="nomethoderror" scheme="http://blog.floehopper.org/articles/tag/nomethoderror" />
    <category term="load" scheme="http://blog.floehopper.org/articles/tag/load" />
    <category term="order" scheme="http://blog.floehopper.org/articles/tag/order" />
    <summary type="html">&lt;p&gt;There have been a number of load order issues since 0.9.6 was released for which I apologise.&lt;/p&gt;


	&lt;p&gt;The key message is that since 0.9.6, you must ensure that your test framework (&lt;a href="http://www.ruby-doc.org/stdlib/libdoc/test/unit/rdoc/classes/Test/Unit.html"&gt;Test::Unit&lt;/a&gt; or &lt;a href="http://blog.zenspider.com/minitest/"&gt;MiniTest&lt;/a&gt;) is loaded &lt;strong&gt;before&lt;/strong&gt; &lt;a href="http://mocha.rubyforge.org/"&gt;Mocha&lt;/a&gt; is loaded, otherwise &lt;a href="http://mocha.rubyforge.org/"&gt;Mocha&lt;/a&gt; will not monkey-patch the test framework and calls to the Mocha &lt;span class="caps"&gt;API&lt;/span&gt; will result in &lt;a href="http://www.ruby-doc.org/core/classes/NoMethodError.html"&gt;NoMethodError&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;I hope to write this up in more detail soon, but in the meantime here are a couple of useful links :-&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://railspikes.com/2009/7/29/rails-2-3-3-upgrade-notes/"&gt;Rails 2.3.3 Upgrade Notes&lt;/a&gt; &lt;/li&gt;
		&lt;li&gt;&lt;a href="http://selfamusementpark.com/blog/2009/07/30/rails233mochaconfusion/"&gt;Rails 2.3.3 + Mocha = Confusion&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Please contact us on the &lt;a href="http://groups.google.com/group/mocha-developer"&gt;mailing list&lt;/a&gt; if you have any questions.&lt;/p&gt;</summary>
    <content type="html">&lt;p&gt;There have been a number of load order issues since 0.9.6 was released for which I apologise.&lt;/p&gt;


	&lt;p&gt;The key message is that since 0.9.6, you must ensure that your test framework (&lt;a href="http://www.ruby-doc.org/stdlib/libdoc/test/unit/rdoc/classes/Test/Unit.html"&gt;Test::Unit&lt;/a&gt; or &lt;a href="http://blog.zenspider.com/minitest/"&gt;MiniTest&lt;/a&gt;) is loaded &lt;strong&gt;before&lt;/strong&gt; &lt;a href="http://mocha.rubyforge.org/"&gt;Mocha&lt;/a&gt; is loaded, otherwise &lt;a href="http://mocha.rubyforge.org/"&gt;Mocha&lt;/a&gt; will not monkey-patch the test framework and calls to the Mocha &lt;span class="caps"&gt;API&lt;/span&gt; will result in &lt;a href="http://www.ruby-doc.org/core/classes/NoMethodError.html"&gt;NoMethodError&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;I hope to write this up in more detail soon, but in the meantime here are a couple of useful links :-&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://railspikes.com/2009/7/29/rails-2-3-3-upgrade-notes/"&gt;Rails 2.3.3 Upgrade Notes&lt;/a&gt; &lt;/li&gt;
		&lt;li&gt;&lt;a href="http://selfamusementpark.com/blog/2009/07/30/rails233mochaconfusion/"&gt;Rails 2.3.3 + Mocha = Confusion&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Please contact us on the &lt;a href="http://groups.google.com/group/mocha-developer"&gt;mailing list&lt;/a&gt; if you have any questions.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/floehopper-blog/~4/ZPXS8KRZxoA" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://blog.floehopper.org/articles/2009/09/18/mocha-nomethoderror-load-order-since-version-0-9-6</feedburner:origLink></entry>
  <entry>
    <author>
      <name>James Mead</name>
    </author>
    <id>urn:uuid:61369f37-aabd-489b-b0df-12a07b6fc820</id>
    <published>2009-09-18T11:17:44+00:00</published>
    <updated>2009-09-18T11:17:45+00:00</updated>
    <title type="html">Mocha Release 0.9.8</title>
    <link href="http://feeds.floehopper.org/~r/floehopper-blog/~3/boQWys8YpIk/mocha-release-0-9-8" rel="alternate" type="text/html" />
    <category term="mocha_release" scheme="http://blog.floehopper.org/articles/category/mocha_release" label="mocha_release" />
    <category term="mocha" scheme="http://blog.floehopper.org/articles/tag/mocha" />
    <category term="mock" scheme="http://blog.floehopper.org/articles/tag/mock" />
    <category term="stub" scheme="http://blog.floehopper.org/articles/tag/stub" />
    <category term="ruby" scheme="http://blog.floehopper.org/articles/tag/ruby" />
    <category term="testing" scheme="http://blog.floehopper.org/articles/tag/testing" />
    <category term="tdd" scheme="http://blog.floehopper.org/articles/tag/tdd" />
    <summary type="html">&lt;h3&gt;Release Notes&lt;/h3&gt;


	&lt;ul&gt;
	&lt;li&gt;Fixed bug &lt;a href="http://floehopper.lighthouseapp.com/projects/22289/tickets/53"&gt;NameError raised when using Mocha as a Rails plug-in&lt;/a&gt;. Since 0.9.6 the Rails plugin has been broken. See &lt;a href="http://floehopper.lighthouseapp.com/projects/22289/tickets/53"&gt;bug report&lt;/a&gt; for details. You will need to explicitly load Mocha &lt;strong&gt;after&lt;/strong&gt; the test framework has been loaded, e.g. by adding &amp;#8220;require &amp;#8216;mocha&amp;#8217;&amp;#8221; at the bottom of test/test_helper.rb.&lt;/li&gt;
		&lt;li&gt;Make &lt;a href="http://mocha.rubyforge.org/classes/Mocha/ParameterMatchers.html#M000024"&gt;Mocha::ParameterMatchers#regexp_matches&lt;/a&gt;, &lt;a href="http://mocha.rubyforge.org/classes/Mocha/ParameterMatchers.html#M000018"&gt;#includes&lt;/a&gt;, &lt;a href="http://mocha.rubyforge.org/classes/Mocha/ParameterMatchers.html#M000017"&gt;#has_value&lt;/a&gt;, &lt;a href="http://mocha.rubyforge.org/classes/Mocha/ParameterMatchers.html#M000016"&gt;#has_key&lt;/a&gt; more robust. Thanks to &lt;a href="http://github.com/sander6"&gt;Sander Hartlage&lt;/a&gt;.&lt;/li&gt;
		&lt;li&gt;Allow passing a block to &lt;a href="http://mocha.rubyforge.org/classes/Mocha/Configuration.html"&gt;Mocha::Configuration&lt;/a&gt; methods to only change configuration for the duration of the block. Thanks to &lt;a href="http://www.dcmanges.com/blog"&gt;Dan Manges&lt;/a&gt;.&lt;/li&gt;
		&lt;li&gt;Fixed bug &lt;a href="http://floehopper.lighthouseapp.com/projects/22289/tickets/51"&gt;doc generation fails in 0.9.7 gem&lt;/a&gt;.&lt;/li&gt;
		&lt;li&gt;Remove rdoc template incorporating google analytics from source control. The file just needs to exist locally and be ignored by source control. This should stop the warning showing up on e.g. &lt;a href="http://runcoderun.com/floehopper/mocha"&gt;RunCodeRun build results&lt;/a&gt;.&lt;/li&gt;
	&lt;/ul&gt;</summary>
    <content type="html">&lt;h3&gt;Release Notes&lt;/h3&gt;


	&lt;ul&gt;
	&lt;li&gt;Fixed bug &lt;a href="http://floehopper.lighthouseapp.com/projects/22289/tickets/53"&gt;NameError raised when using Mocha as a Rails plug-in&lt;/a&gt;. Since 0.9.6 the Rails plugin has been broken. See &lt;a href="http://floehopper.lighthouseapp.com/projects/22289/tickets/53"&gt;bug report&lt;/a&gt; for details. You will need to explicitly load Mocha &lt;strong&gt;after&lt;/strong&gt; the test framework has been loaded, e.g. by adding &amp;#8220;require &amp;#8216;mocha&amp;#8217;&amp;#8221; at the bottom of test/test_helper.rb.&lt;/li&gt;
		&lt;li&gt;Make &lt;a href="http://mocha.rubyforge.org/classes/Mocha/ParameterMatchers.html#M000024"&gt;Mocha::ParameterMatchers#regexp_matches&lt;/a&gt;, &lt;a href="http://mocha.rubyforge.org/classes/Mocha/ParameterMatchers.html#M000018"&gt;#includes&lt;/a&gt;, &lt;a href="http://mocha.rubyforge.org/classes/Mocha/ParameterMatchers.html#M000017"&gt;#has_value&lt;/a&gt;, &lt;a href="http://mocha.rubyforge.org/classes/Mocha/ParameterMatchers.html#M000016"&gt;#has_key&lt;/a&gt; more robust. Thanks to &lt;a href="http://github.com/sander6"&gt;Sander Hartlage&lt;/a&gt;.&lt;/li&gt;
		&lt;li&gt;Allow passing a block to &lt;a href="http://mocha.rubyforge.org/classes/Mocha/Configuration.html"&gt;Mocha::Configuration&lt;/a&gt; methods to only change configuration for the duration of the block. Thanks to &lt;a href="http://www.dcmanges.com/blog"&gt;Dan Manges&lt;/a&gt;.&lt;/li&gt;
		&lt;li&gt;Fixed bug &lt;a href="http://floehopper.lighthouseapp.com/projects/22289/tickets/51"&gt;doc generation fails in 0.9.7 gem&lt;/a&gt;.&lt;/li&gt;
		&lt;li&gt;Remove rdoc template incorporating google analytics from source control. The file just needs to exist locally and be ignored by source control. This should stop the warning showing up on e.g. &lt;a href="http://runcoderun.com/floehopper/mocha"&gt;RunCodeRun build results&lt;/a&gt;.&lt;/li&gt;
	&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/floehopper-blog/~4/boQWys8YpIk" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://blog.floehopper.org/articles/2009/09/18/mocha-release-0-9-8</feedburner:origLink></entry>
  <entry>
    <author>
      <name>James Mead</name>
    </author>
    <id>urn:uuid:4f6bf634-8f6e-44be-a5c0-76d1b3199a6a</id>
    <published>2009-09-14T16:58:56+00:00</published>
    <updated>2009-09-14T17:07:32+00:00</updated>
    <title type="html">Mocha Test Spies</title>
    <link href="http://feeds.floehopper.org/~r/floehopper-blog/~3/TWROFmPw8Yo/mocha-test-spies" rel="alternate" type="text/html" />
    <category term="mocha" scheme="http://blog.floehopper.org/articles/tag/mocha" />
    <category term="mock" scheme="http://blog.floehopper.org/articles/tag/mock" />
    <category term="stub" scheme="http://blog.floehopper.org/articles/tag/stub" />
    <category term="ruby" scheme="http://blog.floehopper.org/articles/tag/ruby" />
    <category term="testing" scheme="http://blog.floehopper.org/articles/tag/testing" />
    <category term="tdd" scheme="http://blog.floehopper.org/articles/tag/tdd" />
    <category term="spy" scheme="http://blog.floehopper.org/articles/tag/spy" />
    <category term="fork" scheme="http://blog.floehopper.org/articles/tag/fork" />
    <category term="thoughtbot" scheme="http://blog.floehopper.org/articles/tag/thoughtbot" />
    <summary type="html">&lt;h3&gt;Introduction&lt;/h3&gt;


	&lt;p&gt;Today I finally got round to looking at &lt;a href="http://github.com/jferris/mocha/commits/spies"&gt;Joe Ferris&amp;#8217; Test Spies fork&lt;/a&gt; of Mocha. Joe explained how Test Spies work and why he thinks they are useful in &lt;a href="http://robots.thoughtbot.com/post/159805295/spy-vs-spy"&gt;Spy vs spy&lt;/a&gt; on the ThoughtBot blog. I apologise to Joe for not getting round to this sooner.&lt;/p&gt;


	&lt;p&gt;I have a number of hesitations about merging these changes into &lt;a href="http://mocha.rubyforge.org/"&gt;Mocha&lt;/a&gt; as they stand. My thinking hasn&amp;#8217;t really crystallized, but in these situations I often find it&amp;#8217;s useful to force myself to try and explain myself in writing. Hopefully it&amp;#8217;ll also generate some feedback.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;d like to thank Joe for taking the time to fork Mocha and add this functionality. I&amp;#8217;m particularly grateful that he&amp;#8217;s taken the trouble to write a &lt;a href="http://github.com/jferris/mocha/raw/spies/test/acceptance/spy_test.rb"&gt;bunch of high-level acceptance tests&lt;/a&gt;.&lt;/p&gt;


	&lt;h3&gt;Concept&lt;/h3&gt;


	&lt;p&gt;In this section I&amp;#8217;ve tried to write up some comments on &lt;a href="http://robots.thoughtbot.com/post/159805295/spy-vs-spy"&gt;Joe&amp;#8217;s blog post&lt;/a&gt; under roughly the same headings :-&lt;/p&gt;


	&lt;h4&gt;Why would I let spies in my code?&lt;/h4&gt;


	&lt;p&gt;Joe correctly points out that setting up expectations before exercising the object under test is a bit of a departure from the traditional &lt;a href="http://xunitpatterns.com/Four%20Phase%20Test.html"&gt;Four-Phase Test&lt;/a&gt; regime. I can see how some people might see this as counter-intuitive, but it doesn&amp;#8217;t seem particularly so to me. Also the idea of &lt;a href="http://xunitpatterns.com/Behavior%20Verification.html#Expected%20Behavior%20Specification"&gt;Expected Behaviour Specification&lt;/a&gt; (i.e. setting up expectations before the Exercise phase) has a couple of advantages :-&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Using &lt;a href="http://xunitpatterns.com/Test%20Spy.html"&gt;Test Spies&lt;/a&gt;, you have to (a) set up a stub so the mock object knows what value to return and (b) assert that the stubbed method was invoked the requisite number of times with the appropriate parameters. Whereas using &lt;a href=":http://xunitpatterns.com/Behavior%20Verification.html#Expected%20Behavior%20Specification"&gt;Expected Behaviour Specification&lt;/a&gt;, these are combined into setting up an expectation on the mock object. I think this results in terser code with less duplication.&lt;/li&gt;
		&lt;li&gt;Using &lt;a href=":http://xunitpatterns.com/Behavior%20Verification.html#Expected%20Behavior%20Specification"&gt;Expected Behaviour Specification&lt;/a&gt; means that the test can fail fast if an unexpected invocation is made against a mock object. Failing fast is generally a good idea, because you are more likely to be able to identify the root cause of the problem.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h4&gt;Sharing stubs in a context&lt;/h4&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;describe&lt;/span&gt; &lt;span class="constant"&gt;PostsController&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;on GET show&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
  &lt;span class="ident"&gt;before&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:each&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="attribute"&gt;@post&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;stub&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;a post&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="symbol"&gt;:to_param&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;
    &lt;span class="constant"&gt;Post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;stubs&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:find&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="attribute"&gt;@post&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

    &lt;span class="ident"&gt;get&lt;/span&gt; &lt;span class="symbol"&gt;:show&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:id&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="attribute"&gt;@post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_param&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;render_template&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:show&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;

  &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;should find and assign the given post&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="constant"&gt;Post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;have_received&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:find&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;with&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="attribute"&gt;@post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_param&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;assign_to&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:post&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;with&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="attribute"&gt;@post&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;I&amp;#8217;m going to struggle a bit when commenting on this code example for a couple of reasons :-&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;I dislike the use of &lt;code&gt;setup&lt;/code&gt; methods (&lt;code&gt;before&lt;/code&gt; in this &lt;a href="http://rspec.info/"&gt;RSpec&lt;/a&gt; example). I prefer to do my &lt;a href="http://blog.jayfields.com/2007/06/testing-inline-setup.html"&gt;setup in-line in the test&lt;/a&gt; to make the test as independent and as explicit as possible. I particularly dislike exercising the object under test within the &lt;code&gt;setup&lt;/code&gt; method. To me this seems like a more fundamental breakage of the &lt;a href="http://xunitpatterns.com/Four%20Phase%20Test.html"&gt;Four-Phase Test&lt;/a&gt; concept.&lt;/li&gt;
		&lt;li&gt;In this example, I would not want to assert that &lt;code&gt;Post.find&lt;/code&gt; has been called. &lt;a href="http://www.natpryce.com/"&gt;Nat Pryce&lt;/a&gt; (one of the authors of jMock) has a rule of thumb that says: &amp;#8220;&lt;a href="http://www.jmock.org/yoga.html"&gt;stub queries and expect commands&lt;/a&gt;&amp;#8221;. In this example, the call to &lt;code&gt;Post.find&lt;/code&gt; is clearly a query, so I would just stub it. I think about it like this: (a) stubbing &lt;code&gt;Post.find&lt;/code&gt; is setting up the environment and making the instance of &lt;code&gt;Post&lt;/code&gt; available; (b) the assertion then checks that the instance of &lt;code&gt;Post&lt;/code&gt; is assigned to the &lt;code&gt;@post&lt;/code&gt; instance variable; (c) the combination of (a) and (b) is enough to tell me that the &lt;code&gt;Post.find&lt;/code&gt; method has been called &amp;#8211; where else would the controller have got the instance of &lt;code&gt;Post&lt;/code&gt; from?&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;So I&amp;#8217;m not convinced I would need &lt;em&gt;Test Spies&lt;/em&gt; for this example.&lt;/p&gt;


	&lt;h4&gt;Sharing stubs between tests&lt;/h4&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;module &lt;/span&gt;&lt;span class="module"&gt;PostHelpers&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;stub_post&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;post_attrs&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;{})&lt;/span&gt;
    &lt;span class="ident"&gt;post_attrs&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;
      &lt;span class="symbol"&gt;:to_param&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt;
      &lt;span class="symbol"&gt;:published?&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="constant"&gt;true&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;
      &lt;span class="symbol"&gt;:title&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;a title&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
    &lt;span class="punct"&gt;}.&lt;/span&gt;&lt;span class="ident"&gt;update&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;post_attrs&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;stub&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;a post&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="ident"&gt;post_attrs&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;stub_post!&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;post_attrs&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;{})&lt;/span&gt;
    &lt;span class="ident"&gt;returning&lt;/span&gt; &lt;span class="ident"&gt;stub_post&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;post&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
      &lt;span class="constant"&gt;Post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;stubs&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:find&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ident"&gt;post&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="ident"&gt;describe&lt;/span&gt; &lt;span class="constant"&gt;PostsController&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
  &lt;span class="ident"&gt;include&lt;/span&gt; &lt;span class="constant"&gt;PostHelpers&lt;/span&gt;
  &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;should show a published post on GET show&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="ident"&gt;post&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;stub_post!&lt;/span&gt;
    &lt;span class="ident"&gt;get&lt;/span&gt; &lt;span class="symbol"&gt;:show&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:id&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ident"&gt;post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_param&lt;/span&gt;
    &lt;span class="constant"&gt;Post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;have_received&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:find&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;with&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_param&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;have_received&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:published?&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;render_template&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:show&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;assign_to&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:post&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;with&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;post&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="ident"&gt;describe&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;/posts/show&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
  &lt;span class="ident"&gt;include&lt;/span&gt; &lt;span class="constant"&gt;PostHelpers&lt;/span&gt;
  &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;should display a post&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="ident"&gt;assigns&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:post&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;stub_post&lt;/span&gt;
    &lt;span class="ident"&gt;render&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;/posts/show&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
    &lt;span class="ident"&gt;template&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;have_tag&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;h1&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="ident"&gt;assigns&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:post&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;title&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;ul&gt;
	&lt;li&gt;In this example, as above, I would stub the call to &lt;code&gt;Post.find&lt;/code&gt; rather than expect it.&lt;/li&gt;
		&lt;li&gt;I&amp;#8217;d also prefer to use a real &lt;code&gt;Post&lt;/code&gt; instance rather than a stub object. I&amp;#8217;d use some kind of &lt;a href="http://natpryce.com/articles/000714.html"&gt;Test Data Builder&lt;/a&gt; like &lt;a href="http://github.com/thoughtbot/factory_girl"&gt;factory_girl&lt;/a&gt; to remove any duplication rather than methods like those in the &lt;code&gt;PostHelpers&lt;/code&gt; module. While these &lt;code&gt;ActiveRecord&lt;/code&gt; objects aren&amp;#8217;t strictly &lt;em&gt;Value Objects&lt;/em&gt;, I can&amp;#8217;t help but think that &lt;a href="http://markmail.org/message/v6rvuvmfygaboruf"&gt;this quote from Nat Pryce&lt;/a&gt; is relevant :-&lt;/li&gt;
	&lt;/ul&gt;


	&lt;blockquote&gt;
		&lt;p&gt;Some languages might allow you to &lt;strong&gt;stub&lt;/strong&gt; a value, but what&amp;#8217;s the point? It is easier and less error prone to use the real type. If it&amp;#8217;s not easier to use the real type then, I think, you should investigate why. What can you do to make the value type easier to use?&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;&lt;a href="http://www.m3p.co.uk/blog/"&gt;Steve Freeman&lt;/a&gt; makes a similar point in &lt;a href="http://www.mockobjects.com/2007/04/test-smell-everything-is-mocked.html"&gt;Test Smell: Everything is mocked&lt;/a&gt;.&lt;/p&gt;


	&lt;h4&gt;Reusable matchers and assertions&lt;/h4&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="comment"&gt;# post.class.should have_received(:find).with(post.to_param)&lt;/span&gt;
&lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;find&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;post&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
&lt;span class="comment"&gt;# Post.should have_received(:new).with(post_attrs)&lt;/span&gt;
&lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;build&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;Post&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;post_attrs&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
&lt;span class="comment"&gt;# Post.should have_received(:new).with(post_attrs)&lt;/span&gt;
&lt;span class="comment"&gt;# post.should have_received(:save)&lt;/span&gt;
&lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;build_and_save&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;Post&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;post_attrs&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;I&amp;#8217;m not convinced that extracting the assertion part of an expectation is sensible, because it&amp;#8217;ll always need to be used in conjunction with the stub part of the same expectation.&lt;/p&gt;


	&lt;h3&gt;Syntax&lt;/h3&gt;


	&lt;p&gt;I think the suggested syntax extension is inconsistent with the existing Mocha &lt;span class="caps"&gt;API&lt;/span&gt; and a little clunky. See &lt;a href="http://groups.google.com/group/mocha-developer/msg/8d719b4aa729928f?hl=en"&gt;James Rosen&amp;#8217;s comment&lt;/a&gt; on the &lt;a href="http://groups.google.com/group/mocha-developer?hl=en"&gt;mailing list&lt;/a&gt;. Looking at the following examples given in the documentation :-&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="ident"&gt;assert_received&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;mock&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:to_s&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;assert_received&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;Radio&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:new&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;expect&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;expect&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;with&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;1041&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
  &lt;span class="ident"&gt;assert_received&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;radio&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:volume&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;expect&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;expect&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;with&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;11&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;twice&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;I think I&amp;#8217;d prefer to see something like :-&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="ident"&gt;assert_that&lt;/span&gt; &lt;span class="ident"&gt;mock&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;received&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:to_s&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;assert_that&lt;/span&gt; &lt;span class="constant"&gt;Radio&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;received&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:new&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;with&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;1041&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;assert_that&lt;/span&gt; &lt;span class="ident"&gt;radio&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;received&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:volume&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;with&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;11&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;twice&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Or something like :-&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="ident"&gt;mock&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;assert_received&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:to_s&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="constant"&gt;Radio&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;assert_received&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:new&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;with&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;1041&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;radio&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;assert_received&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:volume&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;with&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;11&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;twice&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Note that I haven&amp;#8217;t completely thought through the implementation implications of these suggestions i.e. whether they are even possible!&lt;/p&gt;


	&lt;h3&gt;Implementation&lt;/h3&gt;


	&lt;p&gt;The code looks good and, since Joe has written acceptance tests, there shouldn&amp;#8217;t be too much difficulty in doing a bit of refactoring. I like the idea of introducing a model for an &lt;a href="http://github.com/jferris/mocha/raw/spies/lib/mocha/invocation.rb"&gt;Invocation&lt;/a&gt; , but I think the &lt;code&gt;Invocation&lt;/code&gt; instances should be stored by the relevant &lt;code&gt;Mock&lt;/code&gt; instance rather than the &lt;code&gt;Mockery&lt;/code&gt;. Similarly I&amp;#8217;d push more of the logic in the &lt;a href="http://github.com/jferris/mocha/blob/4ba321eca2439ae5f55a611e2df716ea7af44ef4/lib/mocha/api.rb#L165"&gt;HaveReceived&lt;/a&gt; class into relevant objects. And I&amp;#8217;d like to avoid having to make &lt;code&gt;Expectation#invocation_count&lt;/code&gt; writeable.&lt;/p&gt;


	&lt;p&gt;One slight concern is what happens if someone mixes up &lt;em&gt;Expected Behaviour Specification&lt;/em&gt; expectations with &lt;em&gt;Test Spies&lt;/em&gt; stubs and assertions? I&amp;#8217;d probably at least want some acceptance tests to convince me that there are no complications on this front.&lt;/p&gt;


	&lt;h3&gt;Conclusion&lt;/h3&gt;


	&lt;p&gt;I&amp;#8217;m sure that some people find the changes useful, but I&amp;#8217;m not yet convinced I want to merge the &lt;a href="http://github.com/jferris/mocha/commits/spies"&gt;Test Spies&lt;/a&gt; changes into &lt;a href="http://mocha.rubyforge.org/"&gt;Mocha&lt;/a&gt;. Please feel free to try and convince me, either here in the &lt;a href="#comments"&gt;comments&lt;/a&gt; or in the &lt;a href="http://groups.google.com/group/mocha-developer/browse_thread/thread/3c3fba12cf313b12?hl=en"&gt;mailing list thread&lt;/a&gt;.&lt;/p&gt;</summary>
    <content type="html">&lt;h3&gt;Introduction&lt;/h3&gt;


	&lt;p&gt;Today I finally got round to looking at &lt;a href="http://github.com/jferris/mocha/commits/spies"&gt;Joe Ferris&amp;#8217; Test Spies fork&lt;/a&gt; of Mocha. Joe explained how Test Spies work and why he thinks they are useful in &lt;a href="http://robots.thoughtbot.com/post/159805295/spy-vs-spy"&gt;Spy vs spy&lt;/a&gt; on the ThoughtBot blog. I apologise to Joe for not getting round to this sooner.&lt;/p&gt;


	&lt;p&gt;I have a number of hesitations about merging these changes into &lt;a href="http://mocha.rubyforge.org/"&gt;Mocha&lt;/a&gt; as they stand. My thinking hasn&amp;#8217;t really crystallized, but in these situations I often find it&amp;#8217;s useful to force myself to try and explain myself in writing. Hopefully it&amp;#8217;ll also generate some feedback.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;d like to thank Joe for taking the time to fork Mocha and add this functionality. I&amp;#8217;m particularly grateful that he&amp;#8217;s taken the trouble to write a &lt;a href="http://github.com/jferris/mocha/raw/spies/test/acceptance/spy_test.rb"&gt;bunch of high-level acceptance tests&lt;/a&gt;.&lt;/p&gt;


	&lt;h3&gt;Concept&lt;/h3&gt;


	&lt;p&gt;In this section I&amp;#8217;ve tried to write up some comments on &lt;a href="http://robots.thoughtbot.com/post/159805295/spy-vs-spy"&gt;Joe&amp;#8217;s blog post&lt;/a&gt; under roughly the same headings :-&lt;/p&gt;


	&lt;h4&gt;Why would I let spies in my code?&lt;/h4&gt;


	&lt;p&gt;Joe correctly points out that setting up expectations before exercising the object under test is a bit of a departure from the traditional &lt;a href="http://xunitpatterns.com/Four%20Phase%20Test.html"&gt;Four-Phase Test&lt;/a&gt; regime. I can see how some people might see this as counter-intuitive, but it doesn&amp;#8217;t seem particularly so to me. Also the idea of &lt;a href="http://xunitpatterns.com/Behavior%20Verification.html#Expected%20Behavior%20Specification"&gt;Expected Behaviour Specification&lt;/a&gt; (i.e. setting up expectations before the Exercise phase) has a couple of advantages :-&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Using &lt;a href="http://xunitpatterns.com/Test%20Spy.html"&gt;Test Spies&lt;/a&gt;, you have to (a) set up a stub so the mock object knows what value to return and (b) assert that the stubbed method was invoked the requisite number of times with the appropriate parameters. Whereas using &lt;a href=":http://xunitpatterns.com/Behavior%20Verification.html#Expected%20Behavior%20Specification"&gt;Expected Behaviour Specification&lt;/a&gt;, these are combined into setting up an expectation on the mock object. I think this results in terser code with less duplication.&lt;/li&gt;
		&lt;li&gt;Using &lt;a href=":http://xunitpatterns.com/Behavior%20Verification.html#Expected%20Behavior%20Specification"&gt;Expected Behaviour Specification&lt;/a&gt; means that the test can fail fast if an unexpected invocation is made against a mock object. Failing fast is generally a good idea, because you are more likely to be able to identify the root cause of the problem.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h4&gt;Sharing stubs in a context&lt;/h4&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;describe&lt;/span&gt; &lt;span class="constant"&gt;PostsController&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;on GET show&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
  &lt;span class="ident"&gt;before&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:each&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="attribute"&gt;@post&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;stub&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;a post&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="symbol"&gt;:to_param&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;
    &lt;span class="constant"&gt;Post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;stubs&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:find&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="attribute"&gt;@post&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

    &lt;span class="ident"&gt;get&lt;/span&gt; &lt;span class="symbol"&gt;:show&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:id&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="attribute"&gt;@post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_param&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;render_template&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:show&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;

  &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;should find and assign the given post&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="constant"&gt;Post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;have_received&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:find&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;with&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="attribute"&gt;@post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_param&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;assign_to&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:post&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;with&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="attribute"&gt;@post&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;I&amp;#8217;m going to struggle a bit when commenting on this code example for a couple of reasons :-&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;I dislike the use of &lt;code&gt;setup&lt;/code&gt; methods (&lt;code&gt;before&lt;/code&gt; in this &lt;a href="http://rspec.info/"&gt;RSpec&lt;/a&gt; example). I prefer to do my &lt;a href="http://blog.jayfields.com/2007/06/testing-inline-setup.html"&gt;setup in-line in the test&lt;/a&gt; to make the test as independent and as explicit as possible. I particularly dislike exercising the object under test within the &lt;code&gt;setup&lt;/code&gt; method. To me this seems like a more fundamental breakage of the &lt;a href="http://xunitpatterns.com/Four%20Phase%20Test.html"&gt;Four-Phase Test&lt;/a&gt; concept.&lt;/li&gt;
		&lt;li&gt;In this example, I would not want to assert that &lt;code&gt;Post.find&lt;/code&gt; has been called. &lt;a href="http://www.natpryce.com/"&gt;Nat Pryce&lt;/a&gt; (one of the authors of jMock) has a rule of thumb that says: &amp;#8220;&lt;a href="http://www.jmock.org/yoga.html"&gt;stub queries and expect commands&lt;/a&gt;&amp;#8221;. In this example, the call to &lt;code&gt;Post.find&lt;/code&gt; is clearly a query, so I would just stub it. I think about it like this: (a) stubbing &lt;code&gt;Post.find&lt;/code&gt; is setting up the environment and making the instance of &lt;code&gt;Post&lt;/code&gt; available; (b) the assertion then checks that the instance of &lt;code&gt;Post&lt;/code&gt; is assigned to the &lt;code&gt;@post&lt;/code&gt; instance variable; (c) the combination of (a) and (b) is enough to tell me that the &lt;code&gt;Post.find&lt;/code&gt; method has been called &amp;#8211; where else would the controller have got the instance of &lt;code&gt;Post&lt;/code&gt; from?&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;So I&amp;#8217;m not convinced I would need &lt;em&gt;Test Spies&lt;/em&gt; for this example.&lt;/p&gt;


	&lt;h4&gt;Sharing stubs between tests&lt;/h4&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;module &lt;/span&gt;&lt;span class="module"&gt;PostHelpers&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;stub_post&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;post_attrs&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;{})&lt;/span&gt;
    &lt;span class="ident"&gt;post_attrs&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;
      &lt;span class="symbol"&gt;:to_param&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt;
      &lt;span class="symbol"&gt;:published?&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="constant"&gt;true&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;
      &lt;span class="symbol"&gt;:title&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;a title&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
    &lt;span class="punct"&gt;}.&lt;/span&gt;&lt;span class="ident"&gt;update&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;post_attrs&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;stub&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;a post&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="ident"&gt;post_attrs&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;stub_post!&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;post_attrs&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;{})&lt;/span&gt;
    &lt;span class="ident"&gt;returning&lt;/span&gt; &lt;span class="ident"&gt;stub_post&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;post&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
      &lt;span class="constant"&gt;Post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;stubs&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:find&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ident"&gt;post&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="ident"&gt;describe&lt;/span&gt; &lt;span class="constant"&gt;PostsController&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
  &lt;span class="ident"&gt;include&lt;/span&gt; &lt;span class="constant"&gt;PostHelpers&lt;/span&gt;
  &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;should show a published post on GET show&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="ident"&gt;post&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;stub_post!&lt;/span&gt;
    &lt;span class="ident"&gt;get&lt;/span&gt; &lt;span class="symbol"&gt;:show&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:id&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ident"&gt;post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_param&lt;/span&gt;
    &lt;span class="constant"&gt;Post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;have_received&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:find&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;with&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_param&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;post&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;have_received&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:published?&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;render_template&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:show&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;assign_to&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:post&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;with&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;post&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="ident"&gt;describe&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;/posts/show&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
  &lt;span class="ident"&gt;include&lt;/span&gt; &lt;span class="constant"&gt;PostHelpers&lt;/span&gt;
  &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;should display a post&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="ident"&gt;assigns&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:post&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;stub_post&lt;/span&gt;
    &lt;span class="ident"&gt;render&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;/posts/show&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
    &lt;span class="ident"&gt;template&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;have_tag&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;h1&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="ident"&gt;assigns&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:post&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;title&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;ul&gt;
	&lt;li&gt;In this example, as above, I would stub the call to &lt;code&gt;Post.find&lt;/code&gt; rather than expect it.&lt;/li&gt;
		&lt;li&gt;I&amp;#8217;d also prefer to use a real &lt;code&gt;Post&lt;/code&gt; instance rather than a stub object. I&amp;#8217;d use some kind of &lt;a href="http://natpryce.com/articles/000714.html"&gt;Test Data Builder&lt;/a&gt; like &lt;a href="http://github.com/thoughtbot/factory_girl"&gt;factory_girl&lt;/a&gt; to remove any duplication rather than methods like those in the &lt;code&gt;PostHelpers&lt;/code&gt; module. While these &lt;code&gt;ActiveRecord&lt;/code&gt; objects aren&amp;#8217;t strictly &lt;em&gt;Value Objects&lt;/em&gt;, I can&amp;#8217;t help but think that &lt;a href="http://markmail.org/message/v6rvuvmfygaboruf"&gt;this quote from Nat Pryce&lt;/a&gt; is relevant :-&lt;/li&gt;
	&lt;/ul&gt;


	&lt;blockquote&gt;
		&lt;p&gt;Some languages might allow you to &lt;strong&gt;stub&lt;/strong&gt; a value, but what&amp;#8217;s the point? It is easier and less error prone to use the real type. If it&amp;#8217;s not easier to use the real type then, I think, you should investigate why. What can you do to make the value type easier to use?&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;&lt;a href="http://www.m3p.co.uk/blog/"&gt;Steve Freeman&lt;/a&gt; makes a similar point in &lt;a href="http://www.mockobjects.com/2007/04/test-smell-everything-is-mocked.html"&gt;Test Smell: Everything is mocked&lt;/a&gt;.&lt;/p&gt;


	&lt;h4&gt;Reusable matchers and assertions&lt;/h4&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="comment"&gt;# post.class.should have_received(:find).with(post.to_param)&lt;/span&gt;
&lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;find&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;post&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
&lt;span class="comment"&gt;# Post.should have_received(:new).with(post_attrs)&lt;/span&gt;
&lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;build&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;Post&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;post_attrs&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
&lt;span class="comment"&gt;# Post.should have_received(:new).with(post_attrs)&lt;/span&gt;
&lt;span class="comment"&gt;# post.should have_received(:save)&lt;/span&gt;
&lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;build_and_save&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;Post&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;post_attrs&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;I&amp;#8217;m not convinced that extracting the assertion part of an expectation is sensible, because it&amp;#8217;ll always need to be used in conjunction with the stub part of the same expectation.&lt;/p&gt;


	&lt;h3&gt;Syntax&lt;/h3&gt;


	&lt;p&gt;I think the suggested syntax extension is inconsistent with the existing Mocha &lt;span class="caps"&gt;API&lt;/span&gt; and a little clunky. See &lt;a href="http://groups.google.com/group/mocha-developer/msg/8d719b4aa729928f?hl=en"&gt;James Rosen&amp;#8217;s comment&lt;/a&gt; on the &lt;a href="http://groups.google.com/group/mocha-developer?hl=en"&gt;mailing list&lt;/a&gt;. Looking at the following examples given in the documentation :-&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="ident"&gt;assert_received&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;mock&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:to_s&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;assert_received&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;Radio&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:new&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;expect&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;expect&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;with&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;1041&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
  &lt;span class="ident"&gt;assert_received&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;radio&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:volume&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;expect&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;expect&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;with&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;11&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;twice&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;I think I&amp;#8217;d prefer to see something like :-&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="ident"&gt;assert_that&lt;/span&gt; &lt;span class="ident"&gt;mock&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;received&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:to_s&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;assert_that&lt;/span&gt; &lt;span class="constant"&gt;Radio&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;received&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:new&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;with&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;1041&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;assert_that&lt;/span&gt; &lt;span class="ident"&gt;radio&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;received&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:volume&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;with&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;11&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;twice&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Or something like :-&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="ident"&gt;mock&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;assert_received&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:to_s&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="constant"&gt;Radio&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;assert_received&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:new&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;with&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;1041&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;radio&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;assert_received&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:volume&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;with&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;11&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;twice&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Note that I haven&amp;#8217;t completely thought through the implementation implications of these suggestions i.e. whether they are even possible!&lt;/p&gt;


	&lt;h3&gt;Implementation&lt;/h3&gt;


	&lt;p&gt;The code looks good and, since Joe has written acceptance tests, there shouldn&amp;#8217;t be too much difficulty in doing a bit of refactoring. I like the idea of introducing a model for an &lt;a href="http://github.com/jferris/mocha/raw/spies/lib/mocha/invocation.rb"&gt;Invocation&lt;/a&gt; , but I think the &lt;code&gt;Invocation&lt;/code&gt; instances should be stored by the relevant &lt;code&gt;Mock&lt;/code&gt; instance rather than the &lt;code&gt;Mockery&lt;/code&gt;. Similarly I&amp;#8217;d push more of the logic in the &lt;a href="http://github.com/jferris/mocha/blob/4ba321eca2439ae5f55a611e2df716ea7af44ef4/lib/mocha/api.rb#L165"&gt;HaveReceived&lt;/a&gt; class into relevant objects. And I&amp;#8217;d like to avoid having to make &lt;code&gt;Expectation#invocation_count&lt;/code&gt; writeable.&lt;/p&gt;


	&lt;p&gt;One slight concern is what happens if someone mixes up &lt;em&gt;Expected Behaviour Specification&lt;/em&gt; expectations with &lt;em&gt;Test Spies&lt;/em&gt; stubs and assertions? I&amp;#8217;d probably at least want some acceptance tests to convince me that there are no complications on this front.&lt;/p&gt;


	&lt;h3&gt;Conclusion&lt;/h3&gt;


	&lt;p&gt;I&amp;#8217;m sure that some people find the changes useful, but I&amp;#8217;m not yet convinced I want to merge the &lt;a href="http://github.com/jferris/mocha/commits/spies"&gt;Test Spies&lt;/a&gt; changes into &lt;a href="http://mocha.rubyforge.org/"&gt;Mocha&lt;/a&gt;. Please feel free to try and convince me, either here in the &lt;a href="#comments"&gt;comments&lt;/a&gt; or in the &lt;a href="http://groups.google.com/group/mocha-developer/browse_thread/thread/3c3fba12cf313b12?hl=en"&gt;mailing list thread&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/floehopper-blog/~4/TWROFmPw8Yo" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://blog.floehopper.org/articles/2009/09/14/mocha-test-spies</feedburner:origLink></entry>
</feed>
