Capybara y Rack::Test

Rack::Test es una librería que implementa el protocolo Rack y que hace posible testear la pila completa de nuestra aplicación sin que tengamos que pagar la latencia de las comunicaciones HTTP ni el uso de navegadores reales.

Podemos usar su API para enviar una solicitud/request a nuestra aplicación.

Cuando nuestra aplicación responda, Rack::Test procesa la respuesta y nos permite cuestionarla.

Puede hacerlo porque implementa el protocolo Rack. La forma en la que lo hace es construyendo el hash de request y pasandolo a la aplicación tal y como la haría un servidor web, interpretando el hash de respuesta y dejandonoslo disponible via su API.

Veamos un ejemplo de una aplicación que usa Rack::Test pero no Capybara para testear una sencilla aplicación Rack del tipo Hello World (Véase https://github.com/crguezl/application_testing_with_capybara):

[~/application_testing_with_capybara/sinatra(master)]$ pwd -P
/Users/casiano/local/src/ruby/testing_with_capybara/application_testing_with_capybara/sinatra
[~/application_testing_with_capybara/sinatra(master)]$ cat test.rb 
require 'bundler/setup'
require 'rack'
require "rack/test"
require 'test/unit'

class HelloWorld
  def response
    [200, {'Content-Length' => '11'}, ['Hello World']]
  end
end

class HelloWorldApp
  def self.call(env)
    HelloWorld.new.response
  end
end


class HelloWorldAppTest < Test::Unit::TestCase
  include Rack::Test::Methods

  def app
    HelloWorldApp
  end

  def test_redirect_logged_in_users_to_dashboard
    get "/"

    assert last_response.ok?
    assert_equal last_response.body, 'Hello World'
  end

end

Una vez instaladas las dependencias podemos ejecutar las pruebas:

[~/application_testing_with_capybara/sinatra(master)]$ ruby test.rb 
Run options: 

# Running tests:

Finished tests in 0.028666s, 34.8845 tests/s, 69.7691 assertions/s.                
1 tests, 2 assertions, 0 failures, 0 errors, 0 skips

ruby -v: ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-darwin13.0]

Aqui no ha habido ninguna comunicación externa, todo ocurre via software.

Rack::Test no tiene una API para hacer click en los elementos, poner radio buttons, manejar forms, etc.

De lo que se ocupa es de relizar la transacción Rack imitando al servidor web.

Para que sirva de ejemplo, este es el código del driver Capybara que traduce el evento click (fichero capybara/rack_test/node.rb) para que sea procesado por Rack::Test:

  def click
    if tag_name == 'a' && !self[:href].nil?
      method = self["data-method"] if driver.options[:respect_data_method]
      method ||= :get
      driver.follow(method, self[:href].to_s)
    elsif (tag_name == 'input' and %w(submit image).include?(type)) or
        ((tag_name == 'button') and type.nil? or type == "submit")
      associated_form = form
      Capybara::RackTest::Form.new(driver, associated_form).submit(self) if associated_form
    end
  end

Capybara determina el tipo de elemento que esta siendo clickeado y después calcula si Rack::Test debe seguir el enlace o submitir el formulario.



Subsecciones
Casiano Rodriguez León 2015-01-07