La Coctelera

Apuntes prestados

En el parque somos mayoría

24 Diciembre 2009

Formatear separación de decimales en Rails

nando 24, dic , 2 comentarios

Lo dicho, si me resuelve y puedo, lo posteo. En un lugar de la aplicación necesitábamos cambiar el punto de separación de los decimales por una coma.

El helper triunfador: number_with_delimiter(numero_con_decimales)

Por defecto dicha función utilizará como separador el valor que tengamos en config/locales/es.yml (o similar) dentro de la clave number.format.separator.

Si queremos utilizar otro separador puntualmente podemos pasarle el parámetro :separator. Un ejemplo desde la consola de Rails:


 >> helper.number_with_delimiter 34.76, :separator => "'"
 => "34'76"
 

Más info: NumberHelper's doc

2 comentarios Posteado por: nando En: apuntes compártelo Tags: rails, helpers, numeros, decimales, formateo

24 Diciembre 2009

Modificar un texto en archivos dispersos con bash y vim

nando 24, dic , 3 comentarios

Con la sana intención de retomar mi blog voy a comenzar a publicar cualquier cosa que me resulte útil en el día a día. Por ejemplo esta que acabo de utilizar.

Necesitaba modificar un texto que estaba en catorce ficheros dispersos por la geografía de mi disco duro.

Lo primero, localizar dichos ficheros y pasárselos a vim:


 grep -r 'el texto buscado' -l . | xargs vim
 

Una vez en vim, reemplazo el texto en todos los ficheros:


 bufdo! 1,$s/el texto buscado/el texto deseado/gc
 

La "c" final es para que nos pida confirmación antes de reemplazar, si lo tenemos claro la podemos quitar.

Por último, para revisar los cambios en cada fichero antes de guardarlos repetimos la siguiente secuencia para cada uno de ellos:


 :wn + enter +  enter
 

Si por el contrario queremos guardar todos los ficheros de golpe sin revisarlos:


 :wa
 

O :xa si queremos guardarlos y salir de vim. Ahora bien, tal y como comenta Porras más abajo, si desde el principio tenemos claro lo que queremos reemplazar y no nos preocupa revisar directamente con el editor las sustituciones, podemos utilizar sed desde la línea de comandos:


 grep -r 'el texto buscado' -l . | xargs sed -i 's/el texto buscado/el texto deseado/g'
 

Para terminar, no sé muy bien por qué motivo pierdo el eco de la terminal siempre que le paso a vim los ficheros que debe abrir por medio de xargs. Para resolverlo simplemente escribo con fe, por que no lo veo, lo siguiente:


 reset + enter
 

Y todo vuelve a estar como al principio pero, eso sí, con "el texto deseado".

Créditos:

  • el xargs me lo enseñó Javier Picado
  • el bufdo me lo presentó Daniel Blanco
  • el reset se lo vi a Blat
  • el sed y la opción -l de grep me lo comentó Porras

¡Gracias majos!

3 comentarios Posteado por: nando En: apuntes compártelo Tags: vim, bash, xargs, bufdo, sed, grep

18 Mayo 2009

Habemus Iria!!!

nando 18, may , 14 comentarios

Con tres kilos y seiscientos gramos repartidos a lo largo de cincuenta y un centímetros, el pasado miércoles a las doce y treinta y cinco de la mañana Iria se dejó abrazar por primera vez como si tal cosa.

Yo sin embargo no podía dejar de babear de nuevo ante semejante maravilla.

Más amor a dolor.

14 comentarios Posteado por: nando En: personas compártelo Tags: iria

16 Enero 2009

Mi "line & underline Cucumber day"

nando 16, ene , sin comentarios

Es lo que tiene ser un early-adopter: has de volver a aprender una y otra vez lo que pensabas que ya sabías.

Resulta que estas navidades me actualice la versión de Cucumber y para mi sorpresa dos cosas que me parecían muy útiles ya no estaban ahí.

La primera fue la opción de línea de comandos --line que tenía cucumber. Con ésta podías lanzar un escenario concreto facilitando su línea, la cual te devolvía el propio cucumber en su salida estándar. Es decir, que ya no podía hacer:


 $ cucumber
 Característica: [...]
   
   Escenario: Saludo universal      # features/saludo.feature:7
   [...]
 $ cucumber features/saludo.feature --line 7
 optparse.rb:1443:in `complete': invalid option: --line (OptionParser::InvalidOption)
 

... para lanzar el escenario "Saludo universal". La aparente alternativa que tenía era utilizar la opción --scenario pasándole dicho literal ('Saludo universal') como valor. Pero me resultaba mucho más incómodo. Qué raro...

La segunda llegó poco después y estaba relacionada con la salida generada por cucumber al ejecutar las features. En la nueva versión en lugar de subrayar los parámetros de cada paso los resaltaba con el mismo color que el resto del texto, pero más brillante. Es decir, antes tenía:


   Dado que tenemos dos huertos cuyas áreas son "34 y 27"
 

Ahora me encontraba:


   Dado que tenemos dos huertos cuyas áreas son "34 y 27"
 

El problema que me generaba este cambio es que, al no poder destacarse los espacios en blanco, cuando tenía dos parámetros contiguos no sabía donde terminaba el primero y comenzaba el segundo. En el ejemplo anterior, no sabía si el primer parámetro era dos o dos huertos. Otra vez, qué raro... no era posible que la cosa estuviese yendo hacia atrás. Algo me estaba perdiendo.

Como estaba en plenas vacaciones decidí aparcar el asunto hasta que antes de ayer decidí investigar un poco más en el asunto.

Empecé por lo de la opción --line y la primera en la frente. Mandé un correo a la lista de usuarios RSpec (donde también están los de Cucumber) y dos personas (Matt Wynne y el propio Aslak que está al quite el tío) me dijeron lo que debería haber visto yo solito en la primera línea de la información de uso de cucumber:


 $ cucumber --help
 Usage: cucumber [options] [[FILE[:LINE[:LINE]*]] [...]
 

Es decir, ahora la línea (o líneas) se indica después del nombre del archivo precedida de dos puntos. Es decir, ahora podemos directamente copiar y pegar la salida de cucumber (en el ejemplo features/saludo.feature:7) y tirar millas. Muuucho mejor.

La segunda, la de los parámetros subrayados, por tratarse de algo que directamente consideraba un paso hacia atrás, decidí moverlo directamente como un ticket en Lighthouseapp.

En menos de una hora Aslak había respondido y cerrado el ticket:

There is no underline on Windows, so I decided to use a default formatting that works on across OSes. You can get underlines back by defining CUCUMBER_COLORS.

Y terminaba facilitándome el enlace a la página del wiki que también debería haberme leído antes de pedir por esta boquita.

Así es que he añadido la siguente línea en mi .bashrc y ya tengo lo que tenía:


 export CUCUMBER_COLORS="passed_param=green,bold,underline:failed_param=red,bold,underline:skipped_param=cyan,bold,underline"
 

Dos "tolaaaay!" en un mismo día. Tenía que contarlo.

sin comentarios Posteado por: nando En: apuntes compártelo Tags: cucumber, bashrc, tolay

30 Noviembre 2008

Bryan Helmkamp <brynary/>

nando 30, nov , 1 comentario

Mi intención inicial era contar más en detalle cómo echar a correr un navegador con nuestras features de Cucumber vía Webrat y Selenium. Después de la charla en la Conferencia Rails varias personas se han puesto en contacto con nosotros para contarnos sus dificultades a la hora de conseguir dicho objetivo.

Sin embargo en este caso, por suerte, no es tan fácil como escribir un post o dar una charla sobre el asunto. Ésta misma semana Bryan Helmkamp ha estado subiendo cambios a Webrat que harán que tanto parte de lo que contamos en la conferencia como todo lo que yo pretendía contar en este post sea, si no ruido, sí, al menos, algo totalmente prescindible en una primera toma de contacto.

Dichos cambios están siendo la solución "oficial" a dichos problemas, que son básicamente tres:
- Lanzar el servidor de Selenium-RC (o Selenium Grid)
- Lanzar la versión actual de nuestra aplicación (y pararla cuando terminen los tests)
- Embeber la sesión de Selenium dentro de la API de Webrat (para que la definición de un step sea independiente del tipo de sesión)

De momento no hay (o yo no he encontrado) nada de documentación, pero echando un ojillo al código he visto que ha cambiado la dependencia de la gema del cliente de Selenium (selenium-client en lugar de Selenium como hasta ahora) y que para lanzar el servidor de Selenium-RC lo busca en vendor/selenium-server.jar.

También he visto que, por ahora, la mayoría de las opciones (navegador que queremos lanzar, puerto para nuestra apliación, ubicación del servidor de Selenium, etc.) están metidas "a fuego" sin posibilidad de alterarlas desde fuera. Pero seguro que esto último no tarda en cambiar.

Al igual que el RSpec Story Runner fue un entorno crudo en el que muchas carencias eran resueltas por cada cual a su manera, me da la sensación de que Webrat con Selenium está justo cambiando de color y que en poco tiempo estará maduro y listo para ser disfrutado sin indigestiones.

Go Brynary, Go!

http://www.brynary.com

1 comentario Posteado por: nando En: personas compártelo Tags: webrat, selenium, cucumber

21 Noviembre 2008

Conferencia Rails 2008... ¡grande!

nando 21, nov , sin comentarios

Este año he tenido la suerte de participar y disfrutar "sin preocupaciones" de la Conferencia Rails. El año pasado me pilló empantanado en medio de un proyecto y no pude saborear el momento como lo he hecho en esta edición.

Si no pudisteis asistir u os perdisteis alguna ponencia aquí están los vídeos de todas las charlas. Me gustaron muchas de las que vi, pero si tuviese que recomendar sólo dos de ellas, dada mi devoción por el testing, estas serían la de CI de Calavera y la de BDD de Jorge y Luismi.

En lo que a nuestra charla respecta comentar que nos lo pasamos muy bien tanto en su preparación como en su ejecución final. Raimond y yo nos conocimos en persona el domingo anterior a la presentación y tras cuatro largas noches de risas y buenas intenciones nos dimos cuenta de que teníamos demasiado material para 40 minutos. Pero no sabíamos que quitar, así es que lo que hicimos fue poner la parte de "deseos" y la de "tips" al final de la presentación. Y mira tu por donde fueron estas justamente las que al final se quedaron fuera.

Pero la verdad es que terminado con las clásicas traspas de "Ventajas e Inconvenientes" nos quedamos muy satisfechos, sobre todo después de descubrir que... ¡nos estaban pasando las slides desde la cabina de control!.

Sin duda hubiésemos podido llegar más lejos si hubiésemos pasado las traspas nosotros mismos, ya que teníamos varias agrupadas que la idea era pasarlas rapiditas, en plan animación chuflillas. Pero vamos, que bastante bien quedó la cosa dada la situación. Aquí tenéis el vídeo por si os apetece echaros unas risas.

Y eso sí, no quiero terminar este post sin dar las gracias a todas y todos los que se lo curraron para hacer posible el evento. Otra vez, ¡gracias!

sin comentarios Posteado por: nando En: encuentros documentos compártelo Tags: cucumber, conferenciarails, selenium, rspec, stories, features

2 Octubre 2008

¡Hola amigo! ¡Hola Pepino! (jugando con Cucumber)

nando 2, oct , 7 comentarios

Intro y preámbulos

Todas las opiniones que había leído sobre Cucumber eran buenas, muy buenas. Y cuando el río suena, agua lleva... mi primer contacto con el substituto del RSpec Story Runner ha sido toda una gozada.

Utilizando como referencia su documentación oficial para uso con Rails me puse manos a la obra con un objetivo bastante sencillo: el clásico "Hola mundo", pero en su versión BDD y utilizando castellano en las especificaciones.

Antes de nada instalamos las dependencias que tiene Cucumber. Por un lado, como root, cuatro gemas:


 # gem install term-ansicolor treetop diff-lcs hpricot
 

Y por otro cuatro plugins dentro de nuestra aplicación, a la que cariñosamente llamaremos "Saludeitor":


 rails saludeitor
 cd saludeitor
 git clone git://github.com/aslakhellesoy/cucumber.git vendor/plugins/cucumber
 git clone git://github.com/brynary/webrat.git vendor/plugins/webrat
 git clone git://github.com/dchelimsky/rspec.git vendor/plugins/rspec
 git clone git://github.com/dchelimsky/rspec-rails.git vendor/plugins/rspec-rails

(Si tenemos nuestra aplicación en un repositorio de git podemos incorporar los plugins como submódulos cambiando git clone por git submodule add, tal y como proponen en la documentación oficial)

Acto seguido preparamos el proyecto para que admita la definición de features (o características, como finalmente han sido traducidas en la implementación actual) con la ayuda del generador de Cucumber:


 @nube01:~/src/saludeitor$ script/generate cucumber
       create  features/steps
       create  features/steps/env.rb
       create  features/steps/common_webrat.rb
       exists  lib/tasks
       create  lib/tasks/cucumber.rake
       create  script/cucumber
 

El fichero features/steps/common_webrat.rb implementa las interacciones de navegación típicas, pero las define para features escritas en inglés. No lleva mucho tiempo substituir dichas definiciones por sus equivalentes en castellano de tal forma que, por ejemplo:


 When /^I fill in "(.*)" with "(.*)"$/ do |field, value|
 

 When /^relleno el campo "(.*)" con "(.*)"$/ do |field, value|
 

(Este es mi common_webrat.rb en castellano, por si tienes prisa ;)

Cucumber "flow"

Bueno, ya lo tenemos todo listo para empezar a tirar líneas, eso sí, como esto es "BiDiDí" las tiraremos primero describiendo comportamiento... y como esto es Cucumber, lo haremos de tal forma que nuestra madre pueda participar también si le da por ahí. Creamos pues un archivo features/saludo.feature y escribimos algo como:


 Característica: Saludo
   Para sentirse como en su casa
   Un usuario
   Debería recibir un saludo
 
   Escenario: Saludo universal
     Cuando visito la portada
     Entonces debería ver "¡Hola amigo!"
 

Bien, ya tenemos una especificación. Si le pedimos a Cucumber que compruebe si nuestra aplicación la cumple tenemos muchas posibilidades de que no lo haga. Pero vamos a hacerlo para ver por qué se queja y comenzar a sentir el "flow" ;)

Para lanzar únicamente un fichero de features utilizamos script/cucumber, y para que las interprete en castellano le metemos el parámetro --language, tal que:


 $ script/cucumber --language es  features/saludo.feature
 

A lo que, si nuestra aplicación esta "pelá-y-mondá" como el script de Rails la trajo la mundo, Cucumber responderá:


 Característica: Saludo
   Para sentirse como en su casa
   Un usuario
   Debería recibir un saludo
 
   Escenario: Saludo universal
     Cuando visito la portada
       No route matches "/" with {:method=>:get} (ActionController::RoutingError)
       [...]
 1 step failed
 1 step skipped
 

Con colores muy chulos a la par que apropiados: el principio en verde, justo hasta "Cuando visito la portada" que aparece en rojo junto con el volcado del error, los pasos pendientes de implementar en amarillo (para los que al final nos ofrece una plantilla de su definición que facilite su implementación) y los que se ha saltado por un error en azul.

Además tiene el detalle de subrayar lo que son los valores de los parámetros que recibirá la función que implementa el paso (en este caso "la portada"), lo que nos permite distinguirlos fácilmente de la parte fija de sus definiciones ("Cuando visito").

Bien, pues vamos modificar nuestra aplicación para que salga todo verde verde... ¡tan verde como un pepino!

Editamos el config/routes.rb y descomentamos la línea:


 map.root :controller => "welcome"
 

Y acto seguido creamos dicho controlador con la acción index:


 $ script/generate controller Welcome index
 

Volvemos a lanzar nuestra feature y:


 $ script/cucumber --language es features/saludo.feature
 Característica: Saludo
   Para sentirse como en su casa
   Un usuario
   Debería recibir un saludo
 
   Escenario: Saludo universal
     Cuando visito la portada
     Entonces debería ver "¡Hola amigo!"
       expected: /¡Hola amigo!/m,
            got: "<h1>Welcome#index</h1>\n<p>Find me in app/views/welcome/index.html.erb </p>\n"
      [...]
 

¡Se resiste el bribón! Bien, ahora nos dice que no encuentra por ninguna parte "¡Hola amigo!". Editamos app/views/welcome/index.html.erb y cambiamos el contenido de su H1 por dicho saludo. Volvemos a lanzar Cucumber y...


 Característica: Saludo
   Para sentirse escuchado
   Un usuario
   Debería poder recibir un saludo
 
   Escenario: Saludo universal
     Cuando visito la portada
     Entonces debería ver "¡Hola amigo!"
 
 2 steps passed
 

¡todo verdecico! ¡cómo un pepino! (aunque pueda parecer lo contrario, dice Aslak que el nombre de Cucumber no significa nada y que se le ocurrió porque en el momento que comenzó a desarrollarlo su chica se estaba comiendo un sandwich de pepino).

Bien, vamos a meterle un poco más de chicha a la aplicación (lo que viene siento volver a iterar para comenzar a sentir el "flow"). Metemos un segundo escenario en saludo.feature:


   Escenario: Saludo personal
     Cuando visito la portada
     Y completo "Nombre" con "Pepino"
     Y pulso el botón "Enviar"
     Entonces debería ver "¡Hola Pepino!"
 

Y ahora Cucumber nos dice:


 Característica: Saludo
   Para sentirse escuchado
   Un usuario
   Debería poder recibir un saludo
 
   Escenario: Saludo universal
     Cuando visito la portada
     Entonces debería ver "¡Hola amigo!"
 
   Escenario: Saludo personal
     Cuando visito la portada
     Y completo "Nombre" con "Pepino"
       Could not find [Webrat::TextField, Webrat::TextareaField, Webrat::PasswordField]: "Nombre" (RuntimeError)
     [...]
       ./features/steps/common_webrat.rb:13:in `Y /^completo "(.*)" con "(.*)"$/'
       features/saludo.feature:12:in `Y completo "Nombre" con "Pepino"'
     Y pulso el botón "Enviar"
     Entonces debería ver "¡Hola Pepino!"
 
 3 steps passed
 1 steps failed
 2 steps skipped
 

No encuentra en el HTML de la página el campo "Nombre". De hecho no tiene tampoco el botón "Enviar". Añadimos a app/views/welcome/index.html.erb el siguiente formulario (sé que no es nada Rails, pero es sólo un ejemplo):


 <form action="/">
   <input type="text" name="Nombre" />
   <input type="submit" value="Enviar" />
 </form>
 

Lo lanzamos y ahora Cucumber se queja en la última línea, en la que decimos que deberíamos ver "¡Hola Pepino!". En este momento nuestra aplicación muestra siempre "¡Hola amigo!". Retocamos el H1 de app/views/welcome/index.html.erb y lo dejamos tal que:


 <h1>¡Hola <%= params[:Nombre] || 'amigo' %>!</h1>
 

Y ahora sí que sí, lo lanzamos y Cucumber nos dice que tenemos... ¡todo un pepino!:


 Característica: Saludo
   Para sentirse como en su casa
   Un usuario
   Debería recibir un saludo
 
   Escenario: Saludo universal
     Cuando visito la portada
     Entonces debería ver "¡Hola amigo!"
 
   Escenario: Saludo personal
     Cuando visito la portada
     Y completo "Nombre" con "Pepino"
     Y pulso el botón "Enviar"
     Entonces debería ver "¡Hola Pepino!"
 
 6 steps passed
 

Fit tables

Las Fit tables fueron inventadas allá por 2002 por (ni más ni menos que) Ward Cunningham y han sido implementadas en Cucumber para evitar la repetición de escenarios.

En nuestra aplicación podríamos, por ejemplo, añadir una Fit tables en el segundo escenario que agilizase la especificación de nuevos comportamientos. Simplemente añadimos después del escenario su tabla. En nuestro caso:


 Característica: Saludo
   Para sentirse como en su casa
   Un usuario
   Debería recibir un saludo
 
   Escenario: Saludo universal
     Cuando visito la portada
     Entonces debería ver "¡Hola amigo!"
 
   Escenario: Saludo personal
     Cuando visito la portada
     Y completo "Nombre" con "Pepino"
     Y pulso el botón "Enviar"
     Entonces debería ver "¡Hola Pepino!"
 
    | lugar      | campo     | valor  | botón  | mensaje       |
    | la portada | Nombre    | Nando  | Enviar | ¡Melenas!     |
 

La primera fila de la tabla sólo sirve para poner un nombre descriptivo a cada uno de los parámetros manejados en el escenario (qué son los que Cucumber nos ha subrayado al interpretarlo). Al ver esta tabla Cucumber volvería a comprobar los pasos del escenario pero pasándoles los valores indicados en la tabla en lugar de los utilizados en el mismo (y tal y como tenemos el Saludeitor en este momento fallaría porque a "Nando" le responde con "¡Hola Nando!" y no con "¡Melenas!").

Tuneando la tarea de rake

Por último, comentar que para que la tarea de rake cucumber interprete las features en castellano tenemos que modificar el lib/tasks/cucumber.rake añadiéndole en las cucumber_ops el parámetro --language tal y como hacemos al lanzarlo desde la línea de comandos. Quedaría algo como:


 ...
   t.cucumber_opts = "--format pretty --language es"
 ...
 

Esto es todo, suerte con él y consumirlo con moderación para que no os repita ;)

¡Salud!

7 comentarios Posteado por: nando En: apuntes compártelo Tags: fittables, bdd, cucumber

14 Agosto 2008

Aslak Hellesøy <aslak/>

nando 14, ago , 3 comentarios

Si lo llega a hacer premeditadamente seguro que no le sale. El pasado jueves día 7, coincidiendo con el día en el que cumplía mis treinta y cinco agostos, Aslak mandaba el siguiente correo a la lista de desarrollo de RSpec:

[ANN] Cucumber

Nice vegetable, nice tool.

It's my reimplementation of the story runner, addressing several
shortcomings of the current one. And I'm calling them features instead
of stories now, because that is what they are.

http://github.com/aslakhellesoy/cucumber/ (The home page)
http://gojko.net/2008/08/06/cucumber-next-generation-ruby-bdd-tool/
(Thanks Gojko)

Take a look - it's taking shape.

Aslak

Una de la principales virtudes del Cucumber de Aslak frente al Story Runner de RSpec es la posibilidad de escribir las "plain text stories" en cualquier idioma.

Lo cachondo del asunto es que Aslak tiene asignada la implementación de dicha funcionalidad dentro de RSpec desde que la solicité a primeros de año junto con el parche para la versión de aquel momento y, como no, su "plain text story" asociada:


 Story: Writting stories in other languages
 
   As a non-english RSpec developer
   I want to write stories in my mother tongue
   So that I don't have to make an extra effort to know what's going on
 
   Scenario: Pending
     Given the file stories/plain_text_story_in_spanish.rb
     When I run it with the ruby interpreter
     Then the exit code should be 0
     And the stdout should match /1 scenarios: 0 succeeded, 0 failed, 1 pending/m
     And the stdout should match /4\) La portada de Mi Sitio en La Red/
 
   Scenario: Succeed
     Given the file stories/plain_text_story_in_spanish_with_steps.rb
     When I run it with the ruby interpreter
     Then the exit code should be 0
     And the stdout should match /1 scenarios: 1 succeeded, 0 failed, 0 pending/m
 

Era muy excitante ver como la versión sin el parche fallaba al ejecutarla y la parcheada campaba triunfal. Adiós TODO ambiguo. Hola Spec-ificación formal.

Sin embargo la realidad es que ha llovido bastante desde aquello, y viendo que seguramente Aslak escribirá sus historias en noruego utilizando Cucumber, me da la sensación de que seguirá lloviendo durante mucho más hasta que dicha posibilidad exista en la versión oficial de RSpec.

Espero probar Cucumber pronto, pero mientras tanto no me queda más remedio que mantener el legado que tenemos actualmente utilizando el Story Runner de RSpec. Para ello me he creado una rama de RSpec y le he metido los cambios para el soporte multilenguaje.

En cualquier caso lo que está claro es que Aslak ha resuelto mi deseo y me lo ha presentado justo el día de mi cumple... Takk så mye!

blog.aslakhellesoy.com

3 comentarios Posteado por: nando En: personas proyectos compártelo Tags: ruby, bdd, cucumber, stories, rspec