Bueno ante la necesidad de incluir un apartado sobre pruebas (testing) y validación para mi proyecto fin de carrera he comenzado a utilizar Shoulda para probar mi aplicación.

Según se puede ver en una presentación de Sergio Gil, su título “Más allá del testing”, la única solución para probar mi aplicación después de su implementación es el DDT “Development Driven Testing” que siempre será mejor que no testear.

Al final me decante por utilizar Shoulda también después de leer la presentación “BDD with Should” de la gente que ha desarrollado este framework de testing. Principalmente porque se pueden enlazar contextos (cierto parecido a rspec), los nombres de los tests están bien, compatible con Test::Unit, están cubiertos la mayoría de los macros de ActiveRecord y de ActionController y también tiene cierta magia con los diseños REST.

Por otro lado, no he dejado de utilizar las fixtures, que son odiadas por gran parte de la comunidad porque de momento me sobra con aprender Shoulda. Para evitar el uso de las fixtures me ha parecido interesante el uso de factorias. La gente de thoughtbot utilizan FactoryGirl.

A continuación algunos ejemplos de el uso que le he dado a shoulda para probar modelos y controladores.

Testeando modelo Artist

should_require_attributes :name
should_belong_to :catalog
should_have_many :albums
should_have_many :tracks
should_have_named_scope :recent, :include => :catalog, :order => 'artists.created_at desc',
  :limit => 9, :group => 'catalog_id'
should_have_named_scope 'most_played(10)', :joins => "INNER JOIN tracks on tracks.artist_id = artists.id",
    :select => "SUM(play_count) as sum_play_count, artists.*",
    :group => "tracks.artist_id", :order => "sum_play_count DESC", :limit => 10

Testeando controller Artist

class ArtistsControllerTest < Test::Unit::TestCase
  fixtures :users, :catalogs, :artists, :albums, :tracks, :playlists
  def setup
    @controller = ArtistsController.new
    @request    = ActionController::TestRequest.new
    @response   = ActionController::TestResponse.new
  end
  logged_in_as(:admin) do
    context "on GET to :index" do
      setup do
        get :index, :catalog_id => catalogs(:catalog_itunes_pacoguzman).id
      end
      should_assign_to :catalog
      should_assign_to :artists
      #FIXME También se asigna @recommended
      should_assign_to :recommended
      should_respond_with :success
      should_not_set_the_flash
      should_render_a_form # search form
      should "has one link to new artist page" do
        assert_select "a[href=?]", new_catalog_artist_path(catalogs(:catalog_itunes_pacoguzman)),
          :count => 1, :text => "New artist"
      end
      should "has one link to back catalog page" do
        assert_select "a[href=?]", catalog_path(catalogs(:catalog_itunes_pacoguzman).id),
          :count => 1, :text => catalogs(:catalog_itunes_pacoguzman).type_catalog
      end
    end
  end
end

Para definir el contexto anterior he utilizado el macro logged_in_as del siguiente modo (test_helper.rb)

def self.logged_in_as(user = :admin)
  context "When logged in as #{user}" do
    setup { @logged_in_user = login_as user }
    yield
  end
end

Hasta aquí he resumido el uso que he dado a shoulda en mi aplicación, y para enlazar aquí dejo unos cuantos links: