What's the best way to test application API library in Ruby? - ruby

Im developing a ruby API library for some web application (not rails based).
Library (in short overview) consists of the following objects:
Client - main api class
Request - module that handles all data transfers
Item (record) - object with attributes (result of api operations)
Im having a hard time figuring out whats the best way to test such libraries?
Currently using RSpec2 and actual (live) requests. But also might use fixtures.
Any suggestions?

You can use WebMock to mock requests. It has RSpec helpers to aid you in your tests.
I haven't personally used WebMock, but once used Fakeweb to accomplish a similar task. The only disadvantage of using mock requests is that if the remote code changes,

Related

Idiomatic REST API versioning in Padrino app

I am writing a Padrino app which will expose a few services via REST apis. I need to version the apis. I found this answer which explains how to version an api such that the version is embedded in the uri. I would rather put my version info in the Accept header or some other HTTP header (let's not go into the whole embed-in-uri vs put-in-header debate for now). Is there an idiomatic way of implementing this in a Padrino controller? I would like to avoid littering version checks in all my routes. Is there any way I can put the check in a central place (DRY) or - better still - let Padrino take care of this for me with some magical directives?
Try to implement (ofc, w/o 'v1' in url) this.
Also found that. It should work since Padrino is the little bro of Sinatra.
Can't test for the moment. Please keep me aware !

Does this block the event loop?

I have a sinatra app that is using thin as it's web server. I interact with my database via ActiveRecord.
If in an endpoint, I do this:
get '/test' do
Model.create(.....)
end
Does the Model.create(.....) block the event loop (thin uses eventmachine internally)? If so, how bad is this and what are the alternatives?
Thanks
My understanding is that thin is threaded by default, unless you disable that. So your request handler can be executed asynchronously using Eventmachine::Defer.
Yes, as the comment by #user2246674 says, if your handler is executed in the reactor thread then it will block everything.
As to the alternatives, I just searched Google for ActiveRecord and Eventmachine and the first hit was this post with some code: http://www.mikeperham.com/2010/03/30/using-activerecord-with-eventmachine/. You might find it useful to take a look at "em-synchrony": https://github.com/igrigorik/em-synchrony that has support for ActiveRecord.
Here is also my own question on a related subject: async requests using sinatra streaming API There I use Sinatra's streaming API to implement asynchronous request processing.
I personally would use direct DB access from my Sinatra app. That is what I always do. ActiveRecord is too heavy for me.
Yes, it does block. If you are on Mysql you can make requests using mysql2 gem, it supports async requests.
https://github.com/brianmario/mysql2

vcr with capybara-webkit

I'm using capybara-webkit to test integration with a third party website (I need javascript).
I want to use vcr to record requests made during the integration test but capybara-webkit doesn't go over net http so vcr is unable to record them. How would I go about writing an adaptor for vcr that would allow me to record the reqeusts?
Unfortunately, VCR is very much incompatible with capybara-webkit. The fact is that capybara webkit is using webkit, which is in c. Webmock and Fakeweb, which are the basis for VCR, can only be used for Ruby web requests. Making the two work together would likely be a monumental task.
I've solved this problem two ways:
The first (hacky, but valid) is to add a new javascript file to the application that is only included in the test environment. This file stubs out the JS classes which make external web requests. Aside from the pure hackatude of this approach, it requires that every time a new request is added or changed you must change the stubs as well.
The second approach is to route all external requests through my own server, effectively proxying all external requests through my server. This has the huge disadvantage that you have to have an action for everything you want to consume (you could genericize it, with some work). It also suffers from the fact that it could as much as double the time for the request to complete. However, since the requests are now being made by Ruby you can use VCR in all it's glory.
In my situations, approach #2 has been much more to my advantage thanks to the fact that I need ruby to manipulate the data so that I can keep my javascript source-agnostic. I was, however, using approach #1 for quite a while successfully.
I've written a small ruby library (puffing-billy) for rspec+capybara that does exactly this -- it injects a proxy in between your browser and the outside world and allows you to fake responses to specific requests.
Example:
describe 'fetching badges from stackoverflow API' do
it 'should show a nice message when you have no badges' do
# stub some JSONP
proxy.stub('http://api.stackoverflow.com/1.1/users/1/badges',
:jsonp => { :badges => [] })
visit '/my_badges'
page.should have_content("You don't have any badges :(")
end
end

How do I test a Curl based FaceBook API implementation?

I wrote my own FaceBook library that uses actual Curl requests, not libcurl.
Is there a way to test it? I'm asking this because most solutions involve using something like fakeweb which as far as I can tell will not work here.
The existing code can be found on my github page.
One approach would be to use a different host/port in test mode (eg localhost:12345)
Then in your test run a sinatra or webrick servlet on that port that you configure to respond to the requests your code should be making
You could mock Request.dispatcher with an expected behavior, pretty much like Fakeweb would do.
There are a few examples on this file, specially https://github.com/chrisk/fakeweb/blob/master/lib/fake_web/ext/net_http.rb#L44.
When running your tests/specs, monkey-patch the run method of your Request class to hook into the Marston VCR library. See the existing library_hooks subdir for examples and ideas on how to do this -- the fakeweb implementation is a good place to start.
VCR works well with live services like Facebook's because it captures interactions "as is", and VCRs can be easily re-recorded when the services change.
I'm running into problems with your library, however. You need to require the cgi and json libraries; it also looks like it requires a Rails environment (it's failing to find with_indifferent_access on Hash).

How to debug RESTful services? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 7 years ago.
Improve this question
I'm looking for an easy way to debug RESTful services. For example, most webapps can be debugged using your average web browser. Unfortunately that same browser won't allow me to test HTTP PUT, DELETE, and to a certain degree even HTTP POST.
I am not looking to automate tests. I'd like to run new services through a quick sanity check, ideally without having to writing my own client.
Use an existing 'REST client' tool that makes it easy to inspect the requests and responses, like RESTClient.
At my firm we use a variety of different tools and approaches to testing RESTful services:
We write cURL scripts - essentially a single command saved in a file. One file per resource per method. For PUT and POST, we'll usually have files containing the representations to send alongside the cURL script. For example, for a mailbox resource, we might have a file named mailbox_post.cmd, which might contain the line curl -v -X POST -u username -H 'Content-Type:application/xml' -d #mailbox_post.xml http://service/mailbox. We like this approach because we end up building a collection of tests which can be run in a batch, or at least passed around between testers, and used for regression testing.
We use cURL and RESTClient for ad-hoc tests
We have the service serve XHTML by default, so it's browsable, and add forms resources, so the service is actually partially or fully testable using a browser. This was partly inspired by some parts of RESTful Web Services, wherein the authors show that the line between web services and web applications may not need to be as solid and strict as is usually assumed.
We write functional tests as Groovy closures, using the Restlet framework, and run the tests with a test runner Groovy script. This is useful because the tests can be stateful, build on each other, and share variables, when appropriate. We find Restlet's API to be simple and intuitive, and so easy to write quick HTTP requests and test the responses, and it's even easier when used in Groovy. (I hope to share this technique, including the test runner script, on our blog soon.)
Postman, a Google Chrome extension, may be helpful.
Edit years later: Also the website of the url in case Chrome extension link gets changed: www.postman.com
I've found RequestBin useful for debugging REST requests. Post to a unique URL and request data are updated/displayed. Can help in a pinch when other tools are not available.
https://requestbin.com/
A tool I've found useful if you're running OS X Leopard:
HTTP Client
It's a very simple GUI program that allows you to craft http requests to a resource and view the response.
cURL works just fine.
You can use fiddler's Composer to debug restful services..
Updated JD 12 sep 2013: Rest Builder is now called Composer.
I ended up settling on POSTMAN
It supports all REST features I could think of, and the UI is absolutely excellent. The only downside is that it requires Chrome.
RESTTest for Firefox (an add-on). Fiddler for IE.
I'm using Soap UI to test my REST API.
It is more complete than any other tools:
fine debug requests and responses
automated testing
all GUI based
properties and properties transfer to parameterize your tests
conditional testing
performance testing
I'm not working for SmartBear.
I was already a big fan of SoapUI while using it for SOAP WebServices.
Aside from using one of the tools in Peter Hilton's response, I would have to say that scripting the tests with LWP or some similar tool may be your only option. You could bypass the use of LWP by just opening a socket, sending a raw HTTP request in and examining what you get in return. But as far as I know, there are a dearth of testing tools for this sort of domain-- most look at this problem-space primarily from the lens of a web-site developer, and for them the browser is enough of a testing platform.
I use restclient, available from Google Code. It's a simple Java Swing application which supports all HTTP methods, and allows you full control over the HTTP headers, conneg, etc.
If you want free tool for the same purpose with additional feature of multipart form data submission it is here http://code.google.com/a/eclipselabs.org/p/restclient-tool/
Firefox's has RESTClient plug-in to send different request with methods, parameters, headers etc.
You guys should check poster extension for firefox, it's simple and useful enough to use :)
I tend to write unit tests for RESTful resources using Jersey which comes with a nice REST client. The nice thing is if you implement your RESTful resources using JAX-RS then the Jersey client can reuse the entity providers such as for JAXB/XML/JSON/Atom and so forth - so you can reuse the same objects on the server side as you use on the client side unit test.
For example here is a unit test case from the Apache Camel project which looks up XML payloads from a RESTful resource (using the JAXB object Endpoints). The resource(uri) method is defined in this base class which just uses the Jersey client API.
e.g.
clientConfig = new DefaultClientConfig();
client = Client.create(clientConfig);
resource = client.resource("http://localhost:8080");
// lets get the XML as a String
String text = resource("foo").accept("application/xml").get(String.class);
because its totally missing here:
https://luckymarmot.com/paw
Is worth ever penny...

Resources