Category Archives: Ruby on Rails

Integration Tests for Web Services Using RSpec

Recently I had to implement a REST web service for a project in Rails. I’ve been using RSpec for every kind of tests for a long time but, still, wasn’t sure on what was the best way to use it to test a web service.

Capybara has always been my first choice for integration tests, but it doesn’t make much sense if your views are just plain JSON. Thus, I went for a leaner approach taking advantage of Rack::Test::Methods.

In this post I will explain my approach to test a web service. I won’t get into any details on how the web service in question could or should be implemented.

Setup

The first thing to setup is the filesystem. There are infinite ways to do this, I prefer to keep the API tests isolated from the rest of the application.

spec
  ├── api
  │
  ├── controllers
  │
  ├── factories
  │
  ├── features
  │
  ├── models
  │
  ├── spec_helper.rb
  │
  └── support

I guess it would also make sense to decide to put the tests for your API inside the features folder, but I prefer to create a separate api folder. It just feels cleaner.

There’s only one more step to complete the setup. We need the Rack::Test::Methods module in our tests. For convenience let’s add it to the spec_helper.rb.

# ...
RSpec.configure do |config|
  config.include Rack::Test::Methods
  # ...
end

That’s it! No more setup needed, let’s write some specs!

Specs

For the sake of example let’s say we are building an application that, for some reason, manages products.

I always create one file for each endpoint. Since we’re managing products, there should be an endpoint for products. Therefore there is a spec file named products_spec.rb inside our spec/api folder.

require 'spec_helper'

describe '/api/products', type: :api do
  # ...
end

The main describe block clearly states that we’re describing the /api/products endpoint spec in this file. The describe block as a type of api, the type property is not very important in this case, but it can be used to create filters. More info about that here.

Inside the main describe block we can describe the several actions available at this endpoint, like index, show… This is where all the magic happens.

describe '#index' do
  before { get api_products_path }

  it { last_response.status.should eq 200 }

  it 'should return 10 products' do
    products = JSON.parse last_response.body
    products.count.should eq 10
  end
end

On this example we are testing the index action for the /api/products endpoint. We have a before hook that sends a get request to api_products_path. This means that get api_products_path will execute before each it block.

My favourite part of it is that we have the method last_response. This method returns the response for the last request made in the script and we can use it to access the status of the response, the body, header, etc… All courtesy of Rack::Test::Methods. You can check the documentation for other methods that you may need.

Btw, the get method is also part of the Rack::Test::Methods module. There’s also methods for the other types of requests, post, put, patch, delete, etc…

Conclusion

  • Integration tests for you API should be isolated from the rest of your test suite;
  • Each spec file should have the specs for an endpoint;
  • You don’t need a complex framework for this kind of tests, Rack::Test::Methods works just fine;

Matz, why?

In “The Well Grounded Rubyist”, David Black talks about the “Class/Object Chicken-and-Egg Paradox”:

The class Class is an instance of itself; that is, it’s a Class object. And there’s more. Remember the class Object? Well, Object is a class… but classes are objects. So, Object is an object. And Class is a class. And Object is a class, and Class is an object.

Tagged , , , , ,

Blocks as Closures

Closures can be something difficult to grasp but they have some interesting use-cases from simple to harder ones. For instance:

def power_to
  foo = 1
  Proc.new { foo += foo }
end

proc_obj = power_to
puts proc_obj.call
puts proc_obj.call
puts proc_obj.call

This will print:

$ 2
$ 4
$ 8

The method power_to returns a Proc object which has the state of foo local variable. Though, the variable remains accessible to the block even if that variable is out of scope when the block is called again.

That’s closures and it’s the basis of lexical scoping which you can find in other programming languages such as JavaScript.

Tagged , , ,

Faraday: your new best friend

I am a die-hard REST API fan, however the default Net::HTTP Ruby lib is very verbose and doesn’t give me all the features and flexibility I need for coding API clients fast and easy.
Faraday is a hell of a tool.. (disclaimer: the name is not related with any English scientist well known for contributions in the electromagnetism field). Faraday it’s a HTTP library, started by Rick Olson, which reuses Rack middleware concepts and provides a common interface for building API wrappers. Also it supports many out of the box advanced features, like OAuth, SSL, HTTP caching (Last-Modified and ETag headers), HTTP proxy, easy response data parsing, which could be cumbersome to code and configure with the popular Net::HTTP lib.

Here is a basic snippet:

require 'faraday'

Faraday.get(:url => 'http://faradayisfun.com')

But you can code more complex things and tweak configurations:

require 'faraday'

conn = Faraday.new(:url => 'http://faradayisfun.com') do |builder|
  builder.response :logger #logging stuff
  builder.use Faraday::Adapter::NetHttp #default adapter for Net::HTTP
  builder.use FaradayMiddleware::ParseJson #cool for parsing response bodies
end

res = conn.post do |request|
  request.url '/example'
  request.headers['Content-Type'] = 'application/json'
  request.body = "{send: body}"
end

res.body

Do you need HTTP basic auth? Faraday gives you some:

...
conn.basic_auth('user', 'pwd')
...

With Faraday you can consume APIs with some lines of code and customize its behavior like a pro. Checkout the github repo and take a look at all the cool extra options and supported features.

Tagged , , , , ,

For all the Ruby coders out there

“When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck”

You will know what I mean…

Tagged ,

If you’re deploying a rails app to appfog you’ll need to use environment variables to get the properties to connect to the database.

Here’s an example of how you’re production section from the database.yml file should look like. It uses postgres but you can get the idea and use it with other database engines.

production:
  adapter: postgresql
  encoding: unicode
  pool: 5
  timeout: 5000
  host: <%= JSON.parse( ENV['VCAP_SERVICES'] )['postgres'].first['credentials']['hostname'] rescue 'localhost' %>
  port: <%= JSON.parse( ENV['VCAP_SERVICES'] )['postgres'].first['credentials']['port'] rescue 3306 %>
  database: <%= JSON.parse( ENV['VCAP_SERVICES'] )['postgres'].first['credentials']['name'] rescue '' %>
  username: <%= JSON.parse( ENV['VCAP_SERVICES'] )['postgres'].first['credentials']['username'] rescue '' %>
  password: <%= JSON.parse( ENV['VCAP_SERVICES'] )['postgres'].first['credentials']['password'] rescue '' %>
Tagged , ,