Build a Sinatra API Using TDD, Heroku, and Continuous Integration with Travis


  1. Build a Sinatra API Using TDD, Heroku, and Continuous Integration with Travis by Darren Jones. Published December 9, 2013 SitePoint
  2. Código del artículo anterior

The Problem

The application to build is a Number Cruncher. It will return information about numbers, such as its factors, whether it is odd or even, and if it’s prime.

Monkey-patch the Integer class

The first thing we want to do is monkey-patch the Integer class to add a method that returns the factors of a number as an array.

[~/sinatra/sinatra-number_cruncher(master)]$ cat -n number_cruncher.rb | head -n 10
     1  class Integer
     2    def factors
     3      square_root = self**0.5
     4      (1..square_root).map{ |n| [n,self/n] if self/n*n == self }.compact.flatten.sort
     5    end
     7    def prime?
     8      self.factors.size == 2 ? true : false
     9    end
    10  end

I also want to add a prime? method to test if a number is prime.

Once I’ve done this, I’ll use Sinatra to provide an API that will return information about a number in JSON format.

See it working

Testing con minitest/autorun y rack/test

Before we write any code, we should write some tests that cover the description above. First of all, create a file called number_cruncher.rb and another called test.rb.

Then add the following MiniTest setup code to test.rb:

ENV['RACK_ENV'] = 'test'
require 'minitest/autorun'
require 'rack/test'
require_relative 'number_cruncher.rb'
include Rack::Test::Methods
def app

The Rack::Test::Methods module includes a variety of helper methods for simulating requests against an application and asserting expectations about the response. It’s typically included directly within the test context and makes a few helper methods and attributes available.

This module serves as the primary integration point for using Rack::Test in a testing environment.

It depends on an app method being defined in the same context, and provides the Rack::Test API methods (see Rack::Test::Session for their documentation).

If you want to test one Sinatra app in isolation, you just return Sinatra::Application as shown above.

If you are using Sinatra in the modular style, (Véase la sección 35) replace Sinatra::Application above with the class name of your app.

Especificando Requisitos

Now, we’ll write a spec to test some of the features described above. Add the following code to the bottom of test.rb:

describe "Number Cruncher" do
  it "should return the factors of 6" do
    6.factors.must_equal [1,2,3,6]
  it "should say that 2 is prime" do
  it "should say that 10 is not prime" do
  it "should return json" do
    get '/6'
    last_response.headers['Content-Type'].must_match 'application/json'
  it "should return the correct info about 6 as json" do
    get '/6'
    six_info = { number: 6, factors: 6.factors, 
                 odd: 6.odd?, 
                 even: 6.even?, prime: }
    six_info.to_json.must_equal last_response.body

The first test is for the factors method that I plan to add to the Integer class. We check to see that if the integer 6 calls the factors method followed by if the factors of 6 are returned as an array.

Next, test the prime? method that will also be added to the Integer class. First of all, check to see if 2 returns true and then if 10 returns false.

The last two tests are specific to the API. The fourth test checks to see if the app is returning JSON. This is done by performing a get request with 6 as a parameter.

The last_response.headers are checked for a content-type of application/json;charset=utf-8.

In the last test, we check that the correct info is returned by comparing a JSON string to the last_response.body method.

To run our tests, enter the following in a terminal prompt:

$ ruby test.rb
This produces the following output:
# Running:
Finished in 0.008729s, 572.8333 runs/s, 0.0000 assertions/s. 
5 runs, 0 assertions, 0 failures, 5 errors, 0 skips
All five of our tests produce errors, which is expected since we haven’t written any code yet. Let’s see if we can get those tests passing.

Casiano Rodriguez León 2015-01-07