<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Floehopper: Tag unit</title>
    <link>http://blog.floehopper.org/articles/tag/unit?tag=unit</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>thoughts on the bergy bits of life</description>
    <item>
      <title>Nasty Ruby Bug Affecting Test::Unit</title>
      <description>&lt;h3 id="introduction"&gt;Introduction&lt;/h3&gt;


	&lt;p&gt;Some time ago, while I was pair-programming with him, &lt;a href="http://blog.seagul.co.uk"&gt;Chris&lt;/a&gt; alerted me to a &lt;a href="http://www.ruby-lang.org/"&gt;Ruby&lt;/a&gt; bug he&amp;#8217;d come across which was interfering with the diagnosis of a bug in our application. Since then I&amp;#8217;ve tried to find out more about it, but couldn&amp;#8217;t find much, so I&amp;#8217;ve done a bit of investigation and thought I&amp;#8217;d post it here in case it&amp;#8217;s useful to anyone else. The bug has long since been fixed, but I&amp;#8217;m sure there are still people our there with the &lt;a href="#affected-versions"&gt;affected versions&lt;/a&gt; of Ruby 1.8.6.&lt;/p&gt;


	&lt;h3 id="ruby-bug"&gt;Ruby bug&lt;/h3&gt;


	&lt;p&gt;As far as I understand it, the bug is in Ruby&amp;#8217;s &lt;a href="http://ruby-doc.org/core/classes/Kernel.html#M005958"&gt;&lt;code&gt;Kernel.at_exit&lt;/code&gt;&lt;/a&gt; hook. A call to &lt;a href="http://ruby-doc.org/core/classes/Kernel.html#M005956"&gt;&lt;code&gt;Kernel.exit(false)&lt;/code&gt;&lt;/a&gt; should cause the process to exit with an &lt;strong&gt;exit status of 1&lt;/strong&gt; indicating the process did not complete successfully. The bug means that calling &lt;a href="http://ruby-doc.org/core/classes/Kernel.html#M005956"&gt;&lt;code&gt;Kernel.exit(false)&lt;/code&gt;&lt;/a&gt; from within &lt;a href="http://ruby-doc.org/core/classes/Kernel.html#M005958"&gt;&lt;code&gt;Kernel.at_exit&lt;/code&gt;&lt;/a&gt; incorrectly causes the process to exit with an &lt;strong&gt;exit status of 0&lt;/strong&gt;.&lt;/p&gt;


	&lt;p&gt;The most relevant bug report is &lt;a href="http://rubyforge.org/tracker/?func=detail&amp;#38;atid=1698&amp;#38;aid=9300&amp;#38;group_id=426"&gt;#9300&lt;/a&gt; and the most relevant mailing list thread is made up of:- &lt;a href="http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/10746"&gt;[ruby-core:10746]&lt;/a&gt;, &lt;a href="http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/10748"&gt;[ruby-core:10748]&lt;/a&gt;, &lt;a href="http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/10760"&gt;[ruby-core:10760]&lt;/a&gt;.&lt;/p&gt;


The fix seems to be in changeset 12126&amp;#8230;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;r12126 | nobu | 2007-03-23 16:53:42 +0000 (Fri, 23 Mar 2007) | 9 lines

* eval.c (ruby_cleanup): exit by SystemExit and SignalException in END
  block.  [ruby-core:10609]

* test/ruby/test_beginendblock.rb (test_should_propagate_exit_code):
  test for exit in END block.  [ruby-core:10760]

* test/ruby/test_beginendblock.rb (test_should_propagate_signaled):
  test for signal in END block.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;h3 class="implications"&gt;Implications for Test::Unit &amp;#38; Rake::TestTask&lt;/h3&gt;


	&lt;p&gt;The &lt;a href="#ruby-bug"&gt;bug&lt;/a&gt; has some important consequences. &lt;a href="http://www.ruby-doc.org/stdlib/libdoc/test/unit/rdoc/classes/Test/Unit.html"&gt;&lt;code&gt;Test::Unit&lt;/code&gt;&lt;/a&gt; makes use of this mechanism to report test failures. Unfortunately, the bug means that a &lt;a href="http://www.ruby-doc.org/stdlib/libdoc/test/unit/rdoc/classes/Test/Unit.html"&gt;&lt;code&gt;Test::Unit&lt;/code&gt;&lt;/a&gt; process will always return an &lt;strong&gt;exit status of 0&lt;/strong&gt; even when there have been test failures.&lt;/p&gt;


From &lt;code&gt;test/unit.rb&lt;/code&gt;:
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;at_exit&lt;/span&gt; &lt;span class="keyword"&gt;do&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="constant"&gt;Test&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Unit&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;run?&lt;/span&gt;
    &lt;span class="ident"&gt;exit&lt;/span&gt; &lt;span class="constant"&gt;Test&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Unit&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;AutoRunner&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;run&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;This in turn means that a &lt;a href="http://rake.rubyforge.org/classes/Rake/TestTask.html"&gt;&lt;code&gt;Rake::TestTask&lt;/code&gt;&lt;/a&gt; process will also always return an &lt;strong&gt;exit status of 0&lt;/strong&gt; even when there have been test failures. This is significant, because many &lt;a href="http://martinfowler.com/articles/continuousIntegration.html"&gt;continuous integration&lt;/a&gt; systems rely on &lt;a href="http://rake.rubyforge.org/classes/Rake/TestTask.html"&gt;&lt;code&gt;Rake::TestTask&lt;/code&gt;&lt;/a&gt; processes returning an &lt;strong&gt;exit status of 1&lt;/strong&gt; to indicate that there have been test failures. Thus you will get false positive passing builds &amp;#8211; not good.&lt;/p&gt;


	&lt;h3 id="affected-versions"&gt;Affected versions of Ruby&lt;/h3&gt;


	&lt;p&gt;I&amp;#8217;ve built and installed a number of versions of Ruby and run tests on them to try to establish which ones are affected. Although they aren&amp;#8217;t comprehensive, here are the results&amp;#8230;&lt;/p&gt;


	&lt;table&gt;
		&lt;tr style="background:#ddd;"&gt;
			&lt;td&gt; affected? &lt;/td&gt;
			&lt;td&gt; version &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td style="text-align:center;"&gt;&lt;code&gt;N&lt;/code&gt; &lt;/td&gt;
			&lt;td&gt; &lt;code&gt;ruby 1.8.4 (2005-12-24) [i686-darwin8.10.3]&lt;/code&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td style="text-align:center;"&gt;&lt;code&gt;N&lt;/code&gt; &lt;/td&gt;
			&lt;td&gt; &lt;code&gt;ruby 1.8.5 (2006-08-25) [i686-darwin8.10.3]&lt;/code&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td style="text-align:center;"&gt;&lt;code&gt;N&lt;/code&gt; &lt;/td&gt;
			&lt;td&gt; &lt;code&gt;ruby 1.8.5 (2007-03-16 patchlevel 37) [i686-darwin8.10.3]&lt;/code&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td style="text-align:center;"&gt;&lt;code&gt;N&lt;/code&gt; &lt;/td&gt;
			&lt;td&gt; &lt;code&gt;ruby 1.8.5 (2008-03-03 patchlevel 115) [i686-darwin8.10.3]&lt;/code&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr style="color:red;"&gt;
			&lt;td style="text-align:center;"&gt;&lt;code&gt;Y&lt;/code&gt; &lt;/td&gt;
			&lt;td&gt; &lt;code&gt;ruby 1.8.6 (2007-02-17 patchlevel 0) [i686-darwin8.10.3]&lt;/code&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr style="color:red;"&gt;
			&lt;td style="text-align:center;"&gt;&lt;code&gt;Y&lt;/code&gt; &lt;/td&gt;
			&lt;td&gt; &lt;code&gt;ruby 1.8.6 (2007-03-13 patchlevel 0) [i686-darwin8.10.3]&lt;/code&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr style="color:red;"&gt;
			&lt;td style="text-align:center;"&gt;&lt;code&gt;Y&lt;/code&gt; &lt;/td&gt;
			&lt;td&gt; &lt;code&gt;ruby 1.8.6 (2007-03-16 patchlevel 2) [i686-darwin8.10.3]&lt;/code&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr style="color:red;"&gt;
			&lt;td style="text-align:center;"&gt;&lt;code&gt;Y&lt;/code&gt; &lt;/td&gt;
			&lt;td&gt; &lt;code&gt;ruby 1.8.6 (2007-03-19 patchlevel 4) [i686-darwin8.10.3]&lt;/code&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr style="color:red;"&gt;
			&lt;td style="text-align:center;"&gt;&lt;code&gt;Y&lt;/code&gt; &lt;/td&gt;
			&lt;td&gt; &lt;code&gt;ruby 1.8.6 (2007-05-22 patchlevel 5) [i686-darwin8.10.3]&lt;/code&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr style="color:red;"&gt;
			&lt;td style="text-align:center;"&gt;&lt;code&gt;Y&lt;/code&gt; &lt;/td&gt;
			&lt;td&gt; &lt;code&gt;ruby 1.8.6 (2007-05-22 patchlevel 6) [i686-darwin8.10.3]&lt;/code&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr style="color:red;"&gt;
			&lt;td style="text-align:center;"&gt;&lt;code&gt;Y&lt;/code&gt; &lt;/td&gt;
			&lt;td&gt; &lt;code&gt;ruby 1.8.6 (2007-05-22 patchlevel 7) [i686-darwin8.10.3]&lt;/code&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td style="text-align:center;"&gt;&lt;code&gt;N&lt;/code&gt; &lt;/td&gt;
			&lt;td&gt; &lt;code&gt;ruby 1.8.6 (2007-05-22 patchlevel 8) [i686-darwin8.10.3]&lt;/code&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td style="text-align:center;"&gt;&lt;code&gt;N&lt;/code&gt; &lt;/td&gt;
			&lt;td&gt; &lt;code&gt;ruby 1.8.6 (2007-05-23 patchlevel 9) [i686-darwin8.10.3]&lt;/code&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td style="text-align:center;"&gt;&lt;code&gt;N&lt;/code&gt; &lt;/td&gt;
			&lt;td&gt; &lt;code&gt;ruby 1.8.6 (2007-05-23 patchlevel 10) [i686-darwin8.10.3]&lt;/code&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td style="text-align:center;"&gt;&lt;code&gt;N&lt;/code&gt; &lt;/td&gt;
			&lt;td&gt; &lt;code&gt;ruby 1.8.6 (2007-08-22 patchlevel 50) [i686-darwin8.10.3]&lt;/code&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td style="text-align:center;"&gt;&lt;code&gt;N&lt;/code&gt; &lt;/td&gt;
			&lt;td&gt; &lt;code&gt;ruby 1.9.0 (2007-11-28 patchlevel 0) [i686-darwin8.10.3]&lt;/code&gt; &lt;/td&gt;
		&lt;/tr&gt;
	&lt;/table&gt;</description>
      <pubDate>Sat, 05 Apr 2008 00:10:06 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:3aa53475-6a90-4cf6-915b-ff8804ff5d61</guid>
      <author>James Mead</author>
      <link>http://blog.floehopper.org/articles/2008/04/05/nasty-ruby-bug-affecting-test-unit</link>
      <category>ruby</category>
      <category>bug</category>
      <category>test</category>
      <category>unit</category>
      <category>exit</category>
      <category>code</category>
      <category>hook</category>
      <category>testing</category>
      <category>continuous</category>
      <category>integration</category>
    </item>
    <item>
      <title>Testing tidbits</title>
      <description>&lt;p&gt;A couple of useful nuggets came up while I was &lt;a href="http://c2.com/cgi/wiki?PairProgramming"&gt;pair programming&lt;/a&gt; with &lt;a href="http://interblah.net/"&gt;James&lt;/a&gt; today.&lt;/p&gt;


	&lt;p&gt;Firstly, James had an interesting new use of the Mocha parameter matcher &lt;a href="http://mocha.rubyforge.org/classes/Mocha/ParameterMatchers.html#M000009"&gt;&lt;code&gt;anything&lt;/code&gt;&lt;/a&gt;, which reminded me of &lt;a href="http://joe.truemesh.com/"&gt;Joe Walnes&lt;/a&gt; and his &lt;a href="http://joe.truemesh.com/blog//000511.html"&gt;Flexible JUnit assertions with assertThat()&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Normally &lt;code&gt;anything&lt;/code&gt; is used to determine what parameters are matched by an expectation&amp;#8230;&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="constant"&gt;Product&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;:do_stuff&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="string"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="ident"&gt;anything&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;But James was passing &lt;code&gt;anything&lt;/code&gt; into a method to indicate that the value of that parameter was irrelevant in the context of the test. The kind of thing you might already do using &lt;code&gt;nil&lt;/code&gt;...&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="constant"&gt;Product&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;do_stuff&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="ident"&gt;anything&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;I wonder if this idea could be extended by having a kind of &lt;a href="http://www.youtube.com/watch?v=Kk-G2twc_M4"&gt;holy hand-grenade&lt;/a&gt; object which &amp;#8220;blows up&amp;#8221; by raising an &lt;a href="http://www.ruby-doc.org/stdlib/libdoc/test/unit/rdoc/classes/Test/Unit/AssertionFailedError.html"&gt;&lt;code&gt;AssertionFailedError&lt;/code&gt;&lt;/a&gt; when any method is invoked on it&amp;#8230;?&lt;/p&gt;


	&lt;p&gt;Secondly, we were running all our tests using the default rake task when we discovered a test that was hanging. The standard rake test task output wasn&amp;#8217;t very helpful in identifying which test was stuck (just rows of dots)...&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;Started
.....................................................................
.....................................................................
.....................................................................
......................................................&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Interrupting the process and examining the stack trace didn&amp;#8217;t help either (the relevant stack frames had been collapsed)...&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;   ... 24 levels...
  from /opt/local/lib/ruby/1.8/test/unit/autorunner.rb:216:in `run'
  from /opt/local/lib/ruby/1.8/test/unit/autorunner.rb:12:in `run'
  from /opt/local/lib/ruby/1.8/test/unit.rb:278
  from /opt/local/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake/...&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;So we set the output to verbose which outputs the name of each test as it starts. From this we could work out which was the offending test&amp;#8230;&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;  TESTOPTS=&amp;quot;-v&amp;quot; rake

  test_should_do_something(NaughtyTest): .
  test_should_do_something_else(NaughtyTest): .
  test_should_do_something_ideally_without_hanging(NaughtyTest): .&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
      <pubDate>Tue, 25 Sep 2007 22:03:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:61189aa5-4796-4257-9c98-93b989eb2605</guid>
      <author>James Mead</author>
      <link>http://blog.floehopper.org/articles/2007/09/25/testing-tidbits</link>
      <category>anything</category>
      <category>matcher</category>
      <category>rake</category>
      <category>test</category>
      <category>unit</category>
      <category>options</category>
      <category>verbose</category>
      <category>testopts</category>
    </item>
    <item>
      <title>Stub Queries and Expect Commands</title>
      <description>&lt;p&gt;In &lt;a href="http://metaclass.org/2006/12/22/making-a-mockery-of-activerecord"&gt;Making a Mockery of ActiveRecord&lt;/a&gt;, a single test has multiple expectations set up for accessor methods&amp;#8230;&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="ident"&gt;specify&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;should create EmailMessages and Subscriptions when include_subscribers is true&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="attribute"&gt;@message&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;include_subscribers&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;true&lt;/span&gt;
    &lt;span class="attribute"&gt;@message&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should_receive&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:lists&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;and_return&lt;/span&gt;&lt;span class="punct"&gt;([&lt;/span&gt;&lt;span class="attribute"&gt;@list&lt;/span&gt;&lt;span class="punct"&gt;])&lt;/span&gt;
    &lt;span class="attribute"&gt;@message&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should_receive&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:campaign&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;span class="ident"&gt;and_return&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="attribute"&gt;@campaign&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="attribute"&gt;@list&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should_receive&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:people&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;and_return&lt;/span&gt;&lt;span class="punct"&gt;([&lt;/span&gt;&lt;span class="attribute"&gt;@person&lt;/span&gt;&lt;span class="punct"&gt;])&lt;/span&gt;
    &lt;span class="attribute"&gt;@person&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should_receive&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:campaigns&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;and_return&lt;/span&gt;&lt;span class="punct"&gt;([])&lt;/span&gt;

    &lt;span class="attribute"&gt;@person&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should_receive&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:subscriptions&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;and_return&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="attribute"&gt;@subscriptions&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="attribute"&gt;@subscriptions&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should_receive&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:create&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;and_return&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;nil&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="attribute"&gt;@campaign&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should_receive&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:people&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;and_return&lt;/span&gt;&lt;span class="punct"&gt;([])&lt;/span&gt;

    &lt;span class="ident"&gt;message&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;generate&lt;/span&gt; &lt;span class="comment"&gt;# I think this line is missing from the original test&lt;/span&gt;
    &lt;span class="attribute"&gt;@message&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should_have&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;email_messages&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;ve found &lt;a href="http://nat.truemesh.com/"&gt;Nat Pryce&amp;#8217;s&lt;/a&gt; rule of thumb &amp;#8211; &lt;cite&gt;stub queries and expect commands&lt;/cite&gt; &amp;#8211; to be very useful in reducing the brittleness of tests (see &lt;a href="http://www.jmock.org/yoga.html"&gt;Yoga for Your Unit Tests&lt;/a&gt;).&lt;/p&gt;


	&lt;p&gt;A &lt;em&gt;query&lt;/em&gt; in this context is a method which does not change the state of the object on which it is called. The accessor methods definitely fall into this category, so I would stub them, not set expectations for them. The one &lt;em&gt;command&lt;/em&gt; method in the above example which merits an expectation is the call to &lt;code&gt;create&lt;/code&gt; on &lt;code&gt;@subscriptions&lt;/code&gt;.&lt;/p&gt;


	&lt;p&gt;However, I prefer to use in-memory ActiveRecord objects instead of mocks or stubs wherever possible. So I&amp;#8217;d write something more like this (using &lt;a href="http://www.ruby-doc.org/stdlib/libdoc/test/unit/rdoc/index.html"&gt;Test::Unit&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="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;test_should_create_email_messages_and_subscriptions_when_include_subscribers_is_true&lt;/span&gt;
    &lt;span class="ident"&gt;subscriptions&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;person&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Person&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="symbol"&gt;:campaigns&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;[])&lt;/span&gt;
    &lt;span class="ident"&gt;person&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;:subscriptions&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;returns&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;subscriptions&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;list&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;List&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="symbol"&gt;:people&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;person&lt;/span&gt;&lt;span class="punct"&gt;])&lt;/span&gt;
    &lt;span class="ident"&gt;campaign&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Campaign&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="symbol"&gt;:people&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;[])&lt;/span&gt;
    &lt;span class="ident"&gt;message&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Message&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="symbol"&gt;:lists&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;list&lt;/span&gt;&lt;span class="punct"&gt;],&lt;/span&gt; &lt;span class="symbol"&gt;:campaign&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ident"&gt;campaign&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;message&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;include_subscribers&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;true&lt;/span&gt;

    &lt;span class="ident"&gt;subscriptions&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;:create&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

    &lt;span class="ident"&gt;message&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;generate&lt;/span&gt;
    &lt;span class="ident"&gt;assert_equal&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;message&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;email_messages&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 haven&amp;#8217;t actually run this &amp;#8211; so it&amp;#8217;s quite likely there are errors in it, but you should get the general idea. The &lt;code&gt;person.stubs&lt;/code&gt; line is necessary to avoid the type checking that &lt;a href="http://www.lukeredpath.co.uk/"&gt;Luke Redpath&lt;/a&gt; mentions in &lt;a href="http://metaclass.org/2006/12/22/making-a-mockery-of-activerecord#comment-7"&gt;his comment&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;More thoughts &lt;a href="http://blog.floehopper.org/articles/2006/12/23/tell-dont-ask"&gt;here&lt;/a&gt;.&lt;/p&gt;</description>
      <pubDate>Sat, 23 Dec 2006 20:02:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:39963017-3d76-480c-a1f9-068eb78b8570</guid>
      <author>James Mead</author>
      <link>http://blog.floehopper.org/articles/2006/12/23/stub-queries-and-expect-commands</link>
      <category>mock</category>
      <category>stub</category>
      <category>query</category>
      <category>command</category>
      <category>activerecord</category>
      <category>unit</category>
      <category>test</category>
    </item>
    <item>
      <title>Fixtures, mock objects or in-memory ActiveRecord objects?</title>
      <description>&lt;p&gt;&lt;a href="http://metaclass.org/"&gt;Wilson Bilkovich&lt;/a&gt; has posted an article about &lt;a href="http://metaclass.org/2006/12/22/making-a-mockery-of-activerecord"&gt;mocking ActiveRecord objects&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;A new method &lt;code&gt;mock_model&lt;/code&gt; is defined that builds a mock object which will respond the same way as a real &lt;code&gt;ActiveRecord&lt;/code&gt; object. As I understand it, this means he can replace&amp;#8230;&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="attribute"&gt;@campaign&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;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;campaign&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
  &lt;span class="attribute"&gt;@campaign&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="symbol"&gt;:is_a?&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;and_return&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;true&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="attribute"&gt;@campaign&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="symbol"&gt;:new_record?&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;and_return&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;false&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="attribute"&gt;@campaign&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="symbol"&gt;:id&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;and_return&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;rand&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;1000&lt;/span&gt;&lt;span class="punct"&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;with&amp;#8230;&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="ident"&gt;mock_model&lt;/span&gt; &lt;span class="symbol"&gt;:campaign&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Although &lt;a href="http://blog.floehopper.org/articles/2006/06/27/rails-fixtures-help-or-hindrance"&gt;I agree&lt;/a&gt; with him that using fixtures is not a good idea, why not use a real &lt;code&gt;ActiveRecord&lt;/code&gt; object&amp;#8230;&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="attribute"&gt;@campaign&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Campaign&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Sometimes due to the way &lt;code&gt;ActiveRecord&lt;/code&gt; couples your models to the database, it becomes essential to have a model in the database and not just in memory. In which case why not just do this&amp;#8230;&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="attribute"&gt;@campaign&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Campaign&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;create!&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;I&amp;#8217;ve written up a couple more thoughts &lt;a href="http://blog.floehopper.org/articles/2006/12/23/stub-queries-and-expect-commands"&gt;here&lt;/a&gt; and &lt;a href="http://blog.floehopper.org/articles/2006/12/23/tell-dont-ask"&gt;here&lt;/a&gt;.&lt;/p&gt;</description>
      <pubDate>Sat, 23 Dec 2006 20:00:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:865dc197-829e-401b-af2e-4c1e4b7b2794</guid>
      <author>James Mead</author>
      <link>http://blog.floehopper.org/articles/2006/12/23/fixtures-mock-objects-or-in-memory-activerecord-objects</link>
      <category>mock</category>
      <category>object</category>
      <category>ruby</category>
      <category>test</category>
      <category>unit</category>
      <category>stub</category>
      <category>fixture</category>
    </item>
    <item>
      <title>Mocha in Java using bytecode manipulation</title>
      <description>&lt;p&gt;My former colleague and &lt;a href="http://asm.objectweb.org/"&gt;bytecode&lt;/a&gt; maestro &lt;a href="http://digital-compulsion.blogspot.com/"&gt;Stacy Curl&lt;/a&gt; has an &lt;a href="http://digital-compulsion.blogspot.com/2006/09/java-mocking-without-injection-same.html"&gt;interesting article&lt;/a&gt; explaining how it would be possible to implement &lt;a href="http://mocha.rubyforge.org"&gt;Mocha&lt;/a&gt; in &lt;a href="http://java.sun.com/"&gt;Java&lt;/a&gt; using experience from his &lt;a href="http://picounit.codehaus.org/"&gt;PicoUnit&lt;/a&gt; project.&lt;/p&gt;


	&lt;p&gt;It&amp;#8217;s good to be reminded that meta-programming is possible in Java, but just a bit more effort.&lt;/p&gt;</description>
      <pubDate>Sat, 16 Sep 2006 14:43:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:afe10f9a-e930-4e80-9e10-d8c65f682f4e</guid>
      <author>James Mead</author>
      <link>http://blog.floehopper.org/articles/2006/09/16/mocha-in-java-using-bytecode-manipulation</link>
      <category>ruby</category>
      <category>java</category>
      <category>bytecode</category>
      <category>mocha</category>
      <category>mock</category>
      <category>pico</category>
      <category>unit</category>
      <category>dependency</category>
      <category>injection</category>
      <category>meta</category>
      <category>programming</category>
    </item>
    <item>
      <title>ThoughtWorks team uses Mocha</title>
      <description>&lt;p&gt;It&amp;#8217;s good to see that a team from &lt;a href="http://www.thoughtworks.com"&gt;my old company&lt;/a&gt; has caught the &lt;a href="http://mocha.rubyforge.org"&gt;Mocha&lt;/a&gt; bug&amp;#8230;&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://jayfields.blogspot.com/"&gt;Jay Fields&lt;/a&gt; describes how his team have been using Mocha to achieve &lt;a href="http://jayfields.blogspot.com/2006/09/rubyrails-unit-testing-in-less-than-1.html"&gt;Ruby on Rails Unit Testing in less than 1 second&lt;/a&gt;.&lt;/p&gt;</description>
      <pubDate>Tue, 05 Sep 2006 06:35:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:a589217f-72aa-42f3-a160-233fbd43c51b</guid>
      <author>James Mead</author>
      <link>http://blog.floehopper.org/articles/2006/09/05/thoughtworks-team-uses-mocha</link>
      <category>mocha</category>
      <category>ruby</category>
      <category>rails</category>
      <category>mock</category>
      <category>unit</category>
      <category>test</category>
      <category>thoughtworks</category>
    </item>
    <item>
      <title>Unit tests - Can 100% coverage be a bad thing?</title>
      <description>&lt;p&gt;Consider what happens when you have &amp;#8220;unit&amp;#8221; tests that go more than one unit deep (in call stack terms) i.e. tests that don’t mock out all units external to the unit under test. Although such tests may give you good coverage&amp;#8230;&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;They usually require complex setup code which means it can be hard to identify the intention of a test. It’s generally accepted that self-documenting code is a good thing &amp;#8211; unit tests with clear intent can be one of the best ways to achieve such documentation.&lt;/li&gt;
		&lt;li&gt;They are by definition more fragile than a true unit test, because they&amp;#8217;re vulnerable to changes in multiple units. Also, the more of these tests you have, the more likely it is that a number of tests will be vulnerable to changes in a single unit.&lt;/li&gt;
		&lt;li&gt;When they fail, it often proves difficult to identify the reason for the failure. This difficulty is often a consequence of the unclear intention of the test. A failure caused by an exception thrown deep in the call stack (rather than an assertion in the test) can lead to similar problems.&lt;/li&gt;
		&lt;li&gt;They usually take longer to run, partly by definition because they execute more code, but also because they often run against a real database or other external resource.&lt;/li&gt;
		&lt;li&gt;All of these issues will act as a barrier to &lt;a href="http://www.refactoring.com/"&gt;refactoring&lt;/a&gt;. Faced with the choice of performing a sensible refactoring that breaks a number of such tests or adding duplicate logic to a system, many developers will understandably choose to add the duplicate logic. This can start a spiral that leads to the rapid build up of crippling &lt;a href="http://www.martinfowler.com/bliki/TechnicalDebt.html"&gt;technical debt&lt;/a&gt;.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;I call that a bad thing!&lt;/p&gt;


	&lt;p&gt;Update: I see that Tim Bacon has already &lt;a href="http://coachspot.blogspot.com/2003_11_01_coachspot_archive.html#106758276083501884"&gt;touched on this subject&lt;/a&gt;.&lt;/p&gt;</description>
      <pubDate>Fri, 14 May 2004 12:12:37 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:15cb09c0-2a7e-4c98-b0b9-c11dfb85bf14</guid>
      <author>James Mead</author>
      <link>http://blog.floehopper.org/articles/2004/05/14/unit-tests-can-100-coverage-be-a-bad-thing</link>
      <category>testing</category>
      <category>unit</category>
      <category>coverage</category>
    </item>
  </channel>
</rss>
