Ed Howland
2009-Dec-09 00:09 UTC
[rspec-users] 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 Mon, Nov 9, 2009 at 5:03 PM, Matt Wynne <matt at mattwynne.net> wrote:> > On 6 Nov 2009, at 12:49, David Chelimsky wrote: > > >> [3] > http://github.com/aslakhellesoy/cucumber/blob/master/features/wire_protocol.feature > > I''m well behind this effort and would like to offer my help on the Cucumber > end to make it possible to use the features to generate the user > documentation - I think this would make a terrific use case for us to > support. > > cheers, > Matt > > http://mattwynne.net > +447974 430184 > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >-- Ed Howland http://greenprogrammer.wordpress.com http://twitter.com/ed_howland -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20091208/300e8037/attachment.html>
Matt Wynne
2009-Dec-11 14:03 UTC
[rspec-users] RSpec wire protocol Was:Re: describe "RSpec''s documentation" do
On 9 Dec 2009, at 00:09, Ed Howland wrote:> 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?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 :) 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]http://fitnesse.org/FitNesse.UserGuide.SliM> On Mon, Nov 9, 2009 at 5:03 PM, Matt Wynne <matt at mattwynne.net> wrote: > > On 6 Nov 2009, at 12:49, David Chelimsky wrote: > > > [3]http://github.com/aslakhellesoy/cucumber/blob/master/features/wire_protocol.feature > > I''m well behind this effort and would like to offer my help on the > Cucumber end to make it possible to use the features to generate the > user documentation - I think this would make a terrific use case for > us to support. > > cheers, > Matt > > http://mattwynne.net > +447974 430184 > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users > > > > -- > Ed Howland > http://greenprogrammer.wordpress.com > http://twitter.com/ed_howland > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-userscheers, Matt http://mattwynne.net +447974 430184
Ed Howland
2009-Dec-11 22:29 UTC
[rspec-users] RSpec wire protocol Was:Re: describe "RSpec''s documentation" do
On Fri, Dec 11, 2009 at 9:03 AM, Matt Wynne <matt at mattwynne.net> wrote:> 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.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 <sexy name goes here> (in ../spec_helper.rb: require ''<sexy name>'') describe MyObject before(:each) @obj = MyObject.new end it "should be valid" @obj.should be_valid # would PUT/ object/<id>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 -- <a naming convention> 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 :) 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]http://fitnesse.org/FitNesse.UserGuide.SliM >Ed Howland http://greenprogrammer.wordpress.com http://twitter.com/ed_howland
Matt Wynne
2009-Dec-12 02:53 UTC
[rspec-users] Cuke4PHP Was: RSpec wire protocol Was:Re: describe "RSpec''s documentation" do
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.> >>> BTW, anyone working on a Cuke4PHP? >> >> That''s the first time I''ve heard anyone even suggest it :) 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!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 Lawrence has written the reference implementation of a server in .NET: http://github.com/richardlawrence/Cuke4Nuke 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 http://github.com/richardlawrence/Cuke4Nuke/blob/master/features/cuke4nuke.feature> 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 http://mattwynne.net +447974 430184