in web we trust

también en color en: blat.lacoctelera.com

12 Agosto 2007

Tests de unidad de ActionMailer

ActionMailer es la librería incluída en Ruby on Rails para gestionar el envío de correos desde el framework.

Su uso es bastante sencillo y cumple su labor perfectamente, a excepción de pequeños detalles que parece que falten por pulir.

Uno de esos "detalles insignificantes" es, para mi humilde opinión, el testing, que, aunque se puede realizar sin problemas, y con una cobertura muy buena de la funcionalidad, no queda tan limpio como queda en otras partes del framework.

De hecho, una de las cosas que más se echa en falta es algo de documentación. Por suerte, en los Manuales de Rails (qué mal suena, ¿no?), encontramos un "libro" sobre testing en Rails, y uno de sus capítulos es testing your Mailers, que es justo lo que queremos hacer.

Ahí proponen un esquema o esqueleto para los tests de unidad tal que así:


require File.dirname(__FILE__) + '/../test_helper'
require 'my_mailer'


class MyMailerTest < Test::Unit::TestCase
  fixtures :users
  FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures'
  CHARSET = "utf-8" 

  include ActionMailer::Quoting

  def setup
    ActionMailer::Base.delivery_method = :test
    ActionMailer::Base.perform_deliveries = true
    ActionMailer::Base.deliveries = []

    @expected = TMail::Mail.new
    @expected.set_content_type "text", "plain", { "charset" => CHARSET }
  end

  def test_reset_password
    user = User.find(:first)
    newpass = 'newpass'
    response = MyMailer.create_reset_password(user,newpass)
    assert_equal 'Your New Password', response.subject
    assert_match /Dear #{user.full_name},/, response.body
    assert_match /New Password: #{newpass}/, response.body
    assert_equal user.email, response.to[0]
  end

  private
    def read_fixture(action)
      IO.readlines("#{FIXTURES_PATH}/community_mailer/#{action}")
    end

    def encode(subject)
      quoted_printable(subject, CHARSET)
    end
end

Así un poco por encima, además de los requires pertinentes y de establecer unas cuantas constantes debemos de incluír include ActionMailer::Quoting para poder utilizarlo en los tests con aquellos emails que tengan acentos, eñes o cualquier otro carácter no estándar en el subject.

En el método setup configuramos el ActionMailer y además creamos un objeto TMail llamado @expected, y que utilizaremos en todos los tests para compararlo con el que genera nuestro modelo:


  def setup
    ActionMailer::Base.delivery_method = :test
    ActionMailer::Base.perform_deliveries = true
    ActionMailer::Base.deliveries = []

    @expected = TMail::Mail.new
    @expected.set_content_type "text", "plain", { "charset" => CHARSET }
  end

Y respecto a las fixturas, básicamente no tenemos, así que nos proponen utilizar ficheros de texto plano cuyo contenido será el contenido del email. Esos ficheros se sitúan en RAIlS_ROOT/test/fixtures/community_mailer/ como se puede ver en la función read_fixture:


  def read_fixture(action)
    IO.readlines("#{FIXTURES_PATH}/community_mailer/#{action}")
  end

Nuestro propio test

Con el esquema ya creado podemos empezar a escribir nuestros propios tests sobre nuestros modelos de Mailer.

Por ejemplo, veamos una acción muy simple de La Coctelera, que te envía un email cada vez que alguien te añade como amigo:


	def new_friend(user,friend)
    @headers['reply-to'] = user.email
    @from = 'admin@domain.com'
    @recipients = friend.email
    @subject = "[La Coctelera] #{user.shortname} te ha añadido como amigo"
    @body = {
      'user_name' => user.name,
      'friend_name' => friend.name,
      'profile_link' => profile_url(user.username),
      'profile_link_friends' => friends_url(friend.username)
    }
  end

Y esta es la vista asociada:


Hola <%= @friend_name %>!

<%= @user_name %> te ha añadido como amig@. Puedes visitar su página en la siguiente
dirección: <%= @profile_link %>

Puedes ver a todos tus amigos en:

<%= @profile_link_friends %>

Hasta otra!

--
La Coctelera
http://www.lacoctelera.com

El test podría ser algo tal que así:


def test_new_friend
  user = User.find_by_username('lucas')
  friend = User.find_by_username('blat')
  @expected.from = APP['adminmaster']
  @expected.subject = encode("[La Coctelera] #{user.shortname} te ha añadido como amigo")
  @expected.body = read_fixture('new_friend')
  @expected.to = friend.email
  @expected.reply_to = user.email
  assert_equal @expected.encoded, Notifier.create_new_friend(user, friend).encoded
end

El procedimiento es muy sencillo:

  • cargamos a los dos usuarios implicados en la acción
  • vamos rellenando los atributos de @expected con los valores que esperamos que tenga el email resultante: remitente, asunto, contenido, destinatario...
  • finalmente, comparamos el email "esperado", con el que genera la acción create_new_friend

Hemos necesitado crear una fixtura new_friend con el siguiente contenido:


Hola Fernando!

Lucas Nicolás te ha añadido como amig@. Puedes visitar su página en la siguiente dirección: http://test.host/lucas/perfil

Puedes ver a todos tus amigos en:

http://test.host/blat/amigos

Hasta otra!

-- La Coctelera http://test.host

Como veis, esta fixtura tiene una limitación más que evidente: no es dinámica, y su contenido depende de los valores (en este caso de los usuarios), que estamos utilizando en el test.

También quiero destacar esta línea:


  @expected.subject = encode("[La Coctelera] #{user.shortname} te ha añadido como amigo")

Cuando el subject del email vaya a incluir algún caracter acentuado, o con eñe, como es el caso, hay que forzar la recodificación de la cadena, pues ActionMailer también la recodificará cuando cree el email.

En un post posterior propondremos un par de mejoras para solventar alguna de las deficiencias que hemos visto.

servido por Fernando sin comentarios compártelo favorito

5 Agosto 2007

Entendiendo la diferencia entre and y &&

Para aquellos que nos preguntábamos por qué && y and no son lo mismo, y porqué en el Core de Rails prefieren && aquí hay una buena explicación sobre cuál es su principal diferencia, que no es más que un tema de precedencia de operadores.

Supongo que todo es acostumbrarse a utilizar uno u otro.

Tags: ruby

servido por Fernando 1 comentario compártelo favorito

30 Julio 2007

Y antes fue la línea de comandos...

La línea de comandos (¿esa gran desconocida?), es una de las mejores herramientas que tenemos a mano los que desarrollamos en entorno UNIX/Linux. Por eso, posts como este, inspiran.

Y es que seguro que no todo lo que cuenta lo desconoces, pero tiene dos o tres perlas muy buenas.

Aquí van las que más me han gustado:

Repetir un comando con sudo:


	$ vim /etc/hosts
	$ sudo !!
	sudo vim /etc/hosts
	Password:

Utilizar el history para lanzar comandos:


$ history | head
    6  vim config/deploy.rb 
    7  vim config/deploy
    8  vim config/deploy.rb 
    9  cap club_deploy
   10  ssh bellini
   11  cd Proyectos/new-shaker-club/
   12  vim appserver/etc/logrotate.d/the-shaker
$ !10 # lanza un ssh a bellini

Alias de irb:


	alias irb='irb --readline -r irb/completion -rubygems' # use readline, completion and require rubygems by default for irb

Hay muchísimos más en el post que vale la pena repasar.

Y aquí algunos de mi cosecha:

Alias para resetear caché de resolución de nombres (ideal para cuando modificas el /etc/hosts):


	alias dns='sudo lookupd -flushcache'

Alias para ver los cambios en Subversion del directorio actual:


	alias stm='svn st | grep ^M'

Seguro que tú también utilizas alguno que otro, ¡así que ahí tienes los comentarios para compartirlo con los demás!

Actualización: y como remate a este post os dejo mi .irbrc en este pastie.

servido por Fernando 4 comentarios compártelo favorito

23 Julio 2007

Ofertas de empleo en The Cocktail: administrador de sistemas y programador

Desempolvo el blog para informar que en The Cocktail buscamos un administrador de sistemas y un programador.

Podéis leer la oferta entera en nuestra página de empleo.

servido por Fernando sin comentarios compártelo favorito

22 Junio 2007

Google lee tus e-mails

Que Google lee tus e-mails es un hecho por todos conocido, y cuyo fin, sea cual sea, de momento sólo se ve reflejado en la publicidad que se muestra a la derecha.

Sin embargo hoy me ha sorprendido encontrar esto:

Interesante forma de integrar servicios, sobre todo el de mapas.

Tags: google, gmail

servido por Fernando 2 comentarios compártelo favorito

9 Junio 2007

Cosas que hago al empezar un nuevo proyecto en Rails

A lo largo de todo este tiempo que llevo como desarrollador de Rails he cogido una serie de manías y hábitos, a la vez que he descubierto una serie de herramientas y plugins que me han parecido imprescindibles, y que incluso podrían venir incorporadas de serie en Rails.

Así que tras el clásico rails vaporware_project hago lo siguiente:

Instalar el plugin annotate_models

Se trata de un plugin que te copia un listado de atributos de la clase como comentarios en los ficheros del modelo y de las fixturas mediante un simple rake annotate_models.

El resultado es algo como esto:


# == Schema Information
# Schema version: 4
#
# Table name: sources
#
#  id          :integer(11)   not null, primary key
#  url         :string(255)   default(), not null
#  feed_type   :string(255)   default(), not null
#  title       :string(255)   default(), not null
#  description :text          
#  created_at  :datetime      not null
#  updated_at  :datetime      not null
#
class Source < ActiveRecord::Base

Más información: http://agilewebdevelopment.com/plugins/annotate_models

Instalar el plugin test_fixtures

Este plugin, desarrollado por Ernesto Jiménez, añade dinámicamente un test de las fixturas de cada uno de los modelos.

Más información: http://www.lacoctelera.com/ernesto-jimenez/post/2007/04/19/plugins-mi-propia-cosecha

Instalar el plugin memory_test_fix

Se trata de un plugin que permite que los tests se ejecuten contra una base de datos cargada en memoria, lo cuál hace que vayan infinitamente más rápidos, algo muy recomendable si su número crece y crece.

Más información: http://agilewebdevelopment.com/plugins/memory_test_fix

Tanto este plugin como el anterior son ideales si vas a empezar un proyecto siguiendo la metodología TDD

Limpiar los ficheros database.yml y environment.rb

Esto es más una manía que otra cosa, pero ambos ficheros vienen llenos de comentarios (muy instructivos y útiles, la verdad), pero que hace que ocupen infinitamente más de lo que deberían de ocupar.

Por ejemplo, mi database.yml es así:


development:
  adapter: mysql
  database: vapor_development
  username: user
  password: pass
  host: localhost
test:
  adapter: sqlite3
  database: ":memory:"

Y mi environment.rb es así:


RAILS_GEM_VERSION = '1.2.3' unless defined? RAILS_GEM_VERSION
require File.join(File.dirname(__FILE__), 'boot')
Rails::Initializer.run do |config|
end

Utilizar los generadores de Rails

Los generadores de Rails son realmente útiles para crear las plantillas de los ficheros que vamos a utilizar: son mucho más limpios que el scaffold porque crean los ficheros vacíos, pero ya crean fixturas, controladores, tests, etcétera.

Especialmente recomendable el nuevo script/generate resource item, que nos creará nuestro modelo y nuestro controlador como un recursos, creando también las rutas asociadas.

Copio el script rsql en mi carpeta de scripts

El script rsql nos lo enseñó Juan Lupión, y si le dieran un céntimo por cada vez que lo utilizamos ya sería rico.

Se trata de un script de consola que toma como argumento el entorno (cogiendo por defecto development si no indicamos nada) y abre un cliente de SQL con los datos que lee del fichero config/database.yml, con lo cuál en lugar de un mysql -u user -p password -h host databasename, basta con hacer un script/rsql production para entrar en la base de datos de producción, por ejemplo.

El script no sé de donde es ni que licencia tiene, pero podéis descargar de aquí una versión mejorada por el mismo Juan.

The end

Y eso es todo, hay cosas más personales y hay cosas que son un must do, pero seguro que os resultan útiles.

¿Y tú tienes algún consejo?

servido por Fernando 6 comentarios compártelo favorito

21 Mayo 2007

La Rails Conference 2007 de Oregón

Ayer terminó la segunda conferencia Rails americana , que ha tenido lugar en Portland, Oregon. Y ya están disponibles algunas de las presentaciones para ser descargadas.

Si le echáis un vistazo por encima, así a bote pronto destacar la variedad: 2 presentaciones sobre testing, otro para sobre ActiionView, una de Joyent sobre el escalado de aplicaciones web (a la que le he echado un ojo y venía a echar un cable a los chicos de Twitter), REST, routing, y mucho más.

La verdad es que parecen bastante interesantes.

Y como anécdota, una pequeña broma sobre la presentación de David, un bingo con las buzzwords de su keynote:

A destacar bastards de entre todas ellas.

servido por Fernando sin comentarios compártelo favorito

19 Mayo 2007

15 atajos de teclados para Firefox en Mac OS X

No los voy a traducir porque soy un vago, pero no dejéis de echárles un vistazo, que seguro que descubrís alguno nuevo:

15 Must know Firefox shortcuts

Tags: firefox, macosx

servido por Fernando 1 comentario compártelo favorito


Sobre mí

Avatar de Fernando

in web we trust

Valencia y Madrid, España
ver perfil »
contacto »
Blog personal de Fernando Blat, desarrollador en The Cocktail, sobre programación web y Ruby on Rails. Puedes seguir a "mi otro yo" en blat.

Buscar

suscríbete

Selecciona el agregador que utilices para suscribirte a este blog (también puedes obtener la URL de los feeds):

¿Qué es esto?

Crea tu blog gratis en La Coctelera