Kyle Hargraves
2008-Jun-07 20:10 UTC
[rspec-users] Rails integration tests without stories
I''m looking to drive the development of a rails app that does nothing but serve a JSON API. All of the models are well tested elsewhere, so I needn''t worry about that. My only immediate goal is to be able to fire off requests to a path and check the returned JSON. I''ve tried a number of methods for this today, without being particularly enthused about any of them. I started with user stories, but the conversion to english was difficult for something largely developer-facing. "When I get /widgets/:id" where :id is actually determined behind the scenes did not read well, and a lot of my expectations were tough to express in sentence form. I''ve had a lot of success with stories in the application that is related to this API, but they don''t seem to fit well here. I tried out using standard rails test/unit integration tests, but that would be a suite largely divorced from all of my other specs, and I miss the :should syntax. Requiring spec/expectations and spec/matchers alleviated some of that, but test_names_end_up_being_unpleasantly_long_and_cumbersome. I haven''t yet looked at the test/unit interop support, but maybe that would be helpful here? I tried to make an IntegrationExampleGroup akin to the other rails example groups: module Spec::Rails::Example class IntegrationExampleGroup < ActionController::IntegrationTest Spec::Example::ExampleGroupFactory.register(:integration, self) end end describe ''GET /widgets'', :type => :integration do it "should ..." do get ''/widgets'' [...] end end This roughly seems to work for the integration tests (I''d still need to add in transactions, maybe a few other things), but for reasons I haven''t yet figured out means all my other specs try to run within an integration session. Finally, I could just test the serialization methods on the model (or build a WidgetSerializer), and then use mocks in controller specs. But I''m really looking for full-stack specs here, so I''d like to avoid that. Any suggestions? The path of least resistance is probably using the test/unit tests, followed closely by just sucking it up and having awkward user stories. My preferred solution would be the IntegrationExampleGroup, and I may yet get that to work, but I thought I''d ask here while I sit on it for a bit. Thanks Kyle
David Chelimsky
2008-Jun-07 20:16 UTC
[rspec-users] Rails integration tests without stories
On Jun 7, 2008, at 3:10 PM, Kyle Hargraves wrote:> I''m looking to drive the development of a rails app that does nothing > but serve a JSON API. All of the models are well tested elsewhere, so > I needn''t worry about that. My only immediate goal is to be able to > fire off requests to a path and check the returned JSON. > > I''ve tried a number of methods for this today, without being > particularly enthused about any of them. > > I started with user stories, but the conversion to english was > difficult for something largely developer-facing. "When I get > /widgets/:id" where :id is actually determined behind the scenes did > not read well, and a lot of my expectations were tough to express in > sentence form. I''ve had a lot of success with stories in the > application that is related to this API, but they don''t seem to fit > well here.Can you post an example or two? I''d like to see what''s not working for you. No promises I can offer up anything better, but just curious.> I tried out using standard rails test/unit integration tests, but that > would be a suite largely divorced from all of my other specs, and I > miss the :should syntax. Requiring spec/expectations and spec/matchers > alleviated some of that, but > test_names_end_up_being_unpleasantly_long_and_cumbersome. I haven''t > yet looked at the test/unit interop support, but maybe that would be > helpful here? > > I tried to make an IntegrationExampleGroup akin to the other rails > example groups: > > module Spec::Rails::Example > class IntegrationExampleGroup < ActionController::IntegrationTest > Spec::Example::ExampleGroupFactory.register(:integration, self) > end > end > describe ''GET /widgets'', :type => :integration do > it "should ..." do > get ''/widgets'' > [...] > end > end > > This roughly seems to work for the integration tests (I''d still need > to add in transactions, maybe a few other things), but for reasons I > haven''t yet figured out means all my other specs try to run within an > integration session.That definitely shouldn''t happen. What you have here is very close to what> Finally, I could just test the serialization methods on the model (or > build a WidgetSerializer), and then use mocks in controller specs. But > I''m really looking for full-stack specs here, so I''d like to avoid > that. > > Any suggestions? The path of least resistance is probably using the > test/unit tests, followed closely by just sucking it up and having > awkward user stories. My preferred solution would be the > IntegrationExampleGroup, and I may yet get that to work, but I thought > I''d ask here while I sit on it for a bit.The IntegrationExampleGroup should work. Let''s try to figure out why you''re getting bleed into the other groups. Cheers, David
Kyle Hargraves
2008-Jun-08 00:18 UTC
[rspec-users] Rails integration tests without stories
On Sat, Jun 7, 2008 at 3:16 PM, David Chelimsky <dchelimsky at gmail.com> wrote:>> I started with user stories, but the conversion to english was >> difficult for something largely developer-facing. "When I get >> /widgets/:id" where :id is actually determined behind the scenes did >> not read well, and a lot of my expectations were tough to express in >> sentence form. I''ve had a lot of success with stories in the >> application that is related to this API, but they don''t seem to fit >> well here. > > Can you post an example or two? I''d like to see what''s not working for you. > No promises I can offer up anything better, but just curious.I''ve since rm''d what I wrote, but imagine the case where I need to create a widget, and then I''d like to spec what Widgets#show should return to me: Given a green widget named Panel When I get the JSON representation of the widget Then it should include its buttons And it should not include the widget''s super secret name There''s nothing inherently wrong with this -- I actually rather like it. Reasonably succinct, and a nice high-level overview. But notice that it doesn''t really document the API, which is the goal of my specs. No mention that the widget is at /widgets/1. If I were to mention the URL, I''d have to use something like the /widgets/:id I mentioned, where :id is a bare string in the step name, but filled in with whatever id I happened to get when I created a widget in step #1. Nor is it very clear about what "should include its buttons" means. Again, that''s a good thing if I were documenting behavior of something closer to an application, but it''s awkward here. Cf. to: widget = create_widget(:name => ''Panel'', :color => ''green'') 3.times { create_button(:widget => widget) } obj = get_json(''/widgets/'' + widget.id) obj[''buttons''].length.should == 3 obj.should_not have_key(''super-secret-name'') (I would actually split these up into separate examples, but you get the idea) Given well chosen example group/example names, it feels like this will be more useful when another developer opens them up to learn how to consume the API. And the specdocs have ended up being almost identical to the stories for the purposes of at-a-glance understanding.> The IntegrationExampleGroup should work. Let''s try to figure out why you''re > getting bleed into the other groups.The issue was that my other specs are for the models, which are shared between two applications in a plugin. Thus, the specs are living in plugins/mylib/spec/integration/models -- integration here opposed to the unit tests we have in spec/unit, as they lean on other plugins like will_paginate. That directory then matches :integration and they rightfully try to use the IntegrationExampleGroup. Just an unfortunate overlap of terminology. For now I''ve just opted to rename the :integration type key to :api, but hopefully I''ll come up with a better name for spec/integration. Open to suggestions. =) Works like a charm now, I can use autotest to run them alongside our other specs, and it accomplishes everything I set out for. Big wins all around. k