RSpec wire protocol Was:Re: describe "RSpec's documentation" do

Matt,

I was facinated to read the email thread on Cuke’s wire protoccol. You
guys
collaborated well.

I have been working on my own to develop a similar protocol for RSpec.
It is
totally external to RSpec right now and very primitive.

Whereas with Cucumber, the step definitions are run on some other
language’s
server, my protocol executes all the code in Ruby in the “it” blocks and
proxies objects and method calls to a server. Currently the protocol is
CGIish+XML. The current server is PHP but could be anything like .Net.

In the next iteration, I plan to use REST+JSON sort of like CounchDB or
CounchREST. With REST you get all the error checking/responses with all
the
simplicity of the existing HTTP protocol, My first version used
ActiveResource but there are other REST clients for Ruby, And JSON you
already know.

It seemed to me that part of your discussion revolved around encoding
the
protocol in JSON or externally. Did you consider REST. Did you reject it
because of performance?

If anyone has any thoughts on this, I’d be interested.

Should we :
o continue to use web proxies for objects and method calls?
o -or- switch to running the matchers (should ==, etc.) over the wire
protocol, more like cucumber?

Thanks and great work,
Ed
BTW, anyone working on a Cuke4PHP?

On 9 Dec 2009, at 00:09, Ed Howland wrote:

“it” blocks and proxies objects and method calls to a server.
encoding the protocol in JSON or externally. Did you consider REST.
Did you reject it because of performance?

Yes we did, briefly - probably before the discussion went online on
the lighthouse ticket. I think there were a couple of reasons why not
REST:
(1) simplicity - we wanted the wire server to be as low-tech as
possible so it would be easy and lightweight to implement on any
platform (think Cuke4EmbeddedDevice). Everyone’s got a TCP stack but
not everyone’s got a simple web server like sinatra - I’m not even
sure there’s an especially simple one for .NET
(2) flexibility - as the protocol has emerged, it’s become clear that
the relationship is pretty much client / server, but when we first
started we weren’t sure how much chatter would need to go back &
forth. Obviously a REST server can’t start making requests back to a
client (unless that client also starts offering a web server), but if
you’ve got two peers talking over a socket you can have two-way comms.

If anyone has any thoughts on this, I’d be interested.

If you’re using your protocol to effectively get remote control over
objects, have you considered writing something to support DRB[1] on
the server side? Otherwise you could also look at SLIM[2], which is
the protocol Fitnesse uses in much the same way as Cucumber uses the
wire protocol. We did consider using slim in Cucumber - it’s widely
supported with server implementations on many platforms, but since
SLIM has much more flexibility that we needed, we decided to keep
things simple.

Should we :
o continue to use web proxies for objects and method calls?
o -or- switch to running the matchers (should ==, etc.) over the
wire protocol, more like cucumber?

I’m not really clear what the goal of your app is, but to go more into
line with what cucumber’s doing, I think what you’d do would be to
allow RSpec to remotely invoke entire examples (“it blocks”) remotely.
You could then write those examples entirely in the native language.

Thanks and great work,
Ed
BTW, anyone working on a Cuke4PHP?

That’s the first time I’ve heard anyone even suggest it :slight_smile: I’d be
happy to collaborate with someone if they wanted some help with that.

[1]http://segment7.net/projects/ruby/drb/introduction.html
[2]FitNesse.UserGuide.SliM

us to support.
http://rubyforge.org/mailman/listinfo/rspec-users
http://rubyforge.org/mailman/listinfo/rspec-users
cheers,
Matt

+447974 430184

On Fri, Dec 11, 2009 at 9:03 AM, Matt W. [email protected] wrote:

REST server can’t start making requests back to a client (unless that client
implementations on many platforms, but since SLIM has much more flexibility
that we needed, we decided to keep things simple.

Thanks, Matt.
[2] has some really good ideas and some that I’ve already thought of.
I kinda like the multiple instructions per transaction. I don’t know
if I need that yet. I considered [1] but wasn’t sure how easy it would
be to write a server for DRb in another language.

All I’m doing is representing the Ruby object protocol (object.send
:message, args) in REST.

JSON suffices for just about any object serialization and you can
customize it for your class. I currently don’t need to layer any
command structure on top of JSON. Only the message’s arguments payload
and return values get serialized/deserialized. JSON is built-in or
supported via a standard lib or module in all of my targeted
languages. .Net/PHP/Perl and Python.

REST works to supply the basics of the command layer.

Resources are classes, objects and bare functions.

E.g. To create a new object from a class.
obj=MyObject.new => POST: http://server/class/MyObject
obj-MyObject.new(1,2) POST: http://server/class/MyObject ‘args=[1,2]’

These return an object id along with json_cerate args.

To call a method on said object:

obj.f(:a=>10) => PUT : http://server/object/1/msg/f ‘args={“a”:1,“b”:2}’
… and returning results as above.

To call a class level method, return a single object or a list of them,
use GET.

obj=MyClass.get(1) => GET http://server/class/MyClass/msg/get?args=1
– raw method –
obj =JSON.parse GET http://server/object/1

List (via a query):
array = MyClass.query(‘where active = ?’, true) =>
GET http://server/class/MyClass/msg/query?'args=[“WHERE active =
?”,true]’ # with URL encoding

– raw list of all objects of a class –
GET http://server/class/MyClass/*

– raw list of all objects –
GET http://server/object/*

… and so on

All returned objects on the Ruby side are just handles that only hold
the id. They don’t contain any marshaled data from the target language
side. The reasoning is that all variable access must be done via
accessor methods since that is the case in Ruby. However, given a REST
call like this in a target server:
PUT http://server/object/2/msg/a
the implementation is free to decide that that is a variable access,
and assuming it is public, return its value. Setting the contents of a
variable is just the same, but with Ruby conventions that the target
language has to obey:

obj.a=1 => PUT http://server/object/3/a= ‘args=[1]’

The motivation behind this is to use both Cuke and RSpec to test
legacy (or BDD develop new) projects w/o having to install and learn
another BDD/xUnit framework.

I think this suffices for all RSpec use cases, but it may be
incomplete. If you are anyone think of anything I have missed, let me
know.

Already you can:

sudo gem install
(in …/spec_helper.rb: require ‘’)

describe MyObject
before(:each)
@obj = MyObject.new
end
it “should be valid”
@obj.should be_valid # would PUT/ object/msg/valid?
end
it “should have x == [‘avg’, 10.0]” do
@obj.x.should == [‘avg’, 10.0]
end
end

Note there is no need to declare a class on the RSpec side, or to
include a module or inherit from some other class. In PHP to get the
specs to pass:
— my_object.php –
class MyObject {
var x;
function MyObject() {x=array(“avg”, 10.0);}
function isValid() { return true; } // another convention
}

You get in to a R-G-R rhythm just as quickly as with native Ruby code.

The server code for this would need to reflect on MyObject to
determine variable access and discover methods that start with ‘isXXX’

Currently this is very primitive. There is no support for passing
objects to other objects. I don’t know about class level methods in
all target languages yet. I thought the user could provide class
factory classes for those if they don’t exist, like in PHP4.

It requires an object store on the server side, each implementation is
free to decide on that. In Sinatra I it is just a class variable for
now, the object ids are the indexes.

Should we :
o continue to use web proxies for objects and method calls?
o -or- switch to running the matchers (should ==, etc.) over the wire
protocol, more like cucumber?

I’m not really clear what the goal of your app is, but to go more into line
with what cucumber’s doing, I think what you’d do would be to allow RSpec to
remotely invoke entire examples (“it blocks”) remotely. You could then write
those examples entirely in the native language.

I mentioned the goal above. Writing those examples in the target
language is not what I had in mind. I only want code in the actual
SUT to be written in that SUT’s language. You’d have to port ALL of
RSpec’s matchers there or use another framework’s assertion lib. It’d
be interesting but way beyond the scope of what I am doing. Also,
I am not sure what an it block would look like it it were sent over
the wire. I imagine it queries the SUT wire server for any matching
"it"s and any left over are just reported as unimplemented.

BTW, does Cuke’s wire protocol allow for a mixture of Ruby side and
SUT side step definitions?

BTW, anyone working on a Cuke4PHP?

That’s the first time I’ve heard anyone even suggest it :slight_smile: I’d be happy to
collaborate with someone if they wanted some help with that.

I seriously need this. And am willing to help. Currently we are using
Cuke+Webrat+Mechanize to test only the web facing surface of the app.
But to get things like ‘Given I have a user named “Ted” with password
“Secret”’ to work and insert into the legacy DB is tricky. If that
step could execute on the PHP side, life would be sweet!

AFAIK, there seems to be simple REST servers in at least .Net and PHP.
Fitzgerald for PHP and just using IIS and writing handlers in .Net.

Ed

[1]http://segment7.net/projects/ruby/drb/introduction.html
[2]FitNesse.UserGuide.SliM

Ed Howland

http://twitter.com/ed_howland

Let’s move this bit of the discussion over to the cukes mailing list.
Are you on that list Ed?

On 11 Dec 2009, at 22:29, Ed Howland wrote:

BTW, does Cuke’s wire protocol allow for a mixture of Ruby side and
SUT side step definitions?

Yes. With Cucumber you can implement steps in a mixture of any of the
supported languages, including Ruby code, and any number of wire
servers.

“Secret”’ to work and insert into the legacy DB is tricky. If that
step could execute on the PHP side, life would be sweet!

The protocol is documented in the features here:
http://github.com/mattwynne/cucumber/blob/master/features/wire_protocol.feature
http://github.com/mattwynne/cucumber/blob/master/features/wire_protocol_table_diffing.feature

Richard L. has written the reference implementation of a server
in .NET:

The great thing about how Richard has implemented his server is he’s
written end-to-end tests (in cucumber) that make sure the whole thing
works. See for example

AFAIK, there seems to be simple REST servers in at least .Net and PHP.
Fitzgerald for PHP and just using IIS and writing handlers in .Net.

That’s great, but we don’t use REST for cucumber’s wire protocol as I
explained. Dragging the might of IIS around in order to test a
winforms app, for example, would be pretty bonkers IMO.

cheers,
Matt

+447974 430184