tag:www.rhnh.net,2008:/webrat Webrat - Xavier Shay's Blog 2009-09-17T17:08:26Z Enki Xavier Shay notreal@rhnh.net tag:www.rhnh.net,2008:Post/797 2009-05-18T16:30:00Z 2009-09-17T17:08:26Z Selenium, webrat and the firefox beta <p>*UPDATE: * Latest version of webrat (0.5.3, maybe earlier) includes a fixed version of selenium, so you shouldn&#8217;t need this hack.</p> <p>I needed a few hacks to get selenium running with webrat.</p> <p>First, make sure you are running at least 0.4.4 of webrat. Don&#8217;t make the same mistake I did and upgrade your gem version, but not the plugin installed in vendor/plugins.</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' }">gem install webrat<tt> </tt>gem install selenium-client<tt> </tt>gem install bmabey-database_cleaner --source=http://gems.github.com<tt> </tt></pre></td> </tr></table> <p>There is a trick to get Firefox 3.5 beta working. The selenium server package with webrat 0.4.4 only supports <span class="caps">FF 3</span>.0.*. Follow these instructions, patching the jar that is packaged with webrat (vendor/selenium-server.jar) so that the extensions that selenium uses will be valid for the new FF.</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></pre></td> <td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">cd vendor/ # In webrat dir<tt> </tt>jar xf selenium-server.jar \<tt> </tt>customProfileDirCUSTFFCHROME/extensions/readystate@openqa.org/install.rdf<tt> </tt>jar xf selenium-server.jar \<tt> </tt>customProfileDirCUSTFFCHROME/extensions/{538F0036-F358-4f84-A764-89FB437166B4}/install.rdf<tt> </tt>jar xf selenium-server.jar \<tt> </tt>customProfileDirCUSTFFCHROME/extensions/\{503A0CD4-EDC8-489b-853B-19E0BAA8F0A4\}/install.rdf <tt> </tt>jar xf selenium-server.jar \<tt> </tt>customProfileDirCUSTFF/extensions/readystate\@openqa.org/install.rdf <tt> </tt>jar xf selenium-server.jar \<tt> </tt>customProfileDirCUSTFF/extensions/\{538F0036-F358-4f84-A764-89FB437166B4\}/install.rdf<tt> </tt><tt> </tt>replace &quot;3.0.*&quot; &quot;3.*&quot; -- `find . | grep rdf`<tt> </tt><tt> </tt>jar uf selenium-server.jar \<tt> </tt>customProfileDirCUSTFFCHROME/extensions/readystate@openqa.org/install.rdf<tt> </tt>jar uf selenium-server.jar \<tt> </tt>customProfileDirCUSTFFCHROME/extensions/{538F0036-F358-4f84-A764-89FB437166B4}/install.rdf<tt> </tt>jar uf selenium-server.jar \<tt> </tt>customProfileDirCUSTFFCHROME/extensions/\{503A0CD4-EDC8-489b-853B-19E0BAA8F0A4\}/install.rdf <tt> </tt>jar uf selenium-server.jar \<tt> </tt>customProfileDirCUSTFF/extensions/readystate\@openqa.org/install.rdf <tt> </tt>jar uf selenium-server.jar \<tt> </tt>customProfileDirCUSTFF/extensions/\{538F0036-F358-4f84-A764-89FB437166B4\}/install.rdf<tt> </tt></pre></td> </tr></table> <p>(hat tip to <a href="http://www.spacevatican.org/2008/9/27/selenium-and-firefox-3">space vatican</a>)</p> <p>I haven&#8217;t been able to get Safari working yet.</p> <p>I want to run selenium tests besides normal webrat tests, so I created a new environment &#8220;acceptance&#8221; that I can run tests under. Modify your test helper 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>3<tt> </tt>4<tt> </tt>5<tt> </tt>6<tt> </tt>7<tt> </tt>8<tt> </tt></pre></td> <td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="c"># test/test_helper.rb</span><tt> </tt><span class="co">ENV</span>[<span class="s"><span class="dl">&quot;</span><span class="k">RAILS_ENV</span><span class="dl">&quot;</span></span>] ||= <span class="s"><span class="dl">&quot;</span><span class="k">test</span><span class="dl">&quot;</span></span><tt> </tt>raise <span class="s"><span class="dl">&quot;</span><span class="k">Can't run tests in </span><span class="il"><span class="idl">#{</span><span class="co">ENV</span>[<span class="s"><span class="dl">'</span><span class="k">RAILS_ENV</span><span class="dl">'</span></span>]<span class="idl">}</span></span><span class="k"> environment</span><span class="dl">&quot;</span></span> <span class="r">unless</span> <span class="s"><span class="dl">%w(</span><span class="k">test acceptance</span><span class="dl">)</span></span>.include?(<span class="co">ENV</span>[<span class="s"><span class="dl">&quot;</span><span class="k">RAILS_ENV</span><span class="dl">&quot;</span></span>])<tt> </tt><tt> </tt>require <span class="s"><span class="dl">'</span><span class="k">webrat</span><span class="dl">'</span></span><tt> </tt>require <span class="s"><span class="dl">&quot;</span><span class="k">test/env/</span><span class="il"><span class="idl">#{</span><span class="co">ENV</span>[<span class="s"><span class="dl">&quot;</span><span class="k">RAILS_ENV</span><span class="dl">&quot;</span></span>]<span class="idl">}</span></span><span class="dl">&quot;</span></span><tt> </tt><tt> </tt><span class="c"># ...</span><tt> </tt></pre></td> </tr></table> <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></pre></td> <td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="c"># test/env/test.rb</span><tt> </tt>require <span class="s"><span class="dl">'</span><span class="k">webrat/rails</span><span class="dl">'</span></span><tt> </tt><tt> </tt><span class="co">Webrat</span>.configure <span class="r">do</span> |config|<tt> </tt> config.mode = <span class="sy">:rails</span><tt> </tt> config.open_error_files = <span class="pc">false</span><tt> </tt><span class="r">end</span><tt> </tt></pre></td> </tr></table> <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></pre></td> <td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="c"># test/env/acceptance.rb</span><tt> </tt>require <span class="s"><span class="dl">'</span><span class="k">webrat/selenium/silence_stream</span><span class="dl">'</span></span><tt> </tt>require <span class="s"><span class="dl">'</span><span class="k">webrat/selenium</span><span class="dl">'</span></span><tt> </tt>require <span class="s"><span class="dl">'</span><span class="k">test/selenium_helpers</span><span class="dl">'</span></span><tt> </tt>require <span class="s"><span class="dl">'</span><span class="k">test/element_helpers</span><span class="dl">'</span></span><tt> </tt><tt> </tt><span class="c"># Required because we aren't isolating tests inside a transaction</span><tt> </tt>require <span class="s"><span class="dl">'</span><span class="k">database_cleaner</span><span class="dl">'</span></span><tt> </tt><span class="co">DatabaseCleaner</span>.strategy = <span class="sy">:truncation</span><tt> </tt><tt> </tt><span class="co">Webrat</span>.configure <span class="r">do</span> |config|<tt> </tt> config.mode = <span class="sy">:selenium</span><tt> </tt><span class="r">end</span><tt> </tt><tt> </tt><span class="r">class</span> <span class="cl">ActionController::IntegrationTest</span><tt> </tt> <span class="pc">self</span>.use_transactional_fixtures = <span class="pc">false</span> <span class="c"># Necessary, otherwise selenium will never see any changes!</span><tt> </tt><tt> </tt> setup <span class="r">do</span> |session|<tt> </tt> session.host! <span class="s"><span class="dl">&quot;</span><span class="k">localhost:3001</span><span class="dl">&quot;</span></span><tt> </tt> <span class="r">end</span><tt> </tt><tt> </tt> teardown <span class="r">do</span><tt> </tt> <span class="co">DatabaseCleaner</span>.clean<tt> </tt> <span class="r">end</span><tt> </tt><span class="r">end</span><tt> </tt><tt> </tt><span class="c"># Hack: webrat requires this, even though we're not using rspec</span><tt> </tt><span class="r">module</span> <span class="cl">Spec</span><tt> </tt> <span class="r">module</span> <span class="cl">Expectations</span><tt> </tt> <span class="r">class</span> <span class="cl">ExpectationNotMetError</span> &lt; <span class="co">Exception</span><tt> </tt> <span class="r">end</span><tt> </tt> <span class="r">end</span><tt> </tt><span class="r">end</span><tt> </tt></pre></td> </tr></table> <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></pre></td> <td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="c"># lib/tasks/test.rake</span><tt> </tt>namespace <span class="sy">:test</span> <span class="r">do</span><tt> </tt> task <span class="sy">:force_acceptance</span> <span class="r">do</span><tt> </tt> <span class="co">ENV</span>[<span class="s"><span class="dl">&quot;</span><span class="k">RAILS_ENV</span><span class="dl">&quot;</span></span>] = <span class="s"><span class="dl">'</span><span class="k">acceptance</span><span class="dl">'</span></span><tt> </tt> <span class="r">end</span><tt> </tt><tt> </tt> <span class="co">Rake</span>::<span class="co">TestTask</span>.new(<span class="sy">:acceptance</span> =&gt; <span class="sy">:force_acceptance</span>) <span class="r">do</span> |t|<tt> </tt> t.test_files = <span class="co">FileList</span>[<span class="s"><span class="dl">'</span><span class="k">test/acceptance/*_test.rb</span><span class="dl">'</span></span>]<tt> </tt> t.verbose = <span class="pc">true</span><tt> </tt> <span class="r">end</span><tt> </tt><span class="r">end</span><tt> </tt></pre></td> </tr></table> <p>Notes</p> <ul> <li>selenium and javascript helpers are from <a href="http://pivotallabs.com/users/patn/blog/articles/717-run-javascript-in-selenium-tests-easily">pivotallabs pat</a>, they&#8217;re really handy for testing visibilty of <span class="caps">DOM</span> elements</li> <li>there&#8217;s some magic in webrat to conditionally require <code>silence_stream</code> based on something in active_support. I don&#8217;t understand it quite enough, but requiring it explicitly was necessary to get things running for me</li> <li>webrat/selenium assumes some classes are loaded that only happens if you&#8217;re using rspec. I&#8217;m not, so stubbed out the ExpectationNotMetError (it is only referred to in a rescue block).</li> <li><code>rake test:acceptance</code> runs the selenium tests. Running acceptance tests directly as a ruby script runs them using normal webrat &#8211; this is actually handy when writing tests because you get a quicker turnaround.</li> <li>to pause selenium mid test run (to see wtf is going on), just add <code>gets</code> at the appropriate line in your test</li> </ul>