Sinatra con Cucumber¶
Uso de cucumber-sinatra para comenzar el proyecto.
[gomix@movix CaptaHuellas]$ su -c "gem install cucumber-sinatra" Contraseña: Fetching: cucumber-sinatra-0.4.0.gem (100%) Successfully installed cucumber-sinatra-0.4.0 1 gem installed
Arranque desde cero¶
$ mkdir Captahuella
$ cd Captahuella
$ cucumber-sinatra init --app Captahuella lib/captahuella.rb
Generating with init generator:
[ADDED] features/support/env.rb
[ADDED] features/support/paths.rb
[ADDED] features/step_definitions/web_steps.rb
[ADDED] lib/captahuella.rb
[ADDED] config.ru
features/support/env.rb
# Generated by cucumber-sinatra. (Sat Dec 24 12:22:36 -0430 2011) ENV['RACK_ENV'] = 'test' require File.join(File.dirname(__FILE__), '..', '..', 'lib/captahuella.rb') require 'capybara' require 'capybara/cucumber' require 'rspec' Capybara.app = Captahuella class CaptahuellaWorld include Capybara::DSL include RSpec::Expectations include RSpec::Matchers end World do CaptahuellaWorld.new end
features/support/paths.rb
# Taken from the cucumber-rails project.
module NavigationHelpers
# Maps a name to a path. Used by the
#
# When /^I go to (.+)$/ do |page_name|
#
# step definition in web_steps.rb
#
def path_to(page_name)
case page_name
when /the home\s?page/
'/'
# Add more mappings here.
# Here is an example that pulls values out of the Regexp:
#
# when /^(.*)'s profile page$/i
# user_profile_path(User.find_by_login($1))
else
raise "Can't find mapping from \"#{page_name}\" to a path.\n" +
"Now, go and add a mapping in #{__FILE__}"
end
end
end
World(NavigationHelpers)
config.ru
# config.ru require 'rubygems' require File.join(File.dirname(__FILE__), 'lib/captahuella.rb')
lib/captahuella.rb
1require 'sinatra/base'
2
3class Captahuella < Sinatra::Base
4 get '/' do
5 'Hello Captahuella!'
6 end
7end
$ rackup -p 4567 127.0.0.1 - - [24/Dec/2011 08:20:46] "GET / HTTP/1.0" 200 18 0.6021 ...
$ curl http://localhost:4567/ Hello Captahuella!
Primera funcionalidad¶
Recuerde que el primer paso en BDD es describir su funcionalidad.
features/f1.feature
1# language: es
2Característica: Ejecutar comando ftrScanAPI_Ex
3 Con la finalidad de crear objetos Minucia, se debe primero
4 capturar la imagen de la huella digital de la persona.
5 Para capturar la huella hay que ejecutar ftrScanAPI_Ex.
6
7 Escenario: Captura de huella
8 Dado que acceso '/scan'
9 Entonces yo debería ver el resultado 'Imagen obtenida'
Ahora las definiciones de paso¶
features/step_definitions/scan_pasos_basicos.rb
$ cucumber features/f1.feature
# language: es
Característica: Ejecutar comando ftrScanAPI_Ex
Con la finalidad de crear objetos Minucia, se debe primero
capturar la imagen de la huella digital de la persona.
Para capturar la huella hay que ejecutar ftrScanAPI_Ex.
Escenario: Captura de huella # features/f1.feature:7
Dado que acceso '/scan' # features/f1.feature:8
Entonces yo debería ver el resultado 'Imagen obtenida' # features/f1.feature:9
1 scenario (1 undefined)
2 steps (2 undefined)
0m0.005s
You can implement step definitions for undefined steps with these snippets:
Dado /^que acceso '\/scan'$/ do
pending # express the regexp above with the code you wish you had
end
Entonces /^yo debería ver el resultado 'Imagen obtenida'$/ do
pending # express the regexp above with the code you wish you had
end
Implementando con dichas sugerencias en features/step_definitions/scan_pasos_basicos.rb y volviendo a correr:
$ cucumber features/f1.feature
# language: es
Característica: Ejecutar comando ftrScanAPI_Ex
Con la finalidad de crear objetos Minucia, se debe primero
capturar la imagen de la huella digital de la persona.
Para capturar la huella hay que ejecutar ftrScanAPI_Ex.
Escenario: Captura de huella # features/f1.feature:7
Dado que acceso "/scan" # features/step_definitions/scan_pasos_basicos.rb:1
TODO (Cucumber::Pending)
./features/step_definitions/scan_pasos_basicos.rb:2:in `/^que acceso "([^"]*)"$/'
features/f1.feature:8:in `Dado que acceso "/scan"'
Entonces yo debería ver el resultado "Imagen obtenida" # features/step_definitions/scan_pasos_basicos.rb:5
1 scenario (1 pending)
2 steps (1 skipped, 1 pending)
0m0.006s
Ahora toca implementar, aquí me detengo un momento para pensar y evaluar. Ya que mi ejemplo está apuntando a probar una RESTful Web API hecho en Sinatra, creo que lo más adecuado es usar Rack::Test y un entorno de pruebas simple, es decir Test::Unit.
Después de unas cuantas iteraciones más, aquí va mi el código de mis archivos nuevamente:
features/support/env.rb
1require 'rack/test'
2
3ENV['RACK_ENV'] = 'test'
4
5require File.join(File.dirname(__FILE__), '..', '..', 'lib/captahuella.rb')
6
7Captahuella.set :environment, :test
8
9World do
10 def app
11 @app = Rack::Builder.new do
12 run Captahuella
13 end
14 end
15
16 include Rack::Test::Methods
17 include Test::Unit::Assertions
18end
features/scan.feature (renombre algunos archivos)
1# language: es
2Característica: Ejecutar comando ftrScanAPI_Ex
3 Con la finalidad de crear objetos Minucia, se debe primero
4 capturar la imagen de la huella digital de la persona.
5 Para capturar la huella hay que ejecutar ftrScanAPI_Ex.
6 En particular debe usarse el método HTTP GET.
7
8 Escenario: Captura de huella
9 Dado que el cliente acepta respuesta MIME image/bmp
10 Y que se accede a '/scan'
11 Y que se ha usado el método 'HTTP GET'
12 Entonces debería obtener respuesta HTTP '200'
13 Y recibir una descarga de una imagen tipo bmp
Corrida de cucumber
$ cucumber features/scan.feature
# language: es
Característica: Ejecutar comando ftrScanAPI_Ex
Con la finalidad de crear objetos Minucia, se debe primero
capturar la imagen de la huella digital de la persona.
Para capturar la huella hay que ejecutar ftrScanAPI_Ex.
En particular debe usarse el método HTTP GET.
Escenario: Captura de huella # features/scan.feature:8
Dado que el cliente acepta respuesta MIME image/bmp # features/step_definitions/scan_pasos_basicos.rb:1
Y que se accede a '/scan' # features/step_definitions/scan_pasos_basicos.rb:5
Y que se ha usado el método 'HTTP GET' # features/step_definitions/scan_pasos_basicos.rb:9
Entonces debería obtener respuesta HTTP '200' # features/step_definitions/scan_pasos_basicos.rb:13
Y recibir una descarga de una imagen tipo bmp # features/step_definitions/scan_pasos_basicos.rb:17
1 scenario (1 passed)
5 steps (5 passed)
0m5.221s
features/step_definitions/scan_pasos_basicos.rb
1Dado /^que el cliente acepta respuesta MIME image\/bmp$/ do
2 # header es método de rack-test
3 header 'Accept', 'image/bmp'
4end
5
6Dado /^que se accede a '\/scan'$/ do
7 # get es un método de rack-test
8 get('/scan')
9end
10
11Dado /^que se ha usado el método 'HTTP GET'$/ do
12 # assert_equal es un método de Test::Unit
13 assert_equal("GET",last_request.env["REQUEST_METHOD"])
14end
15
16Entonces /^debería obtener respuesta HTTP '(\d+)'$/ do |status|
17 # assert_equal es un método de Test::Unit
18 assert_equal(status, last_response.status.to_s)
19end
20
21Entonces /^recibir una descarga de una imagen tipo bmp$/ do
22 # assert_equal es un método de Test::Unit
23 assert_equal("image/bmp",last_response.content_type)
24end
Ahora veamos el código que implementa la funcionalidad:
1require 'sinatra/base'
2
3class Captahuella < Sinatra::Base
4
5 get '/scan' do
6 # Servir una imagen capturada desde el scanner
7 begin
8 case
9 when request.accept.include?("image/bmp")
10 `ftrScanAPI_Ex`
11 send_file ("frame_Ex.bmp")
12 else
13 # Solicitud de tipo de contenido no aceptable
14 status 406
15 end
16
17 rescue
18 # No encuentro dicho dispositivo
19 status 404
20 case
21 when request.accept.include?("image/bmp")
22 result = "Scan encontró problemas" # ¿Devolver algo además del código de estado?
23 else
24 # Solicitud de tipo de contenido no aceptable
25 status 406
26 result = "Objeto no encontrado"
27 end
28 end
29 end
30
31end