5

I want to pass an instance of an object between two Ruby processes. Specifically, I want to pass an instance of a Selenium WebDriver from one process to another process. The reason I want to do this is because it takes a lot of time for Ruby to create this object, but I want it to be used by the other process.

I've found some related questions here and here that seem to point towards using DRb, but I've been unable to find any useful examples or sample code.

Is there a tool other than DRb that I should be using? Does anyone have an example similar to this that I could copy from?

Community
  • 1
  • 1
Seanny123
  • 8,776
  • 13
  • 68
  • 124
  • 1
    http://www.unlimitednovelty.com/2012/04/introducing-dcell-actor-based.html – Victor Moroz Aug 09 '13 at 13:47
  • I did come across celluloid while investigating, but I didn't think it could be distributed across multiple servers. Thanks for the link! – Seanny123 Aug 09 '13 at 15:47
  • 1
    I only know c# but since the driver is an object, could you save it off as a [Binary Serialization](http://www.skorks.com/2010/04/serializing-and-deserializing-objects-with-ruby/)? Or maybe [make the object global](http://stackoverflow.com/questions/1042384/in-ruby-how-to-use-global-variables-or-constant-values)? Interesting idea though. Loading the browser is pretty quick but the login and navigation before I can really start my test makes things a bit slower. It would be nice to be able to already have an active session. – Brantley Blanchard Aug 19 '13 at 18:11
  • I've added your suggestions to my answer. Thank you for the input. – Seanny123 Aug 19 '13 at 22:41

2 Answers2

5

It looks like you're going to have to use DRb, although the documentation for it seems to be lacking. There is however an interesting article here. You might also want to consider purchasing The dRuby Book by Masatoshi Seki to get a better idea of how to do this effectively.

Another option to investigate if you are not looking at simultaneous access, but you just want to send the object from one process to another, is to serialize (that is, encode in a way that Ruby can read) the object with YAML (for a human readable file) or Marshall (for a binary encoded file) and send it using a pipe. This was mentioned in another answer that has since been deleted.

Note that either of these solutions require modifying the Selenium code heavily since the objects you want to manipulate neither support copying, nor simultaneous access natively.

Seanny123
  • 8,776
  • 13
  • 68
  • 124
1

TL;DR

Most queue or distributed processes are going to require some sort of serialization to work properly. If you want to pass objects rather than messages, then this will a limiting factor in how you approach the problem.

DRb

I don't know if you can marshal a WebDriver object. If you can't, then DRb may be a good choice for your distributed Ruby programs because it supports DRbObject references for things that can't be marshaled. There are some examples provided in the DRb documentation.

Selenium Wire Protocol

Depending on what you're really trying to do, it may be worth taking a closer look at using the remote bindings for the Remote WebDriver client/server, or Selenium's JSON Wire Protocol as an alternative to passing objects between processes.

Other Alternatives: Fixtures, Factories, Stubs, and Mocks

Whether or not these work in your specific case will depend a lot on why you want to pass objects instead of simply driving the remote server. If it's largely an issue of how long it takes to build your object, then the serialization/de-serialization cycle may not necessarily be faster in all cases.

You might want to revisit why your object is so slow to create. If gathering and processing the data for it is what's taking too long, you can use some sort of test fixture or factory to trim that time, either by using a smaller set of fixed data, or using a pre-serialized object that's optimized for speed.

You might also consider whether you actually need real data or objects for your test at all. In many cases, you can speed up your tests a lot by stubbing methods or creating mock objects that will return the values you need for your integration tests without needing to perform expensive calculations or long-running operations.

There are certainly cases where you need to drive the full stack and perform acceptance tests on real data. Even then, you may be able to devise a set of fixture data that will take less time or memory to process. It's certainly worth at least thinking about.

Todd A. Jacobs
  • 81,402
  • 15
  • 141
  • 199