Philippe showed me a
selenium
-browserSessionReuse -proxyInjectionMode
I'm leaving the original post here as an example of using DRb.
Selenium is a great tool for web acceptance testing, but working on tests can be laborious. In addition to the general slowness of actually testing through the browser, starting a SeleniumDriver takes about 6 seconds on my MacBook.
require "rubygems" gem "Selenium" require "selenium" benchmark = Benchmark.measure do driver = Selenium::SeleniumDriver.new( "localhost", 4444, "*firefox", "http://localhost:3000" ) driver.start driver.stop end benchmark.to_s #=> " 0.000000 0.000000 0.000000 ( 6.294741)"
If the selenium driver could stay open between test runs, running a test could be much faster. Fortunately, DRb makes this easy. Here are the rough steps.
First, start a SeleniumDriver and place it in a DRb service.
require "rubygems" gem "Selenium" require "selenium" require "drb" SERVER = "druby://:51785" driver = Selenium::SeleniumDriver.new( "localhost", 4444, "*firefox", "http://localhost:3000" ) driver.start DRb.start_service SERVER, driver puts "Ready" DRb.thread.join
The DRb.thread.join call at the end of this script means the script won't exit. Run it from a terminal, use Ctrl+C to stop it.
The next step is to use this instance when running tests. DRb provides a class that functions as a proxy to the object running in the server. In this case, that's the selenium driver.
DRb.start_service driver = DRbObject.new(nil, SERVER) class << driver # make sure type hits method_missing to delegate to driver undef_method :type end
Using the DRbObject as a proxy to the SeleniumDriver requires hacking the type method to make sure it delegates properly.
Here's the benchmark for this version:
benchmark = Benchmark.measure do DRb.start_service driver = DRbObject.new(nil, SERVER) class << driver # make sure type hits method_missing to delegate to driver undef_method :type end end benchmark.to_s #=> 0.000000 0.000000 0.000000 ( 0.070634)
The time to start the driver is now negligible.
I've been using this for a few days, and it is working well. If you actually want to try this, here are a couple tweaks to the code that you'll want to make.
To stop the SeleniumDriver when stopping the process, wrap DRb.thread.join like this:
begin DRb.thread.join rescue Interrupt begin puts "Stopping..." driver.stop rescue Exception puts "failed stopping selenium driver" end end
DRbObject does not check the connection when it's first initialized. You may want to force it to check the connection by doing something like this:
begin DRb.start_service driver = DRbObject.new(nil, SERVER) driver.respond_to?(:anything?) rescue DRb::DRbConnError # do something # fail over to non-DRb driver? end
A call to respond_to? will check to see if the DRb server is available. You may want print out an informative message or fail over to using a non-DRb driver if it cannot connect.