tag:www.rhnh.net,2008:/testingTesting - Xavier Shay's Blog2011-09-03T22:46:34ZEnkiXavier Shaynotreal@rhnh.nettag:www.rhnh.net,2008:Post/8502011-07-30T05:45:00Z2011-09-03T22:46:34ZInterface Mocking<p><strong><span class="caps">UPDATE</span>:</strong> This is a gem now: <a href="https://github.com/xaviershay/rspec-fire">rspec-fire</a> The code in the gem is better than that presented here.</p>
<p>Here is a screencast I put together in response to a recent Destroy All Software screencast on <a href="https://www.destroyallsoftware.com/screencasts/catalog/test-isolation-and-refactoring">test isolation and refactoring</a>, showing off an idea I’ve been tinkering around with for automatic validation of your implicit interfaces that you stub in tests.</p>
<p><iframe src="http://player.vimeo.com/video/27079042?title=0&byline=0&portrait=0&color=FFFACD" width="600" height="338" frameborder="0"></iframe><p><a href="http://vimeo.com/27079042">Interface Mocking screencast</a>.</p></p>
<p>Here is the code for <code>InterfaceMocking</code>:</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt>9<tt>
</tt><strong>10</strong><tt>
</tt>11<tt>
</tt>12<tt>
</tt>13<tt>
</tt>14<tt>
</tt>15<tt>
</tt>16<tt>
</tt>17<tt>
</tt>18<tt>
</tt>19<tt>
</tt><strong>20</strong><tt>
</tt>21<tt>
</tt>22<tt>
</tt>23<tt>
</tt>24<tt>
</tt>25<tt>
</tt>26<tt>
</tt>27<tt>
</tt>28<tt>
</tt>29<tt>
</tt><strong>30</strong><tt>
</tt>31<tt>
</tt>32<tt>
</tt>33<tt>
</tt>34<tt>
</tt>35<tt>
</tt>36<tt>
</tt>37<tt>
</tt>38<tt>
</tt>39<tt>
</tt><strong>40</strong><tt>
</tt>41<tt>
</tt>42<tt>
</tt>43<tt>
</tt>44<tt>
</tt>45<tt>
</tt>46<tt>
</tt>47<tt>
</tt>48<tt>
</tt>49<tt>
</tt><strong>50</strong><tt>
</tt>51<tt>
</tt>52<tt>
</tt>53<tt>
</tt>54<tt>
</tt>55<tt>
</tt>56<tt>
</tt>57<tt>
</tt>58<tt>
</tt>59<tt>
</tt><strong>60</strong><tt>
</tt>61<tt>
</tt>62<tt>
</tt>63<tt>
</tt>64<tt>
</tt>65<tt>
</tt>66<tt>
</tt>67<tt>
</tt>68<tt>
</tt>69<tt>
</tt><strong>70</strong><tt>
</tt>71<tt>
</tt>72<tt>
</tt>73<tt>
</tt>74<tt>
</tt>75<tt>
</tt>76<tt>
</tt>77<tt>
</tt>78<tt>
</tt>79<tt>
</tt><strong>80</strong><tt>
</tt>81<tt>
</tt>82<tt>
</tt>83<tt>
</tt>84<tt>
</tt>85<tt>
</tt>86<tt>
</tt>87<tt>
</tt>88<tt>
</tt>89<tt>
</tt><strong>90</strong><tt>
</tt>91<tt>
</tt>92<tt>
</tt>93<tt>
</tt>94<tt>
</tt>95<tt>
</tt>96<tt>
</tt>97<tt>
</tt>98<tt>
</tt>99<tt>
</tt><strong>100</strong><tt>
</tt>101<tt>
</tt>102<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="r">module</span> <span class="cl">InterfaceMocking</span><tt>
</tt><tt>
</tt> <span class="c"># Returns a new interface double. This is equivalent to an RSpec double,</span><tt>
</tt> <span class="c"># stub or, mock, except that if the class passed as the first parameter</span><tt>
</tt> <span class="c"># is loaded it will raise if you try to set an expectation or stub on</span><tt>
</tt> <span class="c"># a method that the class has not implemented.</span><tt>
</tt> <span class="r">def</span> <span class="fu">interface_double</span>(stubbed_class, methods = {})<tt>
</tt> <span class="co">InterfaceDouble</span>.new(stubbed_class, methods)<tt>
</tt> <span class="r">end</span><tt>
</tt><tt>
</tt> <span class="r">module</span> <span class="cl">InterfaceDoubleMethods</span><tt>
</tt><tt>
</tt> include <span class="co">RSpec</span>::<span class="co">Matchers</span><tt>
</tt><tt>
</tt> <span class="r">def</span> <span class="fu">should_receive</span>(method_name)<tt>
</tt> ensure_implemented(method_name)<tt>
</tt> <span class="r">super</span><tt>
</tt> <span class="r">end</span><tt>
</tt><tt>
</tt> <span class="r">def</span> <span class="fu">should_not_receive</span>(method_name)<tt>
</tt> ensure_implemented(method_name)<tt>
</tt> <span class="r">super</span><tt>
</tt> <span class="r">end</span><tt>
</tt><tt>
</tt> <span class="r">def</span> <span class="fu">stub!</span>(method_name)<tt>
</tt> ensure_implemented(method_name)<tt>
</tt> <span class="r">super</span><tt>
</tt> <span class="r">end</span><tt>
</tt><tt>
</tt> <span class="r">def</span> <span class="fu">ensure_implemented</span>(*method_names)<tt>
</tt> <span class="r">if</span> recursive_const_defined?(<span class="co">Object</span>, <span class="iv">@__stubbed_class__</span>)<tt>
</tt> recursive_const_get(<span class="co">Object</span>, <span class="iv">@__stubbed_class__</span>).<tt>
</tt> should implement(method_names, <span class="iv">@__checked_methods__</span>)<tt>
</tt> <span class="r">end</span><tt>
</tt> <span class="r">end</span><tt>
</tt><tt>
</tt> <span class="r">def</span> <span class="fu">recursive_const_get</span> object, name<tt>
</tt> name.split(<span class="s"><span class="dl">'</span><span class="k">::</span><span class="dl">'</span></span>).inject(<span class="co">Object</span>) {|klass,name| klass.const_get name }<tt>
</tt> <span class="r">end</span><tt>
</tt><tt>
</tt> <span class="r">def</span> <span class="fu">recursive_const_defined?</span> object, name<tt>
</tt> !!name.split(<span class="s"><span class="dl">'</span><span class="k">::</span><span class="dl">'</span></span>).inject(<span class="co">Object</span>) {|klass,name|<tt>
</tt> <span class="r">if</span> klass && klass.const_defined?(name)<tt>
</tt> klass.const_get name<tt>
</tt> <span class="r">end</span><tt>
</tt> }<tt>
</tt> <span class="r">end</span><tt>
</tt><tt>
</tt> <span class="r">end</span><tt>
</tt><tt>
</tt> <span class="r">class</span> <span class="cl">InterfaceDouble</span> < <span class="co">RSpec</span>::<span class="co">Mocks</span>::<span class="co">Mock</span><tt>
</tt><tt>
</tt> include <span class="co">InterfaceDoubleMethods</span><tt>
</tt><tt>
</tt> <span class="r">def</span> <span class="fu">initialize</span>(stubbed_class, *args)<tt>
</tt> args << {} <span class="r">unless</span> <span class="co">Hash</span> === args.last<tt>
</tt><tt>
</tt> <span class="iv">@__stubbed_class__</span> = stubbed_class<tt>
</tt> <span class="iv">@__checked_methods__</span> = <span class="sy">:public_instance_methods</span><tt>
</tt> ensure_implemented *args.last.keys<tt>
</tt><tt>
</tt> <span class="c"># __declared_as copied from rspec/mocks definition of `double`</span><tt>
</tt> args.last[<span class="sy">:__declared_as</span>] = <span class="s"><span class="dl">'</span><span class="k">InterfaceDouble</span><span class="dl">'</span></span><tt>
</tt> <span class="r">super</span>(stubbed_class, *args)<tt>
</tt> <span class="r">end</span><tt>
</tt><tt>
</tt> <span class="r">end</span><tt>
</tt><span class="r">end</span><tt>
</tt><tt>
</tt><span class="co">RSpec</span>::<span class="co">Matchers</span>.define <span class="sy">:implement</span> <span class="r">do</span> |expected_methods, checked_methods|<tt>
</tt> match <span class="r">do</span> |stubbed_class|<tt>
</tt> unimplemented_methods(<tt>
</tt> stubbed_class,<tt>
</tt> expected_methods,<tt>
</tt> checked_methods<tt>
</tt> ).empty?<tt>
</tt> <span class="r">end</span><tt>
</tt><tt>
</tt> <span class="r">def</span> <span class="fu">unimplemented_methods</span>(stubbed_class, expected_methods, checked_methods)<tt>
</tt> implemented_methods = stubbed_class.send(checked_methods)<tt>
</tt> unimplemented_methods = expected_methods - implemented_methods<tt>
</tt> <span class="r">end</span><tt>
</tt><tt>
</tt> failure_message_for_should <span class="r">do</span> |stubbed_class|<tt>
</tt> <span class="s"><span class="dl">"</span><span class="k">%s does not publicly implement:</span><span class="ch">\n</span><span class="k">%s</span><span class="dl">"</span></span> % [<tt>
</tt> stubbed_class,<tt>
</tt> unimplemented_methods(<tt>
</tt> stubbed_class,<tt>
</tt> expected_methods,<tt>
</tt> checked_methods<tt>
</tt> ).sort.map {|x|<tt>
</tt> <span class="s"><span class="dl">"</span><span class="k"> </span><span class="il"><span class="idl">#{</span>x<span class="idl">}</span></span><span class="dl">"</span></span><tt>
</tt> }.join(<span class="s"><span class="dl">"</span><span class="ch">\n</span><span class="dl">"</span></span>)<tt>
</tt> ]<tt>
</tt> <span class="r">end</span><tt>
</tt><span class="r">end</span><tt>
</tt><tt>
</tt><span class="co">RSpec</span>.configure <span class="r">do</span> |config|<tt>
</tt><tt>
</tt> config.include <span class="co">InterfaceMocking</span><tt>
</tt><tt>
</tt><span class="r">end</span><tt>
</tt></pre></td>
</tr></table>
tag:www.rhnh.net,2008:Post/8112009-12-29T00:27:00Z2009-12-29T00:24:28ZRuby debugging with puts, tap and Hirb<p>I use <code>puts</code> heaps when debugging. Combined with <code>tap</code>, it’s pretty handy. You can jump right in the middle of a method chain without having to move things around into variables.</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">x = long.chain.of.methods.tap {|x| puts x }.to.do.something.with<tt>
</tt></pre></td>
</tr></table>
<p>I thought hey why don’t I merge the two? And for bonus points, add in Hirb’s table display to format my models nicely. These are fairly personal customizations, and aren’t specific to a project, so I put them in my own <code>~/.railsrc</code> file rather than each project.</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt>9<tt>
</tt><strong>10</strong><tt>
</tt>11<tt>
</tt>12<tt>
</tt>13<tt>
</tt>14<tt>
</tt>15<tt>
</tt>16<tt>
</tt>17<tt>
</tt>18<tt>
</tt>19<tt>
</tt><strong>20</strong><tt>
</tt>21<tt>
</tt>22<tt>
</tt>23<tt>
</tt>24<tt>
</tt>25<tt>
</tt>26<tt>
</tt>27<tt>
</tt>28<tt>
</tt>29<tt>
</tt><strong>30</strong><tt>
</tt>31<tt>
</tt>32<tt>
</tt>33<tt>
</tt>34<tt>
</tt>35<tt>
</tt>36<tt>
</tt>37<tt>
</tt>38<tt>
</tt>39<tt>
</tt><strong>40</strong><tt>
</tt>41<tt>
</tt>42<tt>
</tt>43<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="c"># config/initializers/developer_specific_customizations.rb</span><tt>
</tt><span class="r">if</span> <span class="s"><span class="dl">%w(</span><span class="k">development test</span><span class="dl">)</span></span>.include?(<span class="co">Rails</span>.env)<tt>
</tt> railsrc = <span class="s"><span class="dl">"</span><span class="il"><span class="idl">#{</span><span class="co">ENV</span>[<span class="s"><span class="dl">'</span><span class="k">HOME</span><span class="dl">'</span></span>]<span class="idl">}</span></span><span class="k">/.railsrc</span><span class="dl">"</span></span><tt>
</tt> load(railsrc) <span class="r">if</span> <span class="co">File</span>.exist?(railsrc)<tt>
</tt><span class="r">end</span><tt>
</tt><tt>
</tt><span class="c"># ~/.railsrc</span><tt>
</tt>require <span class="s"><span class="dl">'</span><span class="k">hirb</span><span class="dl">'</span></span><tt>
</tt><tt>
</tt><span class="co">Hirb</span>.enable <span class="sy">:pager</span> => <span class="pc">false</span><tt>
</tt><tt>
</tt><span class="r">class</span> <span class="cl">Object</span><tt>
</tt> <span class="r">def</span> <span class="fu">tapp</span>(prefix = <span class="pc">nil</span>, &block)<tt>
</tt> block ||= lambda {|x| x }<tt>
</tt><tt>
</tt> tap <span class="r">do</span> |x|<tt>
</tt> value = block[x]<tt>
</tt> value = <span class="co">Hirb</span>::<span class="co">View</span>.formatter.format_output(value) || value.inspect<tt>
</tt><tt>
</tt> <span class="r">if</span> prefix<tt>
</tt> print prefix<tt>
</tt> <span class="r">if</span> value.lines.count > <span class="i">1</span><tt>
</tt> print <span class="s"><span class="dl">"</span><span class="k">:</span><span class="ch">\n</span><span class="dl">"</span></span><tt>
</tt> <span class="r">else</span><tt>
</tt> print <span class="s"><span class="dl">"</span><span class="k">: </span><span class="dl">"</span></span><tt>
</tt> <span class="r">end</span><tt>
</tt> <span class="r">end</span><tt>
</tt> puts value<tt>
</tt> <span class="r">end</span><tt>
</tt> <span class="r">end</span><tt>
</tt><span class="r">end</span><tt>
</tt><tt>
</tt><span class="c"># Usage (in your spec files, perhaps?)</span><tt>
</tt><span class="s"><span class="dl">"</span><span class="k">hello</span><span class="dl">"</span></span>.tapp <span class="c"># => hello</span><tt>
</tt><span class="s"><span class="dl">"</span><span class="k">hello</span><span class="dl">"</span></span>.tapp(<span class="s"><span class="dl">'</span><span class="k">a</span><span class="dl">'</span></span>) <span class="c"># => a - "hello</span><tt>
</tt><span class="s"><span class="dl">"</span><span class="k">hello</span><span class="dl">"</span></span>.tapp(&<span class="sy">:length</span>) <span class="c"># => 5</span><tt>
</tt><span class="co">MyModel</span>.first.tapp <span class="c"># =></span><tt>
</tt><span class="c"># +----+-------------------------+</span><tt>
</tt><span class="c"># | id | created_at |</span><tt>
</tt><span class="c"># +----+-------------------------+</span><tt>
</tt><span class="c"># | 7 | 2009-12-29 00:15:56 UTC |</span><tt>
</tt><span class="c"># +----+-------------------------+</span><tt>
</tt><span class="c"># 1 row in set</span><tt>
</tt></pre></td>
</tr></table>
tag:www.rhnh.net,2008:Post/7962009-03-12T08:45:03Z2009-03-12T08:45:03ZFaster rails testing with ruby_fork<p>A long running test suite isn’t the problem. Your build server can take care of that. A second or two here or there, no one notices.</p>
<p><strong>The killer wait is in the red/green/refactor loop.</strong> You’re only running one or two tests, and an extra second can mean the difference between getting into flow or switching to twitter. And you know what kills you in rails?</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">$ time ruby -e '' -r config/environment.rb<tt>
</tt><tt>
</tt>real 0m3.784s<tt>
</tt>user 0m2.707s<tt>
</tt>sys 0m0.687s<tt>
</tt></pre></td>
</tr></table>
<p>Yep, the environment. That’s a lot of overhead to be waiting for everytime you run a test, especially since it’s the same code every time! You fix this with a clever script called <code>ruby_fork</code> that’s included in the <a href="http://zentest.rubyforge.org/ZenTest/">ZenTest</a> package. It loads up your environment, then just chills out, waiting. You send a ruby file to it, and it forks itself (the process containing the environment) to execute that file. The beauty of this is that forking is really quick, and it leaves a pristine copy of the environment around for the next test run.</p>
<p>‘Environment’ doesn’t just have be <code>environment.rb</code>, for bonus points you can load up <code>test_helper.rb</code>, which will also load your testing framework into memory. In fact, you can preload any ruby code at all – <code>ruby_fork</code> isn’t rails specific.</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt>9<tt>
</tt><strong>10</strong><tt>
</tt>11<tt>
</tt>12<tt>
</tt>13<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">$ ruby_fork -r test/test_helper.rb &<tt>
</tt>/opt/local/bin/ruby_fork Running as PID 526 on 9084<tt>
</tt><tt>
</tt>$ time ruby_fork_client -r test/unit/your_test.rb<tt>
</tt>Started<tt>
</tt>...<tt>
</tt>Finished in 0.565636 seconds. # Aside: this time is bollocks<tt>
</tt><tt>
</tt>3 tests, 4 assertions, 0 failures, 0 errors<tt>
</tt><tt>
</tt>real 0m0.972s # This is the time you're interested in<tt>
</tt>user 0m0.225s<tt>
</tt>sys 0m0.035s<tt>
</tt></pre></td>
</tr></table>
<p>That’s fantastic, though you’ll notice in newer versions of rails your application code is not reloaded. By default your test environment caches classes – which normally isn’t a problem except that newer rails versions also eager load those classes (so they’re loaded when you load enviornment.rb). You can fix this by clearing out the eager load paths in your test environment file:</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="c"># config/environments/test.rb</span><tt>
</tt>config.eager_load_paths = []<tt>
</tt></pre></td>
</tr></table>
<p>On my machine this gets individual test runs down from about 4 seconds to less than 1 second. You can sell that to your boss as a four-fold productivity increase.</p>tag:www.rhnh.net,2008:Post/7952009-03-10T08:33:15Z2009-03-10T08:33:15ZTesting Glue Code<p><a href="http://github.com/xaviershay/db2s3">db2s3</a> combines together 3 external dependencies – your database, the filesystem, and Amazon’s S3 service. It has 1 conditional in the main code path (and it’s not even an important one). The classic unit testing approach of “stub everything” provides little benefit.</p>
<p>Unit testing is good for ensuring complex code paths execute properly, that edge cases are properly explored, and for answering the question “what broke?”. For trivial glue code, none of these are of particular benefit. There are no complex code paths or edge cases, and it will be quickly obvious what broke. In fact, the most likely thing to “break” (or change) over time isn’t your code, but the external services it is sticking together, which stubs cannot protect you from. Considering the high relative cost of stubbing out all your dependencies, unit testing becomes an expensive way of testing something quite simple.</p>
<p>For glue code, integration tests are the best solution. Glue code needs to stick, and integration tests ensures that it does. Here is the only test that matters from db2s3:</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt>9<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">it <span class="s"><span class="dl">'</span><span class="k">can save and restore a backup to S3</span><span class="dl">'</span></span> <span class="r">do</span><tt>
</tt> db2s3 = <span class="co">DB2S3</span>.new<tt>
</tt> load_schema<tt>
</tt> <span class="co">Person</span>.create!(<span class="sy">:name</span> => <span class="s"><span class="dl">"</span><span class="k">Baxter</span><span class="dl">"</span></span>)<tt>
</tt> db2s3.full_backup<tt>
</tt> drop_schema<tt>
</tt> db2s3.restore<tt>
</tt> <span class="co">Person</span>.find_by_name(<span class="s"><span class="dl">"</span><span class="k">Baxter</span><span class="dl">"</span></span>).should_not be_nil<tt>
</tt><span class="r">end</span><tt>
</tt></pre></td>
</tr></table>
<p>This test costs money to run since it hits the live S3 service, but only in the academic sense. The question you need to ask is “would I pay one cent to have confidence my backup solution works?”</p>
<p>Always remember why your are testing. <strong>Unit tests are a focussed tool, and not always necessary.</strong></p>tag:www.rhnh.net,2008:Post/7892008-11-14T18:47:00Z2008-11-14T18:47:46ZUnique data in dm-sweatshop<p><code>dm-sweatshop</code> is how you set up test data for your datamapper apps. Standard practice is to generate random data that follows a pattern:</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="co">User</span>.fix {{<tt>
</tt> <span class="sy">:login</span> => <span class="rx"><span class="dl">/</span><span class="ch">\w</span><span class="k">+</span><span class="dl">/</span></span>.gen<tt>
</tt>}}<tt>
</tt><tt>
</tt>new_user = <span class="co">User</span>.gen<tt>
</tt></pre></td>
</tr></table>
<p>Let’s not now debate whether or not random data in tests is a good idea. What’s more important is that the above code should make you uneasy if login is supposed to be unique. There was a hack in sweatshop that would try recreating the data if you had a uniqueness constraint on login and it was invalid, but it was exactly that: a hack. As of a few days ago (what will be 0.9.7), you need to be more explicit if you want unique data. It’s pretty easy:</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">include <span class="co">DataMapper</span>::<span class="co">Sweatshop</span>::<span class="co">Unique</span><tt>
</tt><tt>
</tt><span class="co">User</span>.fix {{<tt>
</tt> <span class="sy">:login</span> => unique { <span class="rx"><span class="dl">/</span><span class="ch">\w</span><span class="k">+</span><span class="dl">/</span></span>.gen }<tt>
</tt>}}<tt>
</tt></pre></td>
</tr></table>
<p>Tada! You can also easily get non-random unique data by providing a block with one parameter. <a href="http://github.com/sam/dm-more/tree/master/dm-sweatshop/README.textile">Check the <span class="caps">README</span></a> for this and other cool things you can do.</p>tag:www.rhnh.net,2008:Post/7862008-10-01T06:11:00Z2008-10-01T06:11:51ZIntegration testing with Cucumber, RSpec and Thinking Sphinx<p>Ideally you would want to include sphinx in your integration tests. It’s really just like your database. In practice, this is problematic. Ensuring the DB is started and triggering a re-index after each model load is doable, if slow, with a small bit of hacking of thinking sphinx (hint – change the initializer for the <code>ThinkingSphinx::Configuration</code> to allow you to specify the environment). Here’s the rub though – if you’re using transactional fixtures the sphinx indexer won’t be able to see any of your data! Turning that off can really slow down your tests, and once you add in the re-indexing time you’re going to be making a few cups of coffee while they run.</p>
<p>One approach I’ve been taking is to stub out the <code>search</code> methods with <a href="http://github.com/btakita/rr/tree/master">RR</a>. I know, I know, stubbing in your integration tests is evil. I’m being pragmatic here. For most applications your search is trivial (find me results for this keyword), and if you unit test your <code>define_index</code> block you’re pretty well covered. To go one step further you could unit test your controllers with an expect on the search method, or have a separate suite of non-transactional integration tests running against sphinx. I like the latter, but haven’t done it yet.</p>
<p>Enough talk! Here’s the magic you need to get it working with <a href="http://github.com/aslakhellesoy/cucumber/tree/master">cucumber</a>:</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt>9<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="c"># features/steps/env.rb</span><tt>
</tt>require <span class="s"><span class="dl">'</span><span class="k">rr</span><span class="dl">'</span></span><tt>
</tt><span class="co">Cucumber</span>::<span class="co">Rails</span>::<span class="co">World</span>.send(<span class="sy">:include</span>, <span class="co">RR</span>::<span class="co">Adapters</span>::<span class="co">RRMethods</span>)<tt>
</tt><tt>
</tt><span class="c"># features/steps/*_steps.rb</span><tt>
</tt><span class="co">Given</span> <span class="rx"><span class="dl">/</span><span class="k">a car with model '(</span><span class="ch">\w</span><span class="k">+)' exists</span><span class="dl">/</span></span> <span class="r">do</span> |model|<tt>
</tt> car = <span class="co">Car</span>.create!(<span class="sy">:model</span> => model)<tt>
</tt> stub(<span class="co">Car</span>).search(model) { [car] }<tt>
</tt><span class="r">end</span><tt>
</tt></pre></td>
</tr></table>
tag:www.rhnh.net,2008:Post/3362007-12-20T22:18:00Z2007-12-20T22:18:46ZTest setup broken in Rails 2.0.2<p>Some changes went into rails 2.0.2 that mean the <code>setup</code> method in test subclasses won’t get called. Here’s how it went down:</p>
<ul>
<li><a href="http://dev.rubyonrails.org/changeset/8392">8392</a> broke it</li>
<li><a href="http://dev.rubyonrails.org/changeset/8430">8430</a> tagged 2.0.2</li>
<li><a href="http://dev.rubyonrails.org/changeset/8442">8442</a> reverted 8392</li>
<li><a href="http://dev.rubyonrails.org/changeset/8445">8445</a> added a test so it doesn’t break again</li>
</ul>
<p>You can see some code illustrating the problem in 8445. This affects two plugins that we’re using – <a href="http://nubyonrails.com/articles/test-your-helpers">helper_test</a> and <a href="http://code.google.com/p/activemessaging/wiki/ActiveMessaging">activemessaging</a>.</p>
<p>For the helper test, the work around is to rename your helper test setup methods to <code>setup_with_fixtures</code>.</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="r">def</span> <span class="fu">setup_with_fixtures</span><tt>
</tt> <span class="r">super</span><tt>
</tt><span class="r">end</span><tt>
</tt></pre></td>
</tr></table>
<p>For activemessaging, add the following line to the setup of your functionals that are failing (<a href="http://groups.google.com/group/activemessaging-discuss/browse_frm/thread/d0c7f025b2855463">from the mailing list</a>):</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="co">ActiveMessaging</span>.reload_activemessaging<tt>
</tt></pre></td>
</tr></table>
tag:www.rhnh.net,2008:Post/3572006-06-10T06:45:00Z2007-12-29T05:54:28ZTesting rails<p>I was working on creating functional tests for some of my code today, a task made ridiculously easy by rails. To add extra value, I added an assertion (from <a href="http://scottraymond.net/articles/2005/09/20/rails-xhtml-validation">Scott Raymond</a>) to validate my markup against the w3c online validator:</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt>9<tt>
</tt><strong>10</strong><tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="r">def</span> <span class="fu">assert_valid_markup</span>(markup=<span class="iv">@response</span>.body)<tt>
</tt> <span class="r">if</span> <span class="co">ENV</span>[<span class="s"><span class="dl">"</span><span class="k">TEST_MARKUP</span><span class="dl">"</span></span>]<tt>
</tt> require <span class="s"><span class="dl">"</span><span class="k">net/http</span><span class="dl">"</span></span><tt>
</tt> response = <span class="co">Net</span>::<span class="co">HTTP</span>.start(<span class="s"><span class="dl">"</span><span class="k">validator.w3.org</span><span class="dl">"</span></span>) <span class="r">do</span> |w3c|<tt>
</tt> query = <span class="s"><span class="dl">"</span><span class="k">fragment=</span><span class="dl">"</span></span> + <span class="co">CGI</span>.escape(markup) + <span class="s"><span class="dl">"</span><span class="k">&output=xml</span><span class="dl">"</span></span><tt>
</tt> w3c.post2(<span class="s"><span class="dl">"</span><span class="k">/check</span><span class="dl">"</span></span>, query)<tt>
</tt> <span class="r">end</span><tt>
</tt> assert_equal <span class="s"><span class="dl">"</span><span class="k">Valid</span><span class="dl">"</span></span>, response[<span class="s"><span class="dl">"</span><span class="k">x-w3c-validator-status</span><span class="dl">"</span></span>]<tt>
</tt> <span class="r">end</span><tt>
</tt><span class="r">end</span><tt>
</tt></pre></td>
</tr></table>
<p>The <span class="caps">ENV</span> test means it isn’t run by default since it slows down my tests considerably, but I don’t want to move markup checks out of the functional tests because that’s where they belong. Next step is to validate locally, which I’ve heard you can do with <span class="caps">HTML</span> Tidy.</p>
<p>Another problem is testing code that relies on <code>DateTime.now</code>, since this is a singleton call and not easily mockable.</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt>9<tt>
</tt><strong>10</strong><tt>
</tt>11<tt>
</tt>12<tt>
</tt>13<tt>
</tt>14<tt>
</tt>15<tt>
</tt>16<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="r">def</span> <span class="fu">pin_time</span><tt>
</tt> time = <span class="co">DateTime</span>.now<tt>
</tt> <span class="co">DateTime</span>.class_eval <span class="s"><span class="dl"><<-EOS</span></span><span class="s"><span class="k"><tt>
</tt> def self.now<tt>
</tt> DateTime.parse("</span><span class="il"><span class="idl">#{</span>time<span class="idl">}</span></span><span class="k">")<tt>
</tt> end</span><span class="dl"><tt>
</tt> EOS</span></span><tt>
</tt> <span class="r">yield</span> time<tt>
</tt><span class="r">end</span><tt>
</tt><tt>
</tt><span class="c"># Usage</span><tt>
</tt>pin_time <span class="r">do</span> |test_time|<tt>
</tt> assert_equal test_time, <span class="co">DateTime</span>.now<tt>
</tt> sleep <span class="i">2</span><tt>
</tt> assert_equal test_time, <span class="co">DateTime</span>.now<tt>
</tt><span class="r">end</span><tt>
</tt></pre></td>
</tr></table>
<p>I haven’t found a neat way of resetting the behaviour of <code>now</code>. Using <code>load 'date.rb'</code> works but produces warnings for redefined constants. I couldn’t get either aliasing the original method, undefining the new one, or even just calling <code>Date.now</code> to work.</p>
<p><strong><span class="caps">UPDATE</span>:</strong> Ah, how young I was. A better way to do this is to use a library like <a href="http://mocha.rubyforge.org">mocha</a></p>