Unit Testing

vía Gluttonous

Test de unidades

El test de unidades es un método para testear el código en pequeños trozos.

Por qué

  • Significa que nunca tendrás el problema de crear un error mientras solucionas otro.
  • Significa que no tendrás que ejecutar tu programa y jugar con él (lo que es lento) para arreglar los errores. El testeo de unidades es mucho más rápido que el "testeo manual".

Requisitos

  • Cargar la biblioteca 'test/unit'
  • Hacer que la clase a testear sea una subclase de Test::Unit::TestCase
  • Escribir los métodos con el prefijo test_
  • Afirmar (assert) las cosas que decidas que sean ciertas.
  • Ejecutar los tests y corregir los errores hasta que desaparezcan.
require 'test/unit'
 
class MiPrimerTest < Test::Unit::TestCase
  def test_de_verdad 
    assert true
  end
end

Cada afirmación, es un método heredado de la clase Test::Unit::TestCase: Hay que echar un ojo al listado de las posibles afirmaciones (asserts) que podemos comprobar.

Ejemplo

Supongamos que queremos escribir una clase sencilla, Mates, que implemente operaciones aritméticas básicas. Queremos hacer distintos tests para comprobar que la suma, la resta, el producto y la división funcionan.

require 'mates'
require 'test/unit'
 
class TestDeMates < Test::Unit::TestCcase
  def test_suma
    assert_equal 4, Mates.run("2+2")
    assert_equal 4, Mates.run("1+3")
    assert_equal 5, Mates.run("5+0")
    assert_equal 0, Mates.run("-5 + 5")
  end
 
  def test_resta
    assert_equal 0, Mates.run("2-2")
    assert_equal 1, Mates.run("2-1")
    assert_equal -1, Mates.run("2-3")
  end
end

Si ejecutamos el programa, aparecerán siete puntos '…….'. Cada . es un test que se ha ejecutado, E es un error y cada F un fallo.

Started
.......
Finished in 0.015931 seconds.
7 tests, 13 assertions, 0 failures, 0 errors

Unidades de test negativas

Además de los tests positivos, también se pueden escribir unidades de tests negativas intentando romper el código. Esto puede incluir el testeo para excepciones que surgan de usar entradas como Mates.run("a + 2") o Mates.run("4/0").

  def test_para_no_numericos 
    assert_raises(ErrorNoNumerico) do
      Mates.run("a + 2")
    end
  end
 
  def test_division_por_cero 
    assert_raises(ErrorDivisionPorZero) do
      Mates.run("4/0")
    end
  end

Automatizando tests: setup, teardown y rake

Algunas veces necesitamos que ocurran cosas antes y después de cada test. Los métodos setup y teardown son tus compañeros en esta aventura. Cualquier código escrito en setup será ejecutado antes del código, y el código escrito en teardown será ejecutado a posteriori.

Si estás escibiendo tests para todo tu código (como debería ser), el número de ficheros a testear empieza a crecer. Una cosa que puede facilitarte la vida, es automatizar los tests, y rake es la herramienta para este trabajo.

fichero_rake

require 'rake'
require 'rake/testtask'
 
task :default => [:test_units]
 
desc "Ejecutando los tests"
Rake::TestTask.new("test_units") { |t|
  t.pattern = 'test/*_test.rb'  # busca los ficheros acabados en '_test.rb'
  t.verbose = true
  t.warning = true
}

Básicamente, un fichero_rake define las tareas que rake puede hacer. En el fichero_rake, la tarea por defecto (la que sucede cuando se ejecuta rake en un directorio con un fichero_rake en él) es configurada hacia la tarea tests_units. En la tarea tests_units, rake es configurado para buscar ficheros en el directorio que terminen en "_test.rb" y los ejecute. Resumiendo: puedes poner todos los tests en un directorio y dejar que rake haga el trabajo.

Si no se indica lo contrario, el contenido de esta página se ofrece bajo Creative Commons Attribution 3.0 License