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.