SlideShare una empresa de Scribd logo
Integración Continua
       y Rails
     David Calavera
         11870.com
ego slide

• desarrollador en 11870.com
• open source: Hudson, Netbeans
• commiter de la Fundación Apache
sobre mi
sobre la charla
sobre que

     NO
trata esta charla
nada que nos enganche


        Texto




                más a Rails
como configurar




    un servidor de CI
sobre que trata
  esta charla
usar menos herramientas
automatizar tareas
calidad del código
¿qué es integración
    continua?
“   practica de reunir el código
    que estamos desarrollando
    frecuentemente, para
    verificarlo y evitar errores
                                  ”
                          David Calavera
“   Continuous Integration is a software development
    practice where members of a team integrate their work
    frequently, usually each person integrates at least daily
    - leading to multiple integrations per day. Each
    integration is verified by an automated build (including
    test) to detect integration errors as quickly as possible.
    Many teams find that this approach leads to significantly



                                                           ”
    reduced integration problems and allows a team to
    develop cohesive software more rapidly.


                                                   Martin Fowler
¿para qué sirve?
reducir riesgos
falta de cohesión
descubrir errores pronto




    http://www.agitar.com/solutions/why_unit_testing.html
baja calidad del código
evitar repetir
procesos manuales
generar deploys



en cualquier momento
automatizar el build

• reducir el número de procesos manuales
• ¡¡Rails --tasks --silent | wc -l a ejecutar!!
           incorpora 71 tareas
  • rake
• ¡¡Capistrano añade 22 -tareas más!!
   • expr `cap --tasks | wc -l` 7
¡¡autodestrucción!!
reducir su duración

• usar una máquina dedicada para CI
• mejorar el rendimiento de nuestros tests
• separar los tests por categorías
• ejecutar el build por etapas
ejecutar los test en
            paralelo
• sudo gem install deep_test
DeepTest::TestTask.new 'deep_test:functionals' do |t|
  t.pattern = quot;test/functional/**/*_test.rbquot;
  t.number_of_workers = 2
end
ejecutar los test en
            paralelo
• también para RSpec
Spec::Rake::SpecTask.new 'deep_spec:functionals' do |t|
  t.spec_files = FileList['spec/functional/**/*_spec.rb']
  t.deep_test :number_of_workers => 2
end
ejecutar los test en
            paralelo
• ¡con una base de datos para cada worker!
DeepTest::TestTask.new 'deep_test:functionals' do |t|
  t.pattern = quot;test/functional/**/*_test.rbquot;
  t.worker_listener = 'DeepTest::Database::MysqlSetupListener'
end
usar un servidor de CI

• preguntar por cambios en el repositorio
• realizar acciones en horarios determinados
• soportar diferentes herramientas
• mostrar builds históricos
• soportar diferentes tipos de informes
• soportar diferentes tipos de notificaciones
CruiseControl.rb
CruiseControl.rb

• muy POCO “user friendly”
• plugins perdidos por internet
• pero muy fáciles de desarrollar
• http://cruisecontrolrb.thoughtworks.com
Hudson
Hudson

• MUY “user friendly”
• plugins muy fácilmente localizables
• pero algo más complicado de desarrollar
• http://hudson.dev.java.net
Run Code Run


•
Run Code Run

• de momento solo proyectos open source
• de momento solo se integra con github
• soporte de CI para la última Rails Rumble
• http://runcoderun.com
mejorar la perspectiva
aumentar la confianza
¿cuáles son las
reglas básicas?
commit frecuente
no subir

código roto
arreglar el build

    inmediatamente
escribir test automáticos
hacer builds en local
evitar usar código roto
¿qué pasos hay
 que seguir para
montar un sistema
     de CI?
1. integración de la
   base de datos
lo que hay que hacer

• automatizar los cambios de la base de datos
  • crear la base de datos


  • modificar la base de datos
• testing e inspección
Migraciones

 • muchas mejoras desde Rails 2.1
create   db/migrate/20081112232842_modify_user.rb

class ModifyUser < ActiveRecord::Migration
  def self.up
    change_table :user do |user|
      t.rename :surname, :last_name
      t.remove :age
      ...
    end
  end
end
2. Testing continuo
test unitarios

• enfocados en un objeto
• comprobar installes totalmente unitario
             que
    •
    sudo gem        unit_record

ActiveRecord::Base.disconnect!




• usar mocks en lugar de fixtures
test unitarios

• ¡¡hay que hacerlos para cualquier clase!!
    •sudo gem install unit_controller

def setup
  @controller = UserController.new
  @controller.do_not_render_vew
end
test funcionales

• usa factories en lugar de fixtures
    •
    sudo gem install thoughtbot-factory_girl

Factory.define :user do |u|
  u.first_name 'Joe'
  u.last_name 'Doe'
  u.email {|att| quot;#{att.first_name}@example.comquot;.downcase }
end
test funcionales

• ¡¡hay que hacerlos modelotodas lasde datos
                          para           clases!!
  •  interacción entre el      y la base
  • interacción entre el modelo y el controlador
  • interacción entre el controlador y la vista
3. Inspección continua
reducir la complejidad

• Flog
def flog(output, *directories)
  `find #{directories.join(quot; quot;)} -name *.rb|xargs flog
       > #{RAILS_ROOT}/tmp/flog/#{output}.txt`
end

desc quot;Flog models, controller, helpers and libquot;
task :flog do
  flog quot;allquot;, *%w[app/models app/controllers app/helpers lib]
end
eliminar código
      duplicado o sin usar
• Dust
def unused_lvar
  a = 1
  1 + 2
end

d = Dust::LocalVariableDuster.new(Object, :unused_lvar)
d.dust!
d.warnings
eliminar código
      duplicado o sin usar
• PMD-CPD
def cpd(*directories)
  `java net.sourceforge.pmd.cpd.CPD --minimum-tokens 100 -files
#{directories.map(quot; --files quot;)} --language ruby`
end
task :cpd do
  cpd *%w[app/models app/controllers app/helpers lib]
end
comprobar cobertura

• Rcov
desc 'Test coverage report'
task :coverage do
  rm_f quot;coveragequot;
  rm_f quot;coverage.dataquot;
  rcov = quot;rcov --rails --aggregate coverage.data -Ilibquot;
  `#{rcov} --no-html test/unit/*_test.rb`
  `#{rcov} --no-html test/functional/*_test.rb`
  `#{rcov} --html test/integration/*_test.rb`
  `open coverage/index.html` if PLATFORM['darwin']
end
all in one

• Metrics_fu para cruisecontrol.rb
  • Saikuro
  • Flog
  • Rcov
  • Rails stats
• RubyMetrics para hudson
  • Rcov
  • Rails stats
revisión de código
4. Deploy continuo
deploy continuo

• etiquetar el repositorio
• producir un entorno limpio
• etiquetar cada build
• tener la capacidad de volver atrás
5. Feedback continuo
feedback continuo

• la información correcta
• a la persona indicada
• en el momento esperado
• de la forma correcta
¿alguna pregunta?
Fotos
• http://flickr.com/photos/chicanerii/507573394
• http://flickr.com/photos/3epmedia/1160364177
• http://flickr.com/photos/cathycracks/183170786
• http://flickr.com/photos/smitty/2245445147/
• http://flickr.com/photos/fcw/384316867/
• http://www.flickr.com/photos/auxesis/2965947278/
• http://www.flickr.com/photos/penguin_man44/1203331011/
• http://flickr.com/photos/rekha6/2902282813/
• http://flickr.com/photos/teepee1/1508261796/
• http://flickr.com/photos/teepee1/2614839885/
• http://flickr.com/photos/_saturnine/2294717858/
• http://flickr.com/photos/ezra/459279198/
• http://flickr.com/photos/x180/1397019888
• http://flickr.com/photos/soulcheck/384769773/
• http://flickr.com/photos/znachor/255143511/
• http://flickr.com/photos/julianbleecker/156303245/

Más contenido relacionado

La actualidad más candente

E2E testing frameworks:lo bueno, lo malo y lo feo
E2E testing frameworks:lo bueno, lo malo y lo feoE2E testing frameworks:lo bueno, lo malo y lo feo
E2E testing frameworks:lo bueno, lo malo y lo feo
Abel Quintana Lopez
 
Codemotion Madrid 2014 - Spring ha muerto... ¡larga vida a spring boot!
Codemotion Madrid 2014 - Spring ha muerto... ¡larga vida a spring boot!Codemotion Madrid 2014 - Spring ha muerto... ¡larga vida a spring boot!
Codemotion Madrid 2014 - Spring ha muerto... ¡larga vida a spring boot!
Iván López Martín
 
Jenkins, no me rompas los builds!
Jenkins, no me rompas los builds!Jenkins, no me rompas los builds!
Jenkins, no me rompas los builds!
Gonzalo Sainz Trápaga
 
Testing como parte de la cultura DevOps
Testing como parte de la cultura DevOpsTesting como parte de la cultura DevOps
Testing como parte de la cultura DevOps
Abel Quintana Lopez
 
Cómo iniciarme en el mundo de la automatización de pruebas
Cómo iniciarme en el mundo de la automatización de pruebasCómo iniciarme en el mundo de la automatización de pruebas
Cómo iniciarme en el mundo de la automatización de pruebas
Abel Quintana Lopez
 
Jenkins ci + selenium
Jenkins ci + seleniumJenkins ci + selenium
Jenkins ci + selenium
Info ArtdeCode
 
Presentacion de integracion continua (lima agile)
Presentacion de integracion continua (lima agile)Presentacion de integracion continua (lima agile)
Presentacion de integracion continua (lima agile)Gustavo Veliz
 
Casper JS - Asegurando la calidad en front-end Drupal
Casper JS - Asegurando la calidad en front-end DrupalCasper JS - Asegurando la calidad en front-end Drupal
Casper JS - Asegurando la calidad en front-end Drupal
David Gil Sánchez
 
Spring boot et. al. para el impaciente
Spring boot et. al. para el impacienteSpring boot et. al. para el impaciente
Spring boot et. al. para el impaciente
Miguel Ángel Enríquez López
 
Probando aplicaciones AngularJS
Probando aplicaciones AngularJSProbando aplicaciones AngularJS
Probando aplicaciones AngularJS
Rodrigo Pimentel
 
Capacidades de programación de procesos Asíncronos
Capacidades de programación de procesos AsíncronosCapacidades de programación de procesos Asíncronos
Capacidades de programación de procesos Asíncronos
Esteve Graells
 
¡Introducción a Cypress! - Globant Tech Insiders: Automatización de Pruebas
¡Introducción a Cypress! - Globant Tech Insiders: Automatización de Pruebas¡Introducción a Cypress! - Globant Tech Insiders: Automatización de Pruebas
¡Introducción a Cypress! - Globant Tech Insiders: Automatización de Pruebas
Globant
 
Intro a cakephp
Intro a cakephpIntro a cakephp
Intro a cakephpbetabeers
 
Continuous Delivery Un caso de estudio
Continuous Delivery Un caso de estudioContinuous Delivery Un caso de estudio
Continuous Delivery Un caso de estudio
Osvaldo
 
Integración Continua
Integración ContinuaIntegración Continua
Integración Continua
Jose Patricio Bovet Derpich
 
Scrum overview
Scrum overview Scrum overview
ReConnect 2015 - ASP.NET 5: MVC 6 y EF 7
ReConnect 2015  - ASP.NET 5: MVC 6 y EF 7ReConnect 2015  - ASP.NET 5: MVC 6 y EF 7
ReConnect 2015 - ASP.NET 5: MVC 6 y EF 7
Luis Ruiz Pavón
 
Presentación Spring Boot en Autentia
Presentación Spring Boot en AutentiaPresentación Spring Boot en Autentia
Presentación Spring Boot en Autentia
Jorge Pacheco Mengual
 
Capistrano drupalcamp-jerez-2015
Capistrano drupalcamp-jerez-2015Capistrano drupalcamp-jerez-2015
Capistrano drupalcamp-jerez-2015
David Gil Sánchez
 

La actualidad más candente (20)

E2E testing frameworks:lo bueno, lo malo y lo feo
E2E testing frameworks:lo bueno, lo malo y lo feoE2E testing frameworks:lo bueno, lo malo y lo feo
E2E testing frameworks:lo bueno, lo malo y lo feo
 
Codemotion Madrid 2014 - Spring ha muerto... ¡larga vida a spring boot!
Codemotion Madrid 2014 - Spring ha muerto... ¡larga vida a spring boot!Codemotion Madrid 2014 - Spring ha muerto... ¡larga vida a spring boot!
Codemotion Madrid 2014 - Spring ha muerto... ¡larga vida a spring boot!
 
Jenkins, no me rompas los builds!
Jenkins, no me rompas los builds!Jenkins, no me rompas los builds!
Jenkins, no me rompas los builds!
 
Testing como parte de la cultura DevOps
Testing como parte de la cultura DevOpsTesting como parte de la cultura DevOps
Testing como parte de la cultura DevOps
 
Cómo iniciarme en el mundo de la automatización de pruebas
Cómo iniciarme en el mundo de la automatización de pruebasCómo iniciarme en el mundo de la automatización de pruebas
Cómo iniciarme en el mundo de la automatización de pruebas
 
Jenkins ci + selenium
Jenkins ci + seleniumJenkins ci + selenium
Jenkins ci + selenium
 
Presentacion de integracion continua (lima agile)
Presentacion de integracion continua (lima agile)Presentacion de integracion continua (lima agile)
Presentacion de integracion continua (lima agile)
 
Integracion Continua
Integracion ContinuaIntegracion Continua
Integracion Continua
 
Casper JS - Asegurando la calidad en front-end Drupal
Casper JS - Asegurando la calidad en front-end DrupalCasper JS - Asegurando la calidad en front-end Drupal
Casper JS - Asegurando la calidad en front-end Drupal
 
Spring boot et. al. para el impaciente
Spring boot et. al. para el impacienteSpring boot et. al. para el impaciente
Spring boot et. al. para el impaciente
 
Probando aplicaciones AngularJS
Probando aplicaciones AngularJSProbando aplicaciones AngularJS
Probando aplicaciones AngularJS
 
Capacidades de programación de procesos Asíncronos
Capacidades de programación de procesos AsíncronosCapacidades de programación de procesos Asíncronos
Capacidades de programación de procesos Asíncronos
 
¡Introducción a Cypress! - Globant Tech Insiders: Automatización de Pruebas
¡Introducción a Cypress! - Globant Tech Insiders: Automatización de Pruebas¡Introducción a Cypress! - Globant Tech Insiders: Automatización de Pruebas
¡Introducción a Cypress! - Globant Tech Insiders: Automatización de Pruebas
 
Intro a cakephp
Intro a cakephpIntro a cakephp
Intro a cakephp
 
Continuous Delivery Un caso de estudio
Continuous Delivery Un caso de estudioContinuous Delivery Un caso de estudio
Continuous Delivery Un caso de estudio
 
Integración Continua
Integración ContinuaIntegración Continua
Integración Continua
 
Scrum overview
Scrum overview Scrum overview
Scrum overview
 
ReConnect 2015 - ASP.NET 5: MVC 6 y EF 7
ReConnect 2015  - ASP.NET 5: MVC 6 y EF 7ReConnect 2015  - ASP.NET 5: MVC 6 y EF 7
ReConnect 2015 - ASP.NET 5: MVC 6 y EF 7
 
Presentación Spring Boot en Autentia
Presentación Spring Boot en AutentiaPresentación Spring Boot en Autentia
Presentación Spring Boot en Autentia
 
Capistrano drupalcamp-jerez-2015
Capistrano drupalcamp-jerez-2015Capistrano drupalcamp-jerez-2015
Capistrano drupalcamp-jerez-2015
 

Destacado

Test Driven Development
Test Driven DevelopmentTest Driven Development
Test Driven Development
Uzi Mamani Fernández
 
Introducción a LDAP
Introducción a LDAPIntroducción a LDAP
Introducción a LDAP
Enrique Verdes
 
BDD: Descubriendo qué requiere realmente tu cliente
BDD: Descubriendo qué requiere realmente tu clienteBDD: Descubriendo qué requiere realmente tu cliente
BDD: Descubriendo qué requiere realmente tu clienteJorge Gamba
 
Introducción a Ganglia
Introducción a GangliaIntroducción a Ganglia
Introducción a GangliaDardo Valdez
 
Alta disponibilidad con MySQL
Alta disponibilidad con MySQLAlta disponibilidad con MySQL
Alta disponibilidad con MySQL
Dennis Cohn
 
Software Debt: Qué Es y Cómo Gestionarlo Holísticamente
Software Debt: Qué Es y Cómo Gestionarlo HolísticamenteSoftware Debt: Qué Es y Cómo Gestionarlo Holísticamente
Software Debt: Qué Es y Cómo Gestionarlo Holísticamente
Angel Nuñez
 
Escalabilidad y alto rendimiento con Symfony2
Escalabilidad y alto rendimiento con Symfony2Escalabilidad y alto rendimiento con Symfony2
Escalabilidad y alto rendimiento con Symfony2
Ricard Clau
 
OAUTH introducción y entretenida explicación.
OAUTH introducción y entretenida explicación.OAUTH introducción y entretenida explicación.
OAUTH introducción y entretenida explicación.
Esteban Enrique Moreno Arias
 
Conferencia Monitoreo de Servidores con Nagios
Conferencia Monitoreo de Servidores con NagiosConferencia Monitoreo de Servidores con Nagios
Continous Delivering a PHP application
Continous Delivering a PHP applicationContinous Delivering a PHP application
Continous Delivering a PHP application
Javier López
 
Automatizacion de proyectos con gradle
Automatizacion de proyectos con gradleAutomatizacion de proyectos con gradle
Automatizacion de proyectos con gradle
Edson Chávez Montaño
 
Integrando sonar
Integrando sonarIntegrando sonar
Integrando sonar
Abimael Desales López
 
Introducción a DDD
Introducción a DDDIntroducción a DDD
Introducción a DDDsergiopolo
 
PhpSpec 2.0 ilustrated by examples
PhpSpec 2.0 ilustrated by examplesPhpSpec 2.0 ilustrated by examples
PhpSpec 2.0 ilustrated by examples
Marcello Duarte
 
Building and Deploying Application to Apache Mesos
Building and Deploying Application to Apache MesosBuilding and Deploying Application to Apache Mesos
Building and Deploying Application to Apache Mesos
Joe Stein
 
A new model for Docker image distribution
A new model for Docker image distributionA new model for Docker image distribution
A new model for Docker image distributionDocker, Inc.
 

Destacado (18)

Test Driven Development
Test Driven DevelopmentTest Driven Development
Test Driven Development
 
Introducción a LDAP
Introducción a LDAPIntroducción a LDAP
Introducción a LDAP
 
BDD: Descubriendo qué requiere realmente tu cliente
BDD: Descubriendo qué requiere realmente tu clienteBDD: Descubriendo qué requiere realmente tu cliente
BDD: Descubriendo qué requiere realmente tu cliente
 
Introducción a Ganglia
Introducción a GangliaIntroducción a Ganglia
Introducción a Ganglia
 
Alta disponibilidad con MySQL
Alta disponibilidad con MySQLAlta disponibilidad con MySQL
Alta disponibilidad con MySQL
 
Software Debt: Qué Es y Cómo Gestionarlo Holísticamente
Software Debt: Qué Es y Cómo Gestionarlo HolísticamenteSoftware Debt: Qué Es y Cómo Gestionarlo Holísticamente
Software Debt: Qué Es y Cómo Gestionarlo Holísticamente
 
Escalabilidad y alto rendimiento con Symfony2
Escalabilidad y alto rendimiento con Symfony2Escalabilidad y alto rendimiento con Symfony2
Escalabilidad y alto rendimiento con Symfony2
 
OAUTH introducción y entretenida explicación.
OAUTH introducción y entretenida explicación.OAUTH introducción y entretenida explicación.
OAUTH introducción y entretenida explicación.
 
Conferencia Monitoreo de Servidores con Nagios
Conferencia Monitoreo de Servidores con NagiosConferencia Monitoreo de Servidores con Nagios
Conferencia Monitoreo de Servidores con Nagios
 
TDD with phpspec2
TDD with phpspec2TDD with phpspec2
TDD with phpspec2
 
Continous Delivering a PHP application
Continous Delivering a PHP applicationContinous Delivering a PHP application
Continous Delivering a PHP application
 
Maven Overview
Maven OverviewMaven Overview
Maven Overview
 
Automatizacion de proyectos con gradle
Automatizacion de proyectos con gradleAutomatizacion de proyectos con gradle
Automatizacion de proyectos con gradle
 
Integrando sonar
Integrando sonarIntegrando sonar
Integrando sonar
 
Introducción a DDD
Introducción a DDDIntroducción a DDD
Introducción a DDD
 
PhpSpec 2.0 ilustrated by examples
PhpSpec 2.0 ilustrated by examplesPhpSpec 2.0 ilustrated by examples
PhpSpec 2.0 ilustrated by examples
 
Building and Deploying Application to Apache Mesos
Building and Deploying Application to Apache MesosBuilding and Deploying Application to Apache Mesos
Building and Deploying Application to Apache Mesos
 
A new model for Docker image distribution
A new model for Docker image distributionA new model for Docker image distribution
A new model for Docker image distribution
 

Similar a Conferencia Rails: Integracion Continua Y Rails

Desarrollo con Java y metodologías agiles
Desarrollo con Java y metodologías agilesDesarrollo con Java y metodologías agiles
Desarrollo con Java y metodologías agiles
Jobsket
 
Test Unitarios y E2E front y Back
Test Unitarios y E2E front y BackTest Unitarios y E2E front y Back
Test Unitarios y E2E front y Back
Eric Zeidan
 
Intro a cakephp
Intro a cakephpIntro a cakephp
Intro a cakephp
Andy Dawson
 
Programa en Rails como si Jugases con Lego. Javier Ramirez
Programa en Rails como si Jugases con Lego. Javier RamirezPrograma en Rails como si Jugases con Lego. Javier Ramirez
Programa en Rails como si Jugases con Lego. Javier Ramirez
javier ramirez
 
Javier Ramirez Rails Plugins Pdf
Javier Ramirez Rails Plugins PdfJavier Ramirez Rails Plugins Pdf
Javier Ramirez Rails Plugins Pdf
javier ramirez
 
Rails Plugins. Javier Ramirez
Rails Plugins. Javier RamirezRails Plugins. Javier Ramirez
Rails Plugins. Javier Ramirez
javier ramirez
 
Presentacion Ruby on Rails en Universidad Autónoma 2009
Presentacion Ruby on Rails en Universidad Autónoma 2009Presentacion Ruby on Rails en Universidad Autónoma 2009
Presentacion Ruby on Rails en Universidad Autónoma 2009
Nelson Rojas Núñez
 
DeSymfonyDay 2014 - To mock or not to mock - Spanish
DeSymfonyDay 2014 - To mock or not to mock - SpanishDeSymfonyDay 2014 - To mock or not to mock - Spanish
DeSymfonyDay 2014 - To mock or not to mock - SpanishJordi Llonch
 
DeSymfonyDay 2014 - To mock or not to mock - Spanish
DeSymfonyDay 2014 - To mock or not to mock - SpanishDeSymfonyDay 2014 - To mock or not to mock - Spanish
DeSymfonyDay 2014 - To mock or not to mock - SpanishAkamon Engineering
 
DeSymfonyDay 2014 - To mock or not to mock - Spanish
DeSymfonyDay 2014 - To mock or not to mock - SpanishDeSymfonyDay 2014 - To mock or not to mock - Spanish
DeSymfonyDay 2014 - To mock or not to mock - SpanishJordi Llonch
 
Test Driven Infrastructure
Test Driven InfrastructureTest Driven Infrastructure
Test Driven Infrastructure
Angel Nuñez
 
Construccion de proyectos con gradle
Construccion de proyectos con gradleConstruccion de proyectos con gradle
Construccion de proyectos con gradle
David Gómez García
 
Introducción a NodeJS
Introducción a NodeJSIntroducción a NodeJS
Introducción a NodeJS
BEEVA_es
 
Conociendo Nuestro Fua interno
Conociendo Nuestro Fua internoConociendo Nuestro Fua interno
Conociendo Nuestro Fua interno
Jose Patricio Bovet Derpich
 
Integracion Continua
Integracion ContinuaIntegracion Continua
Integracion Continua
Lenin Lozano
 
Calidad de código en Chamilo: Behat, Travis-CI y Scrutinizer-CI
Calidad de código en Chamilo: Behat, Travis-CI y Scrutinizer-CICalidad de código en Chamilo: Behat, Travis-CI y Scrutinizer-CI
Calidad de código en Chamilo: Behat, Travis-CI y Scrutinizer-CI
Yannick Warnier
 
DotNet 2019 | Pablo Santos Luaces - Como migrar un producto multiplataforma a...
DotNet 2019 | Pablo Santos Luaces - Como migrar un producto multiplataforma a...DotNet 2019 | Pablo Santos Luaces - Como migrar un producto multiplataforma a...
DotNet 2019 | Pablo Santos Luaces - Como migrar un producto multiplataforma a...
Plain Concepts
 
Framework Catalyst
Framework CatalystFramework Catalyst
Framework Catalyst
Eduardo Rafael Petla
 
Desarrollo de aplicaciones multiplataforma 2/2
Desarrollo de aplicaciones multiplataforma 2/2Desarrollo de aplicaciones multiplataforma 2/2
Desarrollo de aplicaciones multiplataforma 2/2
Ignacio Muñoz Vicente
 
7 Gemas de Ruby on Rails que podrían salvarte el dia
7 Gemas de Ruby on Rails que podrían salvarte el dia7 Gemas de Ruby on Rails que podrían salvarte el dia
7 Gemas de Ruby on Rails que podrían salvarte el dia
Francisco Aranda
 

Similar a Conferencia Rails: Integracion Continua Y Rails (20)

Desarrollo con Java y metodologías agiles
Desarrollo con Java y metodologías agilesDesarrollo con Java y metodologías agiles
Desarrollo con Java y metodologías agiles
 
Test Unitarios y E2E front y Back
Test Unitarios y E2E front y BackTest Unitarios y E2E front y Back
Test Unitarios y E2E front y Back
 
Intro a cakephp
Intro a cakephpIntro a cakephp
Intro a cakephp
 
Programa en Rails como si Jugases con Lego. Javier Ramirez
Programa en Rails como si Jugases con Lego. Javier RamirezPrograma en Rails como si Jugases con Lego. Javier Ramirez
Programa en Rails como si Jugases con Lego. Javier Ramirez
 
Javier Ramirez Rails Plugins Pdf
Javier Ramirez Rails Plugins PdfJavier Ramirez Rails Plugins Pdf
Javier Ramirez Rails Plugins Pdf
 
Rails Plugins. Javier Ramirez
Rails Plugins. Javier RamirezRails Plugins. Javier Ramirez
Rails Plugins. Javier Ramirez
 
Presentacion Ruby on Rails en Universidad Autónoma 2009
Presentacion Ruby on Rails en Universidad Autónoma 2009Presentacion Ruby on Rails en Universidad Autónoma 2009
Presentacion Ruby on Rails en Universidad Autónoma 2009
 
DeSymfonyDay 2014 - To mock or not to mock - Spanish
DeSymfonyDay 2014 - To mock or not to mock - SpanishDeSymfonyDay 2014 - To mock or not to mock - Spanish
DeSymfonyDay 2014 - To mock or not to mock - Spanish
 
DeSymfonyDay 2014 - To mock or not to mock - Spanish
DeSymfonyDay 2014 - To mock or not to mock - SpanishDeSymfonyDay 2014 - To mock or not to mock - Spanish
DeSymfonyDay 2014 - To mock or not to mock - Spanish
 
DeSymfonyDay 2014 - To mock or not to mock - Spanish
DeSymfonyDay 2014 - To mock or not to mock - SpanishDeSymfonyDay 2014 - To mock or not to mock - Spanish
DeSymfonyDay 2014 - To mock or not to mock - Spanish
 
Test Driven Infrastructure
Test Driven InfrastructureTest Driven Infrastructure
Test Driven Infrastructure
 
Construccion de proyectos con gradle
Construccion de proyectos con gradleConstruccion de proyectos con gradle
Construccion de proyectos con gradle
 
Introducción a NodeJS
Introducción a NodeJSIntroducción a NodeJS
Introducción a NodeJS
 
Conociendo Nuestro Fua interno
Conociendo Nuestro Fua internoConociendo Nuestro Fua interno
Conociendo Nuestro Fua interno
 
Integracion Continua
Integracion ContinuaIntegracion Continua
Integracion Continua
 
Calidad de código en Chamilo: Behat, Travis-CI y Scrutinizer-CI
Calidad de código en Chamilo: Behat, Travis-CI y Scrutinizer-CICalidad de código en Chamilo: Behat, Travis-CI y Scrutinizer-CI
Calidad de código en Chamilo: Behat, Travis-CI y Scrutinizer-CI
 
DotNet 2019 | Pablo Santos Luaces - Como migrar un producto multiplataforma a...
DotNet 2019 | Pablo Santos Luaces - Como migrar un producto multiplataforma a...DotNet 2019 | Pablo Santos Luaces - Como migrar un producto multiplataforma a...
DotNet 2019 | Pablo Santos Luaces - Como migrar un producto multiplataforma a...
 
Framework Catalyst
Framework CatalystFramework Catalyst
Framework Catalyst
 
Desarrollo de aplicaciones multiplataforma 2/2
Desarrollo de aplicaciones multiplataforma 2/2Desarrollo de aplicaciones multiplataforma 2/2
Desarrollo de aplicaciones multiplataforma 2/2
 
7 Gemas de Ruby on Rails que podrían salvarte el dia
7 Gemas de Ruby on Rails que podrían salvarte el dia7 Gemas de Ruby on Rails que podrían salvarte el dia
7 Gemas de Ruby on Rails que podrían salvarte el dia
 

Más de David Calavera

Rubyspec y el largo camino hacia Ruby 1.9
Rubyspec y el largo camino hacia Ruby 1.9Rubyspec y el largo camino hacia Ruby 1.9
Rubyspec y el largo camino hacia Ruby 1.9David Calavera
 
GTAC: AtomPub, testing your server implementation
GTAC: AtomPub, testing your server implementationGTAC: AtomPub, testing your server implementation
GTAC: AtomPub, testing your server implementationDavid Calavera
 
ApacheCon: Abdera A Java Atom Pub Implementation
ApacheCon: Abdera A Java Atom Pub ImplementationApacheCon: Abdera A Java Atom Pub Implementation
ApacheCon: Abdera A Java Atom Pub ImplementationDavid Calavera
 
Taller sobre la api 11870.com
Taller sobre la api 11870.comTaller sobre la api 11870.com
Taller sobre la api 11870.com
David Calavera
 
atomPub, ruby y la api de 11870
atomPub, ruby y la api de 11870atomPub, ruby y la api de 11870
atomPub, ruby y la api de 11870David Calavera
 

Más de David Calavera (8)

Trinidad
TrinidadTrinidad
Trinidad
 
JRuby hacking guide
JRuby hacking guideJRuby hacking guide
JRuby hacking guide
 
My name is Trinidad
My name is TrinidadMy name is Trinidad
My name is Trinidad
 
Rubyspec y el largo camino hacia Ruby 1.9
Rubyspec y el largo camino hacia Ruby 1.9Rubyspec y el largo camino hacia Ruby 1.9
Rubyspec y el largo camino hacia Ruby 1.9
 
GTAC: AtomPub, testing your server implementation
GTAC: AtomPub, testing your server implementationGTAC: AtomPub, testing your server implementation
GTAC: AtomPub, testing your server implementation
 
ApacheCon: Abdera A Java Atom Pub Implementation
ApacheCon: Abdera A Java Atom Pub ImplementationApacheCon: Abdera A Java Atom Pub Implementation
ApacheCon: Abdera A Java Atom Pub Implementation
 
Taller sobre la api 11870.com
Taller sobre la api 11870.comTaller sobre la api 11870.com
Taller sobre la api 11870.com
 
atomPub, ruby y la api de 11870
atomPub, ruby y la api de 11870atomPub, ruby y la api de 11870
atomPub, ruby y la api de 11870
 

Último

Conceptos Básicos de Programación. Tecnología
Conceptos Básicos de Programación. TecnologíaConceptos Básicos de Programación. Tecnología
Conceptos Básicos de Programación. Tecnología
coloradxmaria
 
Índice del libro "Big Data: Tecnologías para arquitecturas Data-Centric" de 0...
Índice del libro "Big Data: Tecnologías para arquitecturas Data-Centric" de 0...Índice del libro "Big Data: Tecnologías para arquitecturas Data-Centric" de 0...
Índice del libro "Big Data: Tecnologías para arquitecturas Data-Centric" de 0...
Telefónica
 
TRABAJO DESARROLLO DE HABILIDADES DE PENSAMIENTO.pdf
TRABAJO DESARROLLO DE HABILIDADES DE PENSAMIENTO.pdfTRABAJO DESARROLLO DE HABILIDADES DE PENSAMIENTO.pdf
TRABAJO DESARROLLO DE HABILIDADES DE PENSAMIENTO.pdf
thomasdcroz38
 
Las lámparas de alta intensidad de descarga o lámparas de descarga de alta in...
Las lámparas de alta intensidad de descarga o lámparas de descarga de alta in...Las lámparas de alta intensidad de descarga o lámparas de descarga de alta in...
Las lámparas de alta intensidad de descarga o lámparas de descarga de alta in...
espinozaernesto427
 
Ventajas y desventajas de la desinfección con cloro
Ventajas y desventajas de la desinfección con cloroVentajas y desventajas de la desinfección con cloro
Ventajas y desventajas de la desinfección con cloro
durangense277
 
Estructuras básicas_ conceptos básicos de programación.pdf
Estructuras básicas_  conceptos básicos de programación.pdfEstructuras básicas_  conceptos básicos de programación.pdf
Estructuras básicas_ conceptos básicos de programación.pdf
ItsSofi
 
Desarrollo de Habilidades de Pensamiento.docx (3).pdf
Desarrollo de Habilidades de Pensamiento.docx (3).pdfDesarrollo de Habilidades de Pensamiento.docx (3).pdf
Desarrollo de Habilidades de Pensamiento.docx (3).pdf
AlejandraCasallas7
 
Conceptos básicos de programación 10-5.pdf
Conceptos básicos de programación 10-5.pdfConceptos básicos de programación 10-5.pdf
Conceptos básicos de programación 10-5.pdf
ValeriaAyala48
 
proyecto invernadero desde el departamento de tecnología para Erasmus
proyecto invernadero desde el departamento de tecnología para Erasmusproyecto invernadero desde el departamento de tecnología para Erasmus
proyecto invernadero desde el departamento de tecnología para Erasmus
raquelariza02
 
ACTIVIDAD DE TECNOLOGÍA AÑO LECTIVO 2024
ACTIVIDAD DE TECNOLOGÍA AÑO LECTIVO 2024ACTIVIDAD DE TECNOLOGÍA AÑO LECTIVO 2024
ACTIVIDAD DE TECNOLOGÍA AÑO LECTIVO 2024
DanielErazoMedina
 
Semana 10_MATRIZ IPER_UPN_ADM_03.06.2024
Semana 10_MATRIZ IPER_UPN_ADM_03.06.2024Semana 10_MATRIZ IPER_UPN_ADM_03.06.2024
Semana 10_MATRIZ IPER_UPN_ADM_03.06.2024
CesarPazosQuispe
 
INFORME DE LAS FICHAS.docx.pdf LICEO DEPARTAMENTAL
INFORME DE LAS FICHAS.docx.pdf LICEO DEPARTAMENTALINFORME DE LAS FICHAS.docx.pdf LICEO DEPARTAMENTAL
INFORME DE LAS FICHAS.docx.pdf LICEO DEPARTAMENTAL
CrystalRomero18
 
Conceptos Básicos de Programación Proyecto
Conceptos Básicos de Programación ProyectoConceptos Básicos de Programación Proyecto
Conceptos Básicos de Programación Proyecto
cofferub
 
trabajo de tecnologia, segundo periodo 9-6f
trabajo de tecnologia, segundo periodo 9-6ftrabajo de tecnologia, segundo periodo 9-6f
trabajo de tecnologia, segundo periodo 9-6f
zoecaicedosalazar
 
leidy fuentes - power point -expocccion -unidad 4 (1).pptx
leidy fuentes - power point -expocccion -unidad 4 (1).pptxleidy fuentes - power point -expocccion -unidad 4 (1).pptx
leidy fuentes - power point -expocccion -unidad 4 (1).pptx
Leidyfuentes19
 
Desarrollo de habilidades de pensamiento (2).pdf
Desarrollo de habilidades de pensamiento (2).pdfDesarrollo de habilidades de pensamiento (2).pdf
Desarrollo de habilidades de pensamiento (2).pdf
samuelvideos
 
DESARROLLO DE HABILIDADES DE PENSAMIENTO.pdf
DESARROLLO DE HABILIDADES DE PENSAMIENTO.pdfDESARROLLO DE HABILIDADES DE PENSAMIENTO.pdf
DESARROLLO DE HABILIDADES DE PENSAMIENTO.pdf
sarasofiamontezuma
 
Estructuras básicas_ conceptos de programación (1).docx
Estructuras básicas_ conceptos de programación  (1).docxEstructuras básicas_ conceptos de programación  (1).docx
Estructuras básicas_ conceptos de programación (1).docx
SamuelRamirez83524
 
3Redu: Responsabilidad, Resiliencia y Respeto
3Redu: Responsabilidad, Resiliencia y Respeto3Redu: Responsabilidad, Resiliencia y Respeto
3Redu: Responsabilidad, Resiliencia y Respeto
cdraco
 
Conceptos Básicos de Programación L.D 10-5
Conceptos Básicos de Programación L.D 10-5Conceptos Básicos de Programación L.D 10-5
Conceptos Básicos de Programación L.D 10-5
JulyMuoz18
 

Último (20)

Conceptos Básicos de Programación. Tecnología
Conceptos Básicos de Programación. TecnologíaConceptos Básicos de Programación. Tecnología
Conceptos Básicos de Programación. Tecnología
 
Índice del libro "Big Data: Tecnologías para arquitecturas Data-Centric" de 0...
Índice del libro "Big Data: Tecnologías para arquitecturas Data-Centric" de 0...Índice del libro "Big Data: Tecnologías para arquitecturas Data-Centric" de 0...
Índice del libro "Big Data: Tecnologías para arquitecturas Data-Centric" de 0...
 
TRABAJO DESARROLLO DE HABILIDADES DE PENSAMIENTO.pdf
TRABAJO DESARROLLO DE HABILIDADES DE PENSAMIENTO.pdfTRABAJO DESARROLLO DE HABILIDADES DE PENSAMIENTO.pdf
TRABAJO DESARROLLO DE HABILIDADES DE PENSAMIENTO.pdf
 
Las lámparas de alta intensidad de descarga o lámparas de descarga de alta in...
Las lámparas de alta intensidad de descarga o lámparas de descarga de alta in...Las lámparas de alta intensidad de descarga o lámparas de descarga de alta in...
Las lámparas de alta intensidad de descarga o lámparas de descarga de alta in...
 
Ventajas y desventajas de la desinfección con cloro
Ventajas y desventajas de la desinfección con cloroVentajas y desventajas de la desinfección con cloro
Ventajas y desventajas de la desinfección con cloro
 
Estructuras básicas_ conceptos básicos de programación.pdf
Estructuras básicas_  conceptos básicos de programación.pdfEstructuras básicas_  conceptos básicos de programación.pdf
Estructuras básicas_ conceptos básicos de programación.pdf
 
Desarrollo de Habilidades de Pensamiento.docx (3).pdf
Desarrollo de Habilidades de Pensamiento.docx (3).pdfDesarrollo de Habilidades de Pensamiento.docx (3).pdf
Desarrollo de Habilidades de Pensamiento.docx (3).pdf
 
Conceptos básicos de programación 10-5.pdf
Conceptos básicos de programación 10-5.pdfConceptos básicos de programación 10-5.pdf
Conceptos básicos de programación 10-5.pdf
 
proyecto invernadero desde el departamento de tecnología para Erasmus
proyecto invernadero desde el departamento de tecnología para Erasmusproyecto invernadero desde el departamento de tecnología para Erasmus
proyecto invernadero desde el departamento de tecnología para Erasmus
 
ACTIVIDAD DE TECNOLOGÍA AÑO LECTIVO 2024
ACTIVIDAD DE TECNOLOGÍA AÑO LECTIVO 2024ACTIVIDAD DE TECNOLOGÍA AÑO LECTIVO 2024
ACTIVIDAD DE TECNOLOGÍA AÑO LECTIVO 2024
 
Semana 10_MATRIZ IPER_UPN_ADM_03.06.2024
Semana 10_MATRIZ IPER_UPN_ADM_03.06.2024Semana 10_MATRIZ IPER_UPN_ADM_03.06.2024
Semana 10_MATRIZ IPER_UPN_ADM_03.06.2024
 
INFORME DE LAS FICHAS.docx.pdf LICEO DEPARTAMENTAL
INFORME DE LAS FICHAS.docx.pdf LICEO DEPARTAMENTALINFORME DE LAS FICHAS.docx.pdf LICEO DEPARTAMENTAL
INFORME DE LAS FICHAS.docx.pdf LICEO DEPARTAMENTAL
 
Conceptos Básicos de Programación Proyecto
Conceptos Básicos de Programación ProyectoConceptos Básicos de Programación Proyecto
Conceptos Básicos de Programación Proyecto
 
trabajo de tecnologia, segundo periodo 9-6f
trabajo de tecnologia, segundo periodo 9-6ftrabajo de tecnologia, segundo periodo 9-6f
trabajo de tecnologia, segundo periodo 9-6f
 
leidy fuentes - power point -expocccion -unidad 4 (1).pptx
leidy fuentes - power point -expocccion -unidad 4 (1).pptxleidy fuentes - power point -expocccion -unidad 4 (1).pptx
leidy fuentes - power point -expocccion -unidad 4 (1).pptx
 
Desarrollo de habilidades de pensamiento (2).pdf
Desarrollo de habilidades de pensamiento (2).pdfDesarrollo de habilidades de pensamiento (2).pdf
Desarrollo de habilidades de pensamiento (2).pdf
 
DESARROLLO DE HABILIDADES DE PENSAMIENTO.pdf
DESARROLLO DE HABILIDADES DE PENSAMIENTO.pdfDESARROLLO DE HABILIDADES DE PENSAMIENTO.pdf
DESARROLLO DE HABILIDADES DE PENSAMIENTO.pdf
 
Estructuras básicas_ conceptos de programación (1).docx
Estructuras básicas_ conceptos de programación  (1).docxEstructuras básicas_ conceptos de programación  (1).docx
Estructuras básicas_ conceptos de programación (1).docx
 
3Redu: Responsabilidad, Resiliencia y Respeto
3Redu: Responsabilidad, Resiliencia y Respeto3Redu: Responsabilidad, Resiliencia y Respeto
3Redu: Responsabilidad, Resiliencia y Respeto
 
Conceptos Básicos de Programación L.D 10-5
Conceptos Básicos de Programación L.D 10-5Conceptos Básicos de Programación L.D 10-5
Conceptos Básicos de Programación L.D 10-5
 

Conferencia Rails: Integracion Continua Y Rails

  • 1. Integración Continua y Rails David Calavera 11870.com
  • 2. ego slide • desarrollador en 11870.com • open source: Hudson, Netbeans • commiter de la Fundación Apache
  • 4.
  • 6. sobre que NO trata esta charla
  • 7. nada que nos enganche Texto más a Rails
  • 8. como configurar un servidor de CI
  • 9. sobre que trata esta charla
  • 14. practica de reunir el código que estamos desarrollando frecuentemente, para verificarlo y evitar errores ” David Calavera
  • 15. Continuous Integration is a software development practice where members of a team integrate their work frequently, usually each person integrates at least daily - leading to multiple integrations per day. Each integration is verified by an automated build (including test) to detect integration errors as quickly as possible. Many teams find that this approach leads to significantly ” reduced integration problems and allows a team to develop cohesive software more rapidly. Martin Fowler
  • 19. descubrir errores pronto http://www.agitar.com/solutions/why_unit_testing.html
  • 20. baja calidad del código
  • 23. automatizar el build • reducir el número de procesos manuales • ¡¡Rails --tasks --silent | wc -l a ejecutar!! incorpora 71 tareas • rake • ¡¡Capistrano añade 22 -tareas más!! • expr `cap --tasks | wc -l` 7
  • 25. reducir su duración • usar una máquina dedicada para CI • mejorar el rendimiento de nuestros tests • separar los tests por categorías • ejecutar el build por etapas
  • 26. ejecutar los test en paralelo • sudo gem install deep_test DeepTest::TestTask.new 'deep_test:functionals' do |t| t.pattern = quot;test/functional/**/*_test.rbquot; t.number_of_workers = 2 end
  • 27. ejecutar los test en paralelo • también para RSpec Spec::Rake::SpecTask.new 'deep_spec:functionals' do |t| t.spec_files = FileList['spec/functional/**/*_spec.rb'] t.deep_test :number_of_workers => 2 end
  • 28. ejecutar los test en paralelo • ¡con una base de datos para cada worker! DeepTest::TestTask.new 'deep_test:functionals' do |t| t.pattern = quot;test/functional/**/*_test.rbquot; t.worker_listener = 'DeepTest::Database::MysqlSetupListener' end
  • 29. usar un servidor de CI • preguntar por cambios en el repositorio • realizar acciones en horarios determinados • soportar diferentes herramientas • mostrar builds históricos • soportar diferentes tipos de informes • soportar diferentes tipos de notificaciones
  • 31. CruiseControl.rb • muy POCO “user friendly” • plugins perdidos por internet • pero muy fáciles de desarrollar • http://cruisecontrolrb.thoughtworks.com
  • 33. Hudson • MUY “user friendly” • plugins muy fácilmente localizables • pero algo más complicado de desarrollar • http://hudson.dev.java.net
  • 35. Run Code Run • de momento solo proyectos open source • de momento solo se integra con github • soporte de CI para la última Rails Rumble • http://runcoderun.com
  • 41. arreglar el build inmediatamente
  • 45. ¿qué pasos hay que seguir para montar un sistema de CI?
  • 46. 1. integración de la base de datos
  • 47. lo que hay que hacer • automatizar los cambios de la base de datos • crear la base de datos • modificar la base de datos • testing e inspección
  • 48. Migraciones • muchas mejoras desde Rails 2.1 create db/migrate/20081112232842_modify_user.rb class ModifyUser < ActiveRecord::Migration def self.up change_table :user do |user| t.rename :surname, :last_name t.remove :age ... end end end
  • 50. test unitarios • enfocados en un objeto • comprobar installes totalmente unitario que • sudo gem unit_record ActiveRecord::Base.disconnect! • usar mocks en lugar de fixtures
  • 51. test unitarios • ¡¡hay que hacerlos para cualquier clase!! •sudo gem install unit_controller def setup @controller = UserController.new @controller.do_not_render_vew end
  • 52. test funcionales • usa factories en lugar de fixtures • sudo gem install thoughtbot-factory_girl Factory.define :user do |u| u.first_name 'Joe' u.last_name 'Doe' u.email {|att| quot;#{att.first_name}@example.comquot;.downcase } end
  • 53. test funcionales • ¡¡hay que hacerlos modelotodas lasde datos para clases!! • interacción entre el y la base • interacción entre el modelo y el controlador • interacción entre el controlador y la vista
  • 55. reducir la complejidad • Flog def flog(output, *directories) `find #{directories.join(quot; quot;)} -name *.rb|xargs flog > #{RAILS_ROOT}/tmp/flog/#{output}.txt` end desc quot;Flog models, controller, helpers and libquot; task :flog do flog quot;allquot;, *%w[app/models app/controllers app/helpers lib] end
  • 56. eliminar código duplicado o sin usar • Dust def unused_lvar a = 1 1 + 2 end d = Dust::LocalVariableDuster.new(Object, :unused_lvar) d.dust! d.warnings
  • 57. eliminar código duplicado o sin usar • PMD-CPD def cpd(*directories) `java net.sourceforge.pmd.cpd.CPD --minimum-tokens 100 -files #{directories.map(quot; --files quot;)} --language ruby` end task :cpd do cpd *%w[app/models app/controllers app/helpers lib] end
  • 58. comprobar cobertura • Rcov desc 'Test coverage report' task :coverage do rm_f quot;coveragequot; rm_f quot;coverage.dataquot; rcov = quot;rcov --rails --aggregate coverage.data -Ilibquot; `#{rcov} --no-html test/unit/*_test.rb` `#{rcov} --no-html test/functional/*_test.rb` `#{rcov} --html test/integration/*_test.rb` `open coverage/index.html` if PLATFORM['darwin'] end
  • 59. all in one • Metrics_fu para cruisecontrol.rb • Saikuro • Flog • Rcov • Rails stats • RubyMetrics para hudson • Rcov • Rails stats
  • 62. deploy continuo • etiquetar el repositorio • producir un entorno limpio • etiquetar cada build • tener la capacidad de volver atrás
  • 64. feedback continuo • la información correcta • a la persona indicada • en el momento esperado • de la forma correcta
  • 65.
  • 66.
  • 67.
  • 69. Fotos • http://flickr.com/photos/chicanerii/507573394 • http://flickr.com/photos/3epmedia/1160364177 • http://flickr.com/photos/cathycracks/183170786 • http://flickr.com/photos/smitty/2245445147/ • http://flickr.com/photos/fcw/384316867/ • http://www.flickr.com/photos/auxesis/2965947278/ • http://www.flickr.com/photos/penguin_man44/1203331011/ • http://flickr.com/photos/rekha6/2902282813/ • http://flickr.com/photos/teepee1/1508261796/ • http://flickr.com/photos/teepee1/2614839885/ • http://flickr.com/photos/_saturnine/2294717858/ • http://flickr.com/photos/ezra/459279198/ • http://flickr.com/photos/x180/1397019888 • http://flickr.com/photos/soulcheck/384769773/ • http://flickr.com/photos/znachor/255143511/ • http://flickr.com/photos/julianbleecker/156303245/