TDD con ASP.NET MVC
Jorge Bustos | [email protected], Servicios Profesionales
[email protected]| www.danysoft.com18.04.2013
Contenido de la sesión
• Las pruebas unitarias
• ¿Qué es eso de TDD?
• Inyección de dependencias
• Cómo hacer TDD con MVC
TDD con ASP.NET MVC
Las pruebas unitarias
Todo los desarrolladores probamos
Como poco, F5 y ver que funciona, pero: – Proceso manual
– Proceso pesado (lleva mucho tiempo) Incluso si lo hace un QA y no el desarrollador
Muchas veces se desarrollan pequeños programas, módulos o páginas específicas para probar
Todo los desarrolladores probamos.
Algunos mejor que otros.
Problemas de las “pruebas chapuceras”:
• Pruebas incompletas (se prueba sólo algún caso)
• Errores detectados tarde
• No se sabe exactamente la causa del error
• Aparecen “daños colaterales” al arreglar un error y
d ibid
pasan desapercibidos
Qué son las pruebas unitarias
Pruebas que
– Verifican pequeños fragmentos de códigop q g g – No dependen de otros módulos
– Sólo comprueban la parte pública de las clases – Se ejecutan rápidamente y dan resultados
(rojo/verde)
Incrementan la calidad del código: menos bugs – Incrementan la calidad del código: menos bugs
Anatomía de la prueba: triple A
Arrange:
– Preparaciónp
Act
– Ejecución del código bajo prueba
Assert
– Aserciones
Qué es un proyecto de pruebas
Es una librería de clases
Con referencias a:
Con referencias a:
– Un Framework de pruebas
– Las clases que se desean probar
Con clases con métodos que:
– Ejecutan la triple A
Ejecución de pruebas
Las pruebas se ejecutan con el ejecutor del
Framework de pruebas
– Busca las pruebas marcadas con atributos – Las ejecuta
– Registra los resultados de las aserciones
Frameworks de pruebas
Visual Studio incluye, y con buena integración, MSTest
Frameworks de terceros: xUnit.NET, NUnit, MbUnit… Incluyen ejecutores de pruebas, algunos integrables en Visual Studio
Los hay incluso para JavaScript, como QUnit o Jasmine
TDD con ASP.NET MVC
¿Qué es eso de TDD?
Qué es eso de TDD
Test Driven Development =
Desarrollo dirigido por pruebas Antes de implementar algo de código…
…se escribe la prueba unitaria que deberá pasar (Algunos lo llaman Test First Development)
El ciclo rojo-verde
Definición de pruebas
Primera tentativa de implementación
Primera tentativa de implementación
Ejecución de las pruebas: verdes y rojas
Ciclos de tentativas de implementación +
pruebas hasta que todas resulten verdes
Refactorización (opcional, pero recomendable)
Herramientas soportadas por VS y TFS
Todas las versiones proporcionan ejecución de MSTest
La Ultimate y Premium añaden:y
– Medición de cobertura de código – Ejecución de pruebas de IU:
• Ejecuta aplicación web • Rellena “inputs”
• Hace clicks en enlaces o botones
• Comprueba la interfaz resultanteComprueba la interfaz resultante
TFS puede automatizar la ejecución de pruebas unitarias (integración continua con Team Foundation Build)
Demo: calculadora
Se desea una clase calculadora de tipo decimal que – Sume
– Reste – Multiplique – Divida
La división por cero debe lanzar una excepción Ver cómo las pruebas unitarias facilitan la depuración del
f t d ódi d i t é
fragmento de código de interés
Algunas ventajas de TDD
Las pruebas unitarias incrementan la calidad del código (menos bugs)
Las pruebas son de mayor calidad porque no se hacen tarde
La calidad del diseño aumenta porque implementar las pruebas exige entender bien los requisitos
Ventajas adicionales de TDD
El código resultante se desacopla por requerir Inyección de Dependencias
Se implementa sólo lo estrictamente necesario (lo requerido por las pruebas unitarias)
Las pruebas no están contaminadas por la implementación interna: no se prueba ni más ni menos de la cuenta
La cobertura de pruebas no es tan importante
Cuánta gente se necesita
para programar con TDD
Depende de las metodologías y el tamaño de los equipos:q p
– Las puede implementar el propio desarrollador – Las puede implementar personal de QA
– Las puede implementar el analista que recoge los requisitos
– Una combinación mezcla de todo
TDD con ASP.NET MVC
Inyección de dependencias
¿Qué pasa con las dependencias en las
pruebas unitarias?
El ejemplo anterior fue sencillo: no había dependencias
Las pruebas unitarias requieren aislamiento de módulos: debemos controlar las dependencias
La independencia se consigue: Remplazando las p g p
dependencais de las que depende el código probado (con Mocks, Stubs, Doubles, Fakes o como quiera
¿Para qué sirve la
inyección de dependencias?
Permite implementar código desacoplado: aumenta la mantenibilidad
Permiten software modular, en el que pueden
sustituirse piezas, o elegirse en tiempo de ejecución Facilita aislar los módulos para ejecutar las pruebas unitarias, inyectando “sustitutos”
¿Cómo se hace la inyección de
dependencias?
La clase dependiente “declara las dependencias” por ej. con constructor que las recibe
El Framework de DI proporciona las dependencias al instanciar las clases dependientes
Muy importante: programar para interfaces o clases y p p g p base abstractas
¿Sastres? Las costuras y los patrones
Costura: sitio por donde se puede “descoser” el programa para insertar una dependencia
Patrones:
• Adaptador, Decorador, RRR, Raíz de
dependencia, Localizador de servicios… OJO: los malos sastres se pinchan con la aguja
Contenedores de DI
Son capaces de proporcionar las dependencias Uso del contenedor, con la triple R:
• Register
• Resolve
• Release
DEMO: inyección de dependencia
Catálogo de productos
Mostrar las dependencias del catálogo
Explicar como se inyectan con el contenedor de DI
TDD con ASP.NET MVC
Cómo hacer TDD con MVC
¿Qué se debería cambiar para
usar TDD con ASP.NET MVC?
Utilizar inyección de dependencias, para poder aislar las pruebas unitarias
Controladores:
– Mantener la lógica de negocio fuera de ellos – Inyectando dependencias por constructor
– Procurar hacer uso mínimo de HttpContext (Request, Response, Session…)
Usar más parámetros en e de UpdateModel – Usar más parámetros en vez de UpdateModel Filtros: para actividades ortogonales
Qué permite hacer TDD con MVC
Posibilidad de “sustituir” HttpContextBase, HttpRequestBase (pero no recomendable)
Separación muy clara en capasp y p
– Modelos: en realidad suelen ser librerías externas de datos y lógica de negocio
– Controladores: clases fáciles de probar
– Vistas: se pueden comprobar los modelos de vista Fácil implementar inyección de dependencias (utilizando factorías, “resolvedores” de
¿Qué se puede probar?
Controladores
Modelos de vistas
Modelos de vistas
Capas de lógica de negocio
Capa de “lógica de vista” (si se implementa)
Rutas (mapeadas e ignoradas)
Validadores (son atributos de validación)
Validadores (son atributos de validación)
– Dependen de ValidationContext inyectable por constructor
¿Qué fue antes, la interfaz
de usuario o las pruebas?
Es posible hacer el proyecto de fuera a dentro (de IU a lógica, sin dejar de hacer TDD):
– El diseño de la UI: las vistas requieren objetos
– Los controladores deben generar los objetos a las vistas
pruebas unitarias de controladores, con Mocks de
lógica de negocio
– Al implementar las pruebas de controladores se define la funcionalidad de lógica de negocios g g Pruebas de lógica de negocio
Demo: TDD con MVC
Paso 1: Al entrar al cajero:
– si no hay tarjeta pedirla (vista PedirTarjeta) – Si ya hay tarjeta, pedir el pin (vista PedirPin)
– Si el PIN no es bueno, mostrar mensaje y volver a pedirlo
NOTAS: Se ha implementado la interfaz, pero la aplicación no puede ejecutarse. Sin embargo se puede probar.
Paso 2: hacer pruebas e implementar controlador Paso 2: hacer pruebas e implementar controlador
NOTA: la aplicación no funciona pero está probada
Paso 3: arrancar la aplicación con DI Unity.MVC4