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.