Using cucumber and Rspec to develop a SOAP client with BDD - ruby-on-rails

As a learning experience I'm developing a small Rails application that is supposed to query an existing SOAP API/web service (using the handsoap gem) and will simply present the information gathered there to a user.
I like using rspec and am getting used to cucumber for testing my applications. The part that has me stumped is how to test the interaction with the API, i.e. the 'non-presentation' part of passing back and forth XML requests and responses.
Any tips and pointers are very much appreciated!
Thanks!

Take a look at fakeweb gem.
It helps to stub network interoperability,
i.e. you can create test responses:
FakeWeb.register_uri(:get, "http://example.com/test1", :body => "Hello World!")
and disable ability to send http requests:
FakeWeb.allow_net_connect = false
Net::HTTP.get(URI.parse("http://example.com/"))
=> raises FakeWeb::NetConnectNotAllowedError

I'm assuming you're talking about functional/integration style tests and not unit tests in which case I would probably consider mocking the interface for the web service and unit testing the code on a lower level.
But to return to cucumber. As Aslak Hellesøy points out in Stack overflow q 810410 there is nothing that should prevent you from doing this. When you have written the scenarios for what behaviour you are actually going to test you just have to instantiate the right objects in the step definitions and call the appropriate methods. Possibly also combining it with a few asserts on return values or content if that is what you need. See Rspec expectations for how to load rspec's should() with cucumber.

With the newest version of Handsoap, you can use a mock http-driver, to mock out at the http-level. See: Http::HttpMock and the example in tests/account_test.rb

Related

In RSpec, what are Request Specs supposed to test?

Rspec noob here, just trying to improve my test coverage.
One very basic yet important question I have is just: What kinds of tests go where?
Model tests are straight forward. I just need to test the functionality of the models methods and validations. View tests seem simple. That would just be testing that each view renders the desired data.
What confuses me is what exactly goes in my Request Specs. Most of my rails experience is from following Michael Hartle's Rails Tutorial. His Request specs seem to be based around a series of actions that the user could take in the application. But he also includes test which seem like they should be in the View Specs that I am considering moving elsewhere.
If someone could help me understand what kinds of tests go in Request, that would be helpful.
From the RSpec docs:
Request specs provide a thin wrapper around Rails' integration tests, and are
designed to drive behavior through the full stack, including routing
(provided by Rails) and without stubbing (that's up to you).
With request specs, you can:
specify a single request
specify multiple requests across multiple controllers
specify multiple requests across multiple sessions
Check the rails documentation on integration tests for more information.
From Rails' docs on integration tests:
Integration tests are used to test the interaction among any number of controllers. They are generally used to test important work flows within your application.
If your test has to do with how a single view is rendered (which should be completely decoupled from any actual HTTP request), then it's probably better as a view test. If it has to do with multiple views or multiple requests, then an integration test is probably more appropriate.

How to use Cucumber to test non-Ruby, non-Rack API's

I use cucumber for lots of things. I really like it as a BDD environment.
So I'd like to use it as an external tool to test an API. I'd like to do things like:
Scenario: Hit api /info path and get info back
When I visit the API path '/info'
Then I should see the following text "Here's info on the API"
or something similar. I mainly want to treat the API as a black box and test only inputs and outputs. I don't plan on inspecting anything inside the API.
Most of the libraries I've looked at that work with Cucumber (for example Capybara) seem to be designed around Rack-based applications. I'd like something similar to that but with no dependency on Rack.
What gems, if any, exist that have no rack dependencies. Or is there a way to use Capybara to test an API that's on a remote server?
I wouldn't use Capybara to test a remote API because Capybara is made for testing applications is used for testing applications with a HTML UI (as Aslak points out in the comments).
Instead, I would use Cucumber* in conjunction with something like HTTParty which would be the tool used to make the HTTP requests and parse them neatly. Here's an idea:
When /^I visit the API path '(.*?)'/ do |path|
#result = HTTParty.get("http://theapi.com/#{path}")
end
Then /^I should see the following result:$/ do |result|
#result.should == result
end
The final step here you would use like this:
Then I should see the following result:
"""
{ success: true }
"""
* I would actually use RSpec personally, I find the syntax less clumsy.
I've been using cucumber against a Drupal application for some time now. It's working out well.
This helped me set up capybara with selenium
https://github.com/thuss/standalone-cucumber
If you want to use mechanize, it's a bit buggy. I had to use 0.3.0-rc3 as there were some issues following redirects etc. There are still a few issues with submitting forms with field names containing "[]" characters. I can't quite remember as another person on my team discovered that bug.

Recommended testing frameworks for Rails 2 app with randomness

I have a Rails 2.3.5 app which is serving a card game. I've been a bit lax in writing tests for it (read: I haven't written any :embarrassed:), and I'd like to make a start now.
From reading other questions, I think I probably want to be using Shoulda extending Test::Unit for unit testing.
I wondered about using Capybara extending RSpec for functional testing, but the majority of users' interaction with the app is via POST, which I understand Capybara doesn't handle.
Since this is a card game, I obviously need the ability to control rand; I also definitely need the framework to handle Javascript.
Is Test::Unit + Shoulda suitable?
Am I correct that Capybara can't handle POST? Can I work around that?
Is there a better option instead of Capybara?
Can these methods handle the randomness involved in a card-game? Presumably, for Test::Unit at least, I can just call srand at some early stage to fix the generator, but I don't know if that's doable for Capybara/RSpec/anything else.
Can anyone point me to resources dealing specifically with setting up Shoulda, Capybara and RSpec for Rails 2.3.5? It's a little hard to tell what's Rails 3 specific and what isn't.
Would I gain anything from adding Watir / Firewatir into the mix?
I realise the above questions are manifold, but they basically boil down to "does this work, or have you any better suggestions?"
If the majority of the users' interactions are via POST, is it via an API (as opposed to filling out forms or something)?
Just about any combination of RSpec/Shoulda/Capybara/Test Unit/Rack::Test could work for you depending on your need. They're all capable. However, these are my recommendations:
If you've decided you want integration testing via HTML pages, use Cucumber and Capybara
If you've decided you want integration testing via HTTP API, use RSpec and Rack::Test
You probably want to fake out randomness.
You probably don't need Watir/Firewatir.
It does look like you can make POST requests via some Capybara drivers:
http://suffix.be/blog/capybara-post-requests
When Rails moved to 3.0, RSpec went to 2.0 so for at least RSpec, you'd want RSpec and RSpec Rails 1.3.2.
By "fake out randomess", I mean redefine srand in your tests so you can predictably run them.
module Kernel
def rand
YourApp.rand
end
end
module MyApp
class << self
attr_accessor :rand
end
end
Then, before you have the user press the button, run a step definition like "When random returns 6", which will set MyApp.rand = 6.

Cucumber: Stub, mock or record client calls (google maps)

I'm wondering if this is possible. I use the VCR gem (http://rubygems.org/gems/vcr) for recording API calls within my models for my unit tests. This works fine.
For more higher level testing I'm using Cucumber. In my app I also test stuff with google maps markers, geocoder etc.
So I'm wondering if there is a solution for providing something like VCR for the client side.
Maybe someone got some ideas,
thx, tux
[EDIT]
I forgot to mention that I use Selenium for javascript tests inside cucumber. So JavaScript calls should also be mocked.
Can't you set a different configuration for your tests? Something like:
var gmaps_url = test ? "http://localhost:1234" : "http://maps.google.com";
Another idea could be using backbone-js (http://documentcloud.github.com/backbone/) on your javascript code. It makes it easier to unit test your javascript code.

Rails Fixtures vs. Mocks

I'm developing a Rails app, and I was just talking with my colleague that we have a mix of fixtures and mocks in our tests, which we're doing using cucumber and Rspec. The question would be: when should each one be used?
I would use a mock object when using the real object is impracticable/not necessary. Lets say for example you need to call some remote API such as an address finder via zip code. You would probably want to mock the object so the calls on it aren't actually made each time you run your tests. There are other reasons too such as improving speed, asking for data that changes where you need an exact response or perhaps it doesn't exist yet. It allows you to test things in isolation as you can determine that when you call these methods on this mock object you will get this back and you don't actually need to run the code as for this test it's not important.
If you use fixtures you will have a real object and the methods etc will be called and their code run, unless of course you stub the methods out, which is something for another question.
Hope that helps a little. There is a good peepcode (http://peepcode.com/products/rspec-mocks-and-models) on mocking and stubbing, maybe check it out.

Resources