Cobertura de código en Ruby
En la parte de Ruby, que es la que se quiso inspeccionar, se tienen diversas baterías de test como los unitarios, los de integración y otros de API y funcionales mediante Cucumber.
Partiendo de esta base, se quiso añadir al proceso de integración contínua alguna herramienta de cobertura de test para poder ver el alcance de lo que estaba cubierto por test.
En este punto, cabe destacar que los test funcionales y/o de API no iban a formar parte de esta inspección de cobertura ya que son llamadas HTTP a métodos remotos (o locales) y nos sería imposible inspeccionar qué código ejecutan.
Así pues, tendríamos que inspeccionar el código de test de los unitarios y de los funcionales.
Empezaremos primero con el fichero Rakefile del proyecto, viendo qué tareas tenía y cómo fue evolucionando para integrar la cobertura.
Las tareas de test están separadas por comodidad en el desarrollo
RSpec::Core::RakeTask.new(:spec)do |t|
t.pattern = "test/unit/*_spec.rb"
t.rspec_opts = "-Ilib -c"
end
RSpec::Core::RakeTask.new(:integration)do |t|
t.pattern = "test/integration/*_spec.rb"
t.rspec_opts = "-Ilib -c"
end
RSpec::Core::RakeTask.new(:services) do |t|
t.pattern = "test/services/*_spec.rb"
t.rspec_opts = "-Ilib -c"
end
y después, para la integración contínua para el Jenkins, se tiene otra que
va llamando una tras otra estas tareas de test más las de Cucumber
task :all_specs do ENV['RACK_ENV'] = 'production' Rake::Task['server_up'].execute Rake::Task['spec'].execute Rake::Task['integration'].execute Rake::Task['services'].execute Rake::Task['features'].execute Rake::Task['server_down'].execute end
Este es el escenario que se tiene antes de la implementación de la cobertura.
Tras mucho probar con todo tipo de gemas y otras sandeces como ‘rcov cover_me etc’, por problemas de compatibilidad de contexto entre Rakefile y el código ‘etc etc’, lo mejor que he podido montar ha sido con una gema llamada
simplecov
la cual permite salida tanto en HTML como en formato rcov.
Lo primero fue poner en el Gemfile las gemas necesarias al final del fichero
gem "simplecov", "0.5.4" gem "simplecov-html", "0.5.3"
Las versiones son las últimas en el momento de escribir este artículo. También
indicar que si se quiere salida en formato rcov tambien tendría que añadir la gema
simplecov-rcov
Una vez hecho esto las instalamos
sudo bundle install
Y una vez instalamos, continuamos.
Tenemos nuestras tareas en el Rakefile, nuestras gemas de cobertura y ahora ya empezamos a montar todo el tinglado.
Tras darme de frente mil veces intentando lanzar la cobertura desde el Rakefile antes de ejecutar los test, me di cuenta que la única forma era polucionar un poco los test. Para lo cual me creé un directorio en raíz del proyecto llamado
resources
con un fichero llamado
proyecto_coverage.rb
el cual contiene los require de simplecov y la llamada necesaria para que empiece
la inspección
require 'simplecov'
require 'simplecov-html'
SimpleCov.formatter = SimpleCov::Formatter::HTMLFormatter
SimpleCov.start do
add_filter "test"
end
En este fichero indico que la salida será en HTML y que ignore todo lo que contenga la palabra test.
Este fichero me obligaba a modificar mis tareas de test para incluir en su INCLUDE DIR la ruta de mi nuevo directorio resources y además creé una nueva tarea que sólo lanzará los tests que yo quería que fueran cubiertos. Así pues, las tareas de test fueron modificadas
RSpec::Core::RakeTask.new(:spec)do |t|
t.pattern = "test/unit/*_spec.rb"
t.rspec_opts = "-Iresources -Ilib -c" #<- EL CAMBIO (-Iresources)
end
RSpec::Core::RakeTask.new(:integration)do |t|
t.pattern = "test/integration/*_spec.rb"
t.rspec_opts = "-Iresources -Ilib -c" #<- EL CAMBIO (-Iresources)
end
RSpec::Core::RakeTask.new(:services) do |t|
t.pattern = "test/services/*_spec.rb"
t.rspec_opts = "-Iresources -Ilib -c" #<- EL CAMBIO (-Iresources)
end
y la nueva tarea
RSpec::Core::RakeTask.new(:coverage)do |t|
t.pattern = "test/{unit,integration}/*_spec.rb"
t.rspec_opts = "-Iresources -Ilib -c"
end
Con todo esto hecho, sólo me quedaba modificar la tarea que se lanzaba desde el Jenkins como sigue
task :all_specs do
ENV['RACK_ENV'] = 'production'
Rake::Task['server_up'].execute
Rake::Task['coverage'].execute
Rake::Task['services'].execute
Rake::Task['features'].execute
Rake::Task['server_down'].execute
end
y en cada uno de los ficheros de test, tanto unitarios como de integración, añadir como primera línea el require de mi fichero de cobertura:
require 'proyecto_coverage'
Con esto hecho bastaria con ejecutar la tarea
rake coverage
y ver que nos creaba un directorio llamado
coverage
con un bonito HTML navegable de forma estática.
A modo de ejemplo, decir que nosotros desplegamos este HTML con cada ejecución del Jenkins en un servidor de integración continua para poderlo ver con cada commit del Git.
Happy covering :)
Entradas Similares
Problema con Sinatra Imagemagick Rmagick en Mac











