Testing y Mocking: Probando Aplicaciones

Documentos relacionados
Testing. Tipos, Planificación y Ejecución de Pruebas

Técnicas Avanzadas de Testing Automático

Ingeniería de Software. Pruebas

NUEVAS TENDENCIAS EN LA CALIDAD DEL SOFTWARE IGNACIO BAYUGAR

Demo. TDD desde Cero. Acceptance Test Driven Development.

BETA. Sacándole Partido a JUnit. Mocking. formacion@iwt2.org

Pruebas unitarias en profundidad

Ingeniería del Software. La última lección. Resumen del curso. Buenas prácticas. Conclusión

Pruebas de unidad con JUnit

Programación Orientada a Objetos en Java

Hoy terminamos caja blanca

Patrones Creacionales Builder. Patrones Creacionales Abstract Factory. Patrones Creacionales Singleton. Patrones Creacionales Prototype

Introducción a las Metodologías Ágiles. Nicolás Brailovsky March 7, 2009

Tema 3: Herencia en C++ Programación Orientada a Objetos Curso 2008/2009 Begoña Moros Valle

PRUEBAS DE SOFTWARE TECNICAS DE PRUEBA DE SOFTWARE

Ingeniería del Software. Pruebas. Pruebas en el PUD. Las pruebas del software. Tipos de prueba Estrategias de prueba

Introducción al Proceso de Pruebas.

Figura 1. Símbolo que representa una ALU. El sentido y la funcionalidad de las señales de la ALU de la Figura 1 es el siguiente:

Porque hacemos Testing? BY: ALFREDO ALVAREZ

Curso de Java POO: Programación orientada a objetos

Mejor Framework PythonOO + SOLID. Vivir sin Frameworks

Capítulo 4 Pruebas e implementación de la aplicación CAPÍTULO 4 PRUEBAS E IMPLEMENTACIÓN DE LA APLICACIÓN

Serie Artículos sobre Gestión de IT y Calidad CALIDAD vs TESTING

Plan de estudios ISTQB: Nivel Fundamentos

Ingeniería del Software I Clase de Testing Funcional 2do. Cuatrimestre de 2007

Curso de Spring Framework

Criterios de clasificación

COMO CONFIGURAR UNA MAQUINA VIRTUAL EN VIRTUALBOX PARA ELASTIX

Sistemas de Información Administrativo - Universidad Diego Portales. Cátedra : Sistemas de Información Administrativa S.I.A.

Capitulo III. Diseño del Sistema.

TUTORIAL DE PHP. M. en C. Erika Vilches. Parte 2.

Ejemplos de conversión de reales a enteros

E Documento de entrega de Aplicación

2002 Emerson Process Management. Todos los derechos reservados. Vea este y otros cursos en línea en

Programación I: Funciones y módulos

Proxy Introducción

Baires. Design - Test - Automate

Artesanía de So-ware y Desarrollo Dirigido por Pruebas

De la Integración Continua a la Entrega Continua

Ciclo de vida y Metodologías para el desarrollo de SW Definición de la metodología

Principios y Métricas para el diseño de software

Técnicas de prueba 1. FUNDAMENTOS DE LA PRUEBA DEL SOFTWARE

Modelamiento de Amenazas en el Desarrollo de Software

Técnicas Avanzadas de Testing Automatizado

Modificación y parametrización del modulo de Solicitudes (Request) en el ERP/CRM Compiere.

Técnicas Avanzadas de Testing Automatizado

Tema 3. Test Driven Development

Proceso de implementación OpenERP

Construcción y Pruebas de Software

MANUAL DE USUARIO APLICACIÓN SYSACTIVOS

PROGRAMACIÓN ORIENTADA A OBJETOS Master de Computación. II MODELOS y HERRAMIENTAS UML. II.2 UML: Modelado de casos de uso

Capitulo 3. Test Driven Development

Conceptos. ELO329: Diseño y Programación Orientados a Objetos. ELO 329: Diseño y Programación Orientados a Objetos

Manejo de versiones 392

GUÍA DE EVIDENCIA DE LA UNIDAD DE COMPETENCIA

SAP Business Workflow

Las pruebas unitarias se crean en una carpeta raíz del symfony: Test/Unit/EjemploTest.php

3.1 INGENIERIA DE SOFTWARE ORIENTADO A OBJETOS OOSE (IVAR JACOBSON)

Procesos Críticos en el Desarrollo de Software

SOLUCION PARCIAL TASK SCHEDULER. Task Scheduler

Base de datos en Excel

2 EL DOCUMENTO DE ESPECIFICACIONES

Soluciones Informáticas para la Gestión de la Calidad c/vicente Aleixandre nº 10 4º H, A CORUÑA Telf: / info@spuch.

Curso de JavaServer Faces

Introducción a PHP. * No es necesario declarar previamente las variables.

CAPÍTULO 1 PRIMEROS PASOS

El Proceso de Pruebas de acuerdo a los estandares y la experiencia.

GUIA PROGRAMACIÓN ORIENTADA A OBJETOS

Refactorizar (v) Reestructurar el software aplicando una secuencia de refactorizaciones.

Leica Application Suite

Empresa Financiera Herramientas de SW Servicios

CAPÍTULO 5. PRUEBAS Y RESULTADOS

PRUEBAS, CALIDAD Y MANTENIMIENTO DEL SOFTWARE

2.0 QUÉ ES NECESARIO PARA EMPEZAR A OPERAR CON FUTUROS?

Temario. Introducción Hello Word y Literales Expresiones Bloques Programación orientada a objetos (OOP) Introspección Rake Gemas

Introducción a las Pruebas de Software

Reporte inicial. Metodología

Arquitectura de sistema de alta disponibilidad

Entregable proyecto 3

CLASE # 5 TÉCNICAS DE CAJA BLANCA

Testing y Drupal. Rosa María Orellana Maldoando

XP- EXTREME PROGRAMMING

El modelo de datos para la definición de puertas y recintos es el siguiente:

Resumen. Funcionamiento. Advertencia

Actividades para mejoras. Actividades donde se evalúa constantemente todo el proceso del proyecto para evitar errores y eficientar los procesos.

FUNDACION NIC-NIIF

Orígenes y descripción de la Automatización 'Inteligente'

+ Cómo ahorrar dinero con Software Quality

Puedes manejar todas las áreas de tu negocio?

1. Descripción y objetivos

Introducción a la Programación Orientada a Objetos (POO) Introducción a la Programación Orientada a Objetos (POO)

Contenido. Tipos y niveles de pruebas de software Pruebas de caja negra

TEMA 7: DIAGRAMAS EN UML

DISCOS RAID. Se considera que todos los discos físicos tienen la misma capacidad, y de no ser así, en el que sea mayor se desperdicia la diferencia.

Algunas Herramientas de Apoyo al Análisis y Diseño de Software. Agustín J. González ELO329: Diseño y programación orientados a objetos

SOLICITUD DE PROPUESTA

No se requiere que los discos sean del mismo tamaño ya que el objetivo es solamente adjuntar discos.

Para qué XP_CRYPT y SQL Shield?

Transcripción:

Testing y Mocking: Probando Aplicaciones

1 Introducción 2 Tipos de tests 3 Inyección de dependencias, DI 4 Mocking

Outline 1 Introducción 2 Tipos de tests 3 Inyección de dependencias, DI 4 Mocking

Outline 1 Introducción Planteando el problema Qué es testing?

Cuando escribimos software falta tiempo hacemos suposiciones el código queda feo proyectos legacy sin andar falta tiempo de refactor Por todo esto la calidad se degrada

Si bien no hay silver bullets Veremos como, testeando, el proyecto sale mejor. Los tests: generan confianza permiten la detección temprana de bugs ayudan a detectar inconsistencias en RQs mejoran la productividad (a largo plazo)

Si bien no hay silver bullets Veremos como, testeando, el proyecto sale mejor. Siempre considerando que, los tests... no garantizan el éxito de un proyecto no aseguran 100% de calidad no son aplicables a todo proyecto obligan a pensar antes de programar! a a Queda como ejercicio determinar si esto es bueno o no Pero, Qué es testing?

Outline 1 Introducción Planteando el problema Qué es testing?

Qué es testing? Testear el software es: validar su comportamiento validar un set de datos validar requerimientos una forma de medir la calidad Testear el software no es: asegurar el éxito del proyecto afirmar que no hay bugs "a silver bullet"

Algunos "extras" El testing (o, mejor, TDD) ayuda a: especificar requerimientos especificar comportamiento evitar regresiones refactorizar

Cómo testear Vimos muchos motivos, muy dispares... todo eso con un test? No, hay distintos tipos. Veamos algunos.

Outline 1 Introducción 2 Tipos de tests 3 Inyección de dependencias, DI 4 Mocking

Outline 2 Tipos de tests Tests unitarios Tests de regresión Integración Continua Tests de integración Stress tests Otras clasificaciones

Tests unitarios: el tipo de test mas básico Prueba sólo una clase (aislada) repetibles y deterministicos automáticos se componen de varios tests cases cada test case prueba un aspecto de funcionalidad... que es un requerimiento (de la clase)

Veamos un ejemplo... 1 def Vehiculo.avanzar 2 if combustible > 0 then 3 combustible=combustible-1 4 return self.velocidad 5 else 6 destruido = true 7 return 0 8 end 9 end 10 def Avion.velocidad() return 20 end 11 def Submarino.velocidad() return 10 end

Para el ejemplo Armemos un test unitario que verifique que los vehículos se destruyen si no tienen combustible 1 def test_destruccion 2 avion = Avion.new 3 submarino = Submarino.new 4 5 {avion, submarino}. 6 each.set_combustible 0 7 8 Expect{ avion.avanzar == 0 } 9 Expect{ avion.destruido == true } 10 Expect{ submarino.avanzar == 0 } 11 Expect{ submarino.destruido == true } 12 end

Outline 2 Tipos de tests Tests unitarios Tests de regresión Integración Continua Tests de integración Stress tests Otras clasificaciones

Tests de regresión Los tests de regresión en verdad son tests unitarios que ya funcionan además de requerimientos puede validar "bugs" se corren luego de cada refactor bugfix hacer un deploy en general, modificación verifican si existe una regresión

Siguiendo el ejemplo... 1 def test_destruccion 2 avion = Avion.new 3 submarino = Submarino.new 4 jeep = Jeep.new 5 6 {avion, submarino, jeep}. 7 each.set_combustible 0 8 9 Expect{ avion.avanzar == 0 } 10 Expect{ avion.destruido == true } 11 Expect{ submarino.avanzar == 0 } 12 Expect{ submarino.destruido == true } 13 Expect{ jeep.avanzar == 0 } 14 Expect{ jeep.destruido == false } 15 end

Y corremos el test... Qué falló? 1 def Vehiculo.avanzar 2 if combustible > 0 then 3 combustible=combustible-1 4 return self.velocidad 5 else 6 destruido = true 7 return 0 8 end 9 end 10 def Avion.velocidad() return 20 end 11 def Submarino.velocidad() return 10 end

Corregimos el error, y ahora si... 1 def Jeep.avanzar 2 if combustible > 0 then 3 combustible=combustible-1 4 return self.velocidad 5 else 6 return 0 7 end 8 end

Outline 2 Tipos de tests Tests unitarios Tests de regresión Integración Continua Tests de integración Stress tests Otras clasificaciones

Integración continua Si un test que antes funcionaba ahora falla: existe una regresión entre el último commit testeado y el actual menos commits = mas fácil descubrir la causa uno por commit se llama integración continua!

Integración continua Un servidor de IC requiere tests "rápidos" puede schedulear tests "lentos" diariamente provee feedback del commit en cuestión de minutos requiere tests deterministicos y repetibles!

Integración continua Un servidor de IC requiere tests "rápidos" puede schedulear tests "lentos" diariamente provee feedback del commit en cuestión de minutos requiere tests deterministicos y repetibles! Veamos una demo con el Cruise Control!

Outline 2 Tipos de tests Tests unitarios Tests de regresión Integración Continua Tests de integración Stress tests Otras clasificaciones

Tests de integración Tests de Integración!= Integración Continua Los tests de integración: prueban mas de un componente pueden implementarse como tests unitarios no siempre son deterministicos o repetibles no siempre son "rápidos"

Por qué? Tener solo tests de integración no es cost-effective: 1 def foo(x, y, z) 2 if z then 3 bar(x) 4 else 5 baz(y) 6 end 7 end Cuántos tests unitarios son? Cuántos tests de integración son?

Tests de integración Integración N Función x y z 1 foo true true true 2 foo true true false 3 foo true false true 4 foo true false false 5 foo false true true 6 foo false true false 7 foo false false true 8 foo false false false Unitario N Función x y 1 bar true N/A 2 bar false N/A 3 baz N/A true 4 baz N/A false Hacen falta 8 tests de integración y 4 unitarios Entonces, conviene usar tests de integración?

Por qué no? Los tests para ambas funciones son simples Pero en conjunto andan muy mal! test_multiplicar_manzanas () test_get_peras () multiplicar_manzanas( get_peras () )

Outline 2 Tipos de tests Tests unitarios Tests de regresión Integración Continua Tests de integración Stress tests Otras clasificaciones

stress tests qué son? verifican el funcionamiento bajo carga simulan un entorno de producción pocas veces son automáticos

Outline 2 Tipos de tests Tests unitarios Tests de regresión Integración Continua Tests de integración Stress tests Otras clasificaciones

Orientado a los datos Cuando armarmos un test: Se toma un módulo Determinamos las entradas Evaluamos las salidas Buscamos casos límite Existe un contrato implicito 1 def test_division 2 Expect{1 == 2/2} 3 Expect{Err == 1/0} 4 Expect{-5 == -5/1} 5 Expect{-5 == 5/-1} 6 Expect{5 == -5/-1} 7 # Etc... 8 end

Orientado al comportamiento Cuando armarmos un test (en un proyecto testeable): Pensamos en término de objetos y relaciones... y no tanto en función de la entrada-salida Los objetos tienen interfaces... e interactuan con otros objectos Existe un contrato explícito No es necesario evaluar tantos casos limite

Outline 1 Introducción 2 Tipos de tests 3 Inyección de dependencias, DI 4 Mocking

Outline 3 Inyección de dependencias, DI Qué es DI Para qué usar DI DI aplicado

Empecemos con un ejemplo Qué pasa cuando corremos el test? 1 def test_compra 2 item = Empanada.new 3 item.precio = 2 4 venta = Venta.new 5 venta.add item 6 Expect{ venta.comprar == true } 7 Expect{ venta.total == 2 } 8 end

Empecemos con un ejemplo Qué pasa cuando corremos el test? 1 def test_compra 2 item = Empanada.new 3 item.precio = 2 4 venta = Venta.new 5 venta.add item 6 Expect{ venta.comprar == true } 7 Expect{ venta.total == 2 } 8 end Null ptr exception

Qué hay en la clase Venta? 1 def Venta.new 2 db = ResourceLocator.DbSingleton.get_instance 3 cliente = db.get_instance.get_ultimo_cliente 4 end 5 6 def Venta.add item 7 raise "Te falta plata!" 8 if cliente.billetera.saldo < self.total 9 10 items.add item 11 end 12 13 def Venta.comprar 14 cliente.billetera.debitar self.total 15 return self.total 16 end

Arreglemos el test... 1 def test_compra 2 # Scaffolding 3 dagoberto = Cliente.new 4 dagoberto.billetera = Billetera.new 5 dagoberto.billetera.saldo = 2 6 7 singleton = Singleton.new 8 singleton.instance = DB_Factory.new 9 ResourceLocator.DbSingleton = singleton 10 db = ResourceLocator.DbSingleton.get_instance 11 db.set_cliente = dagoberto 12 13 item = Empanada.new 14 item.precio = 2 15 16 # Test real - Dependencias ocultas 17 venta = Venta.new 18 venta.add item 19 Expect{ venta.comprar == true } 20 Expect{ venta.total == 2 } 21 end

Arreglemos el test... En el test se reflejan varios problemas Hay mucho "scaffolding" El sentido del test se pierde Hay dependencias ocultas Se accede a mas objetos que los necesarios El scope demasiado grande

Outline 3 Inyección de dependencias, DI Qué es DI Para qué usar DI DI aplicado

Podemos mejorar el diseño con DI La inyección de dependencias separa la construcción del uso hace explicitas las dependencias ayuda a simplificar la lógica limita el scope de un objeto reduce el factor sorpresa!

Dependency Injection Demystified La inyección de dependencias es en realidad muy simple Ask for what you need A un objeto se le dan sus dependencias El objeto inyectado no crea sus propias dependencias No mas singletons ni ServiceLocators Chau estado global

Outline 3 Inyección de dependencias, DI Qué es DI Para qué usar DI DI aplicado

Resultados 1 def Venta.new cuenta 2 self.cuenta = cuenta 3 end 4 5 def Venta.add item 6 raise "Te falta plata!" 7 if cuenta.saldo < self.total 8 9 items.add item 10 end 11 12 def Venta.comprar 13 cuenta.debitar self.total 14 return self.total 15 end

Resultados No solo el código es mas prolijo, el test también 1 def test_compra 2 item = Empanada.new 3 item.precio = 2 4 cuenta = Cuenta.new 5 cuenta.saldo = 2 6 7 # Test real - la dependencia es clara 8 venta = Venta.new cuenta 9 venta.add item 10 Expect{ venta.comprar == true } 11 Expect{ venta.total == 2 } 12 end

Outline 1 Introducción 2 Tipos de tests 3 Inyección de dependencias, DI 4 Mocking

Mocking: seguimos el ejemplo Sigamos el ejemplo de DI. Podemos mejoralo mas? Qué estamos testeando? Queremos testear el objeto "Cuenta"? Y si Cuenta aún no está implementado? O tiene muchos muchos bugs? O es muy lento? (P. ej: accede a la BD) Mocking es la solución!

Mocking Pero qué es "mocking"? técnica para testear un mock es un objeto "dummy" son "fakes" de partes del sistema definen su comportamiento "on the fly" usan la interfaz de un objeto real

Outline 4 Mocking Herencia, polimorfismo y Mocking DI y Mocking Ejemplos

Cómo funciona Se basa en el polimorfismo El Objeto testeable usa un objeto "mockeable" El mock hereda de una interfaz común al objeto real Al objeto testeable no le "importa" cual de los dos usa

Cómo funciona El objeto testeado no sabe si es una implementación real Tampoco importa, el mock usa la interfaz conocida Es un concepto similar al de usar varias implementaciones

Outline 4 Mocking Herencia, polimorfismo y Mocking DI y Mocking Ejemplos

Por qué DI + Mocking DI obliga a separar componentes Para testear hace falta aislar módulos Aislar módulo = sacar dependencias Mocking permite simular otros módulos Ergo... Mocking + DI r0ck$!!!!!11uno1

Outline 4 Mocking Herencia, polimorfismo y Mocking DI y Mocking Ejemplos

Mocking: seguimos el ejemplo II Veamos como queda el ejemplo 1 def test_compra 2 item = MockItem.new 3 cuenta = MockCuenta.new 4 item.expect_call("precio").returns( 2 ) 5 cuenta.expect_call("saldo").returns( 2 ) 6 cuenta.expect_call("debitar", 2).returns( true ) 7 8 venta = Venta.new cuenta 9 venta.add item 10 Expect{ venta.comprar == true } 11 Expect{ venta.total == 2 } 12 end

Mocking: ejemplo explicado Algunos detalles del ejemplo: 1 item.expect_call("precio").returns( 2 ) 2 cuenta.expect_call("saldo").returns( 2 ) 3 cuenta.expect_call("debitar", 2).returns( true ) El comportamiento se define con el mismo test Se define un set de "expectations" Las expectations son tests cada una debe cumplirse verifican el comportamiento del objeto Usando DI podemos inyectar una cuenta falsa... sería posible de no usar DI?

Preguntas? 42

Preguntas?