Como vimos cuando estabamos configurando la base de datos, usted necesita tener una base de datos separada para prueba. Si usted ha seguido el tutorial y no creó una base de datos de prueba, la puede crear ahora (vacía) simplemente ejecutando el comando CREATE DATABASE direcciones_test; (o el nombre que tenga su base de datos).
Ahora sí estamos listos para crear las pruebas de nuestro directorio. Rails ya añadió algunas pruebas a nuestro sistema esqueleto, así que intentaremos ejecutarlas:
$ rake (in /home/david/play/direcciones) /ruby/bin/ruby -Ilib;test "/ruby/lib/ruby/gems/1.8/gems/rake-0.6.2/lib/rake/rake_test_loader.rb" "test/unit/persona_test.rb" Loaded suite /ruby/lib/ruby/gems/1.8/gems/rake-0.6.2/lib/rake/rake_test_loader Started . Finished in 0.2 seconds. 1 tests, 1 assertions, 0 failures, 0 errors /ruby/bin/ruby -Ilib;test "/ruby/lib/ruby/gems/1.8/gems/rake-0.6.2/lib/rake/rake_test_loader.rb" "test/functional/personas_controller_test.rb" Loaded suite /ruby/lib/ruby/gems/1.8/gems/rake-0.6.2/lib/rake/rake_test_loader Started ........ Finished in 0.751 seconds. 8 tests, 28 assertions, 0 failures, 0 errors
¡Qué bueno, pasamos! ¿Pero qué se probó? Veamos las pruebas que tenemos. Los programas en el directorio test son:
$ find test -name *.rb test/functional/personas_controller_test.rb test/test_helper.rb test/unit/persona_test.rb
En el esqueleto creado por rails, las pruebas se dividen en pruebas de unidad (que idealmente prueban cada método de nuestro programa), y pruebas funcionales, que prueban que su programa haga lo que usted espera.
En general, las pruebas funcionales prueban el controlador, y las pruebas de unidad prueban el modelo y las clases de soporte
Cuando usted creó el módulo MVC de personas, el generador de código preparó esqueletos para sus pruebas de unidad.
Para ver de qué se compone una prueba básica, veamos el archivo test/unit/persona_test.rb:
require File.dirname(__FILE__) + '/../test_helper' class PersonaTest < Test::Unit::TestCase fixtures :personas # Replace this with your real tests. def test_truth assert_kind_of Persona, personas(:first) end end
Una prueba de unidad en ruby es una clase que hereda de Test::Unit::TestCase. Dentro de esta clase nosotros escribimos las pruebas.
A veces nuestras pruebas de unidad requieren de registros de prueba en la base de datos. En terminología rails, estos registros se llaman "fixtures" o adornos. Se llaman así porque son útiles primariamente para que la prueba tenga datos con los cuales trabajar.
Los adornos para nuestra tabla se encuentran en el folder test/fixtures/personas.yml. Como podrá imaginar, cuando creamos nuesto módulo utilizando el generador rails nos hizo el favor de incluir este archivo de adorno para la tabla:
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html first: id: 1 another: id: 2
Lo que tenemos que hacer ahora es añadir nuestros datos iniciales. El llenado de los adornos es muy sencillo, y se hace de acuerdo a la descripción de la tabla que diseñamos con anterioridad:
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html personaje_novela: id: 1 nombre: Alonso apellido_paterno: Quijano apellido_materno: Cervantes desplegar: Alonso Quijano sexo: Hombre notas: Nacio en un lugar de la Mancha de cuyo nombre no quiero acordarme. actor_famoso: id: 2 nombre: Pedro apellido_paterno: Infante apellido_materno: Cruz desplegar: Pedro Infante sexo: Hombre notas: El Idolo de Guamuchil
Note que en el formato YML podemos nombrar nuestros registros para describir su naturaleza, que nos ayudará para que nuestras pruebas sean más claras. En este caso, cambiamos los nombres "first" y "another" por "personaje_novela" y "actor_famoso". Como cambiamos el nombre de nuestro primer registro, nuestro método "test_truth" en el listado anterior también necesita cambiar.
Estas pruebas son un poco triviales, pero hagamos un par de pruebas de unidad para comprobar que esto funcione:
def test_actor_famoso actorazo = personas(:actor_famoso) assert_equal "Infante", actorazo.apellido_paterno end
Con anterioridad vimos brevemente que Ruby soporta Desarrollo basado en Pruebas, pero no explicamos específicamte la mecánica del desarrollo basado en pruebas con un ejemplo. Ahora veremos un ejemplo práctico de éste desarrollo, que le permitirá comprender el proceso de pensamiento que utiliza un desarrollador que se basa en pruebas.
Lo que vamos a presentar a continuación representa un cambio de metodología y tren de pensamiento de lo que muchos desarrolladores están acostumbrados.
Acostumbrarse a probar primero no es sencillo, pero vale la pena intentarlo.
En la lengua de Cervantes, los apellidos tienen reglas un poco especiales. Necesitamos implementar un método llamado apellidos que desplegará los apellidos de la siguiente manera:
Como estamos desarrollando basados en nuestras pruebas, primero tenemos que preparar una prueba que falle, y datos de prueba:
Para los datos de prueba, añadimos a personas.yml registros que cubran los casos adecuados:
sin_appellidos: id: 3 nombre: Maria desplegar: Maria sexo: Mujer solo_apellido_paterno: id: 4 nombre: Juan apellido_paterno: Gomez solo_apellido_materno: id: 5 nombre: Pedro apellido_materno: Paramo ambos_apellidos: id: 6 nombre: Juan apellido_materno: Torres apellido_paterno: Mendoza
Ahora que tenemos información de prueba, podemos crear nuestras pruebas. Todavía no tenemos el código, pero sabemos lo que esperamos en los diferentes casos. Así que añadimos a nuestro archivo test/unit/persona_test.rb los métodos de prueba que necesitamos. Comenzamos los métodos con test para que la clase TestCase los ejecute:
class PersonaTest < Test::Unit::TestCase fixtures :personas def test_ambos_apellidos bien_nacido = personas(:ambos_apellidos) assert_equal( bien_nacido.apellido_paterno+' '+bien_nacido.apellido_materno, bien_nacido.apellidos ) end def test_solo_paterno persona = personas(:solo_apellido_paterno) assert_equal( persona.apellido_paterno, persona.apellidos ) end def test_solo_materno persona = personas(:solo_apellido_materno) assert_equal( persona.apellido_materno, persona.apellidos ) end def test_sin_apellidos persona = personas(:sin_apellidos) assert_equal( "", persona.apellidos ) end end
Ahora podemos escribir un metodo "cabo" (un método básicamente vacío), que ataremos con el código adecuado más tarde. En nuestro archivo app/models/persona.rb.
def apellidos "" end
Ahora cuando ejecutemos rake, veremos que la única prueba que funciona es la de sin_apellidos. Funciona de pura casualidad, porque la implementación de nuestro método está vacia:
$ rake TEST=test/unit/persona_test.rb (in /cygdrive/c/home/david/play/direcciones) /usr/bin/ruby -Ilib:test "/usr/lib/ruby/gems/1.8/gems/rake-0.7.0/lib/rake/rake_test_loader.rb" "test/unit/persona_test.rb" Loaded suite /usr/lib/ruby/gems/1.8/gems/rake-0.7.0/lib/rake/rake_test_loader Started F.FF. Finished in 0.611 seconds. 1) Failure: test_ambos_apellidos(PersonaTest) [./test/unit/persona_test.rb:13]: <"Mendoza Torres"> expected but was <"">. 2) Failure: test_solo_materno(PersonaTest) [./test/unit/persona_test.rb:24]: <nil> expected but was <"">. 3) Failure: test_solo_paterno(PersonaTest) [./test/unit/persona_test.rb:19]: <"Gomez"> expected but was <""> 5 tests, 5 assertions, 3 failures, 0 errors rake aborted! Test failures (See full trace by running task with --trace)
Note que podemos ejecutar sólo una prueba simplemente añadiendo el nombre del archivo ruby que contiene su prueba.
Pero lo importante que hay que tener en cuenta es que, gracias a nuestras pruebas de unidad (que fueron creadas antes del código basadas en el diseño), tenemos las siguientes ventajas:
Finalmente, podemos implementar la función para los apellidos, y continuar arreglando problemas hasta que nuestro comando de prueba muestre el resultado deseado...
$ rake TEST=test/unit/persona_test.rb ... 5 tests, 5 assertions, 0 failures, 0 errors
Y ahora si podemos decir que nuestro soporte de apellidos en español está completo, y tenemos cinco pruebas que lo demuestran.