introducción a unit testing y tdd

91

Upload: fernando-perez

Post on 11-Jul-2015

149 views

Category:

Software


2 download

TRANSCRIPT

Page 1: Introducción a Unit Testing y TDD
Page 2: Introducción a Unit Testing y TDD

AGENDAa Introducción al software testing

a Pruebas Unitarias (Introducción, FIRST, Dobles)

a Principios SOLID

a TDD (Introducción, patrones y Visual Studio)

a Inyección de dependencias

Page 3: Introducción a Unit Testing y TDD

Software testingIntroducción

Page 4: Introducción a Unit Testing y TDD

Software testing / Introducción

¿Qué son las pruebas de software?Forma automatizada de probar, empíricamente, que un software funciona como se

espera.

¿Qué ganamos realizando pruebas de software?Fiabilidad, consistencia, eficiencia, mantenibilidad, mejor software y facilidad para el

refactoring. Pero sobre todo, dormir mucho mejor.

¿Qué precio debemos pagar?• Diseñar nuestro software para que sea testable facilmente (altamente cohesionado,

bajamente acoplado, etc).

• Crear y mantener nuestros tests como si fuese código de producción.

Class Cohesion Revisited: http://www.iro.umontreal.ca/~sahraouh/qaoose/papers/Kabaili.pdf

Page 5: Introducción a Unit Testing y TDD

Software testing / Introducción

Tipos de Tests• Tests unitarios

Comprueban el correcto funcionamiento de la mínima unidad de código posible (funcionalmente significativa).

• Tests de integraciónComprueban la interacción entre distintas entidades de nuestro software.

• Tests de regresiónAseguran la inmutabilidad del funcionamiento anterior a una modificación.

• Tests de Sistema (end-to-end)Prueban completamente un sistema integrado.

• Tests de aceptaciónPrueban la funcionalidad (habitualmente desde el punto de vista del usuario final).

Page 6: Introducción a Unit Testing y TDD

Pruebas unitariasIntroducción

Page 7: Introducción a Unit Testing y TDD

Pruebas unitarias / Introducción

Tests unitarios• Muy útiles por el alcance de su prueba (muy concreto).

• Imprescindibles para el practicante de TDD

• Solo comprobarán uno de los comportamientos de un método de una clase.

• Suelen ser tests de “caja blanca”.

• Cumpliran los principios FIRST.

Descritos por Robert C. Martín (Uncle Bob) en su libro Clean Code.

Page 8: Introducción a Unit Testing y TDD

Pruebas unitarias / Introducción

Organización de proyectos de Testing

• El proyecto de testing estará separado

del código de producción.

• Cada clase de test tendrá

correspondencia con una clase de

producción.

Page 9: Introducción a Unit Testing y TDD

Pruebas unitarias / Introducción

Atributos MSTESTS

• Obligatorios• TestClass / TestMethod

• Excepciones

• Comprobaciones (Asserts)

1 using Microsoft.VisualStudio.TestTools.UnitTesting;2 3 namespace LibraryTddCourseTests4 {5 [TestClass]6 public class MyProductionClassTests7 {8 [AssemblyInitialize]9 public static void AssemblyInit(TestContext context) {}10 11 [ClassInitialize]12 public static void ClassInit(TestContext context) {}13 14 [TestInitialize]15 public void Initialize() {}16 17 [TestMethod]18 public void TestMethod1() {}19 20 [TestCleanup]21 public void CleanUp() {}22 23 [ClassCleanup]24 public static void ClassCleanUp() { }25 26 [AssemblyCleanup]27 public static void AssemblyCleanup() { }28 }29 }

http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.classinitializeattribute.classinitializeattribute.aspx

[ExpectedException(typeof(System.DivideByZeroException))]

Assert.IsTrue(1 == 1);Assert.IsNull(null);Assert.AreEqual(2, 1 + 1);......

Page 10: Introducción a Unit Testing y TDD

Pruebas unitarias / Introducción

Ejecución de Tests

• Desde el Test Explorer• Denominados Test Runners

Page 11: Introducción a Unit Testing y TDD

Pruebas unitarias / Introducción

Partes de un Test Unitario• Arrange

Preparación del escenario a testear.

• Act

Acto de ejecución del código que va a

devolver el resultado a testear.

• Assert

Chequeo del resultado con las

comprobaciones de resultados.

// ArrangeMyProductionClass myProductionClass = new MyProductionClass();

// Actbool result = myProductionClass.GetBooleanResult();

// AssertAssert.IsTrue(result);

Page 12: Introducción a Unit Testing y TDD

Veamos unUNIT TEST

Page 13: Introducción a Unit Testing y TDD

Pruebas unitariasF.I.R.S.T.

Page 14: Introducción a Unit Testing y TDD

Pruebas unitarias / F.I.R.S.T.

Tests unitarios

• FastRápidos, muy rápidos

Si no se ejecutan rápidamente, no son tests unitarios

Page 15: Introducción a Unit Testing y TDD

Pruebas unitarias / F.I.R.S.T.

Tests unitarios

• Isolated (Independent)Solo tendrán una razón para fallar

Independientes del resto de tests, no afectan al estado final del SUT

El orden de ejecución no debe ser determinante

Deben poder lanzarse en paralelo

Page 16: Introducción a Unit Testing y TDD

Pruebas unitarias / F.I.R.S.T.

Tests unitarios

• RepeatableRepetibles, pueden ejecutarse cuantas veces se desee ofreciendo siempre el mismo

resultado.

Page 17: Introducción a Unit Testing y TDD

Pruebas unitarias / F.I.R.S.T.

Tests unitarios

• Self-ValidatingDe resultado booleano (no logs, no DB, etc).

Automático (no requiere comprobación manual).

Page 18: Introducción a Unit Testing y TDD

Pruebas unitarias / F.I.R.S.T.

Tests unitarios

• TimelySerán construidos en el momento oportuno, preferiblemente antes del código que

tratan de testear.

Debemos saber qué queremos construir con antelación.

Page 19: Introducción a Unit Testing y TDD

Pruebas unitariasDobles (Tests Doubles)

Page 20: Introducción a Unit Testing y TDD

Dobles/ Escenario

¿Y si una clase tiene dependencias?Si tiene dependencias y testeamos también esas dependencias, ¿seguro que es un

test de unidad?

¿Y si una de nuestras dependencias tiene problemas?Nuestro test fallará. Pero…

¿Realmente es un problema de nuestro código?

¿Podemos solucionar el problema o está fuera de nuestra capacidad?

¿Y si el problema es aleatorio o la dependencia es pesada?Dobles al rescate

Page 21: Introducción a Unit Testing y TDD

Dobles / Escenario

SUT

Page 22: Introducción a Unit Testing y TDD

Dobles / Escenario

SUT

Punto de falloPunto de fallo

Page 23: Introducción a Unit Testing y TDD

Dobles / Escenario

SUT

Page 24: Introducción a Unit Testing y TDD

Dobles / Introducción

¿Qué son?Objetos falsos que reemplazan a los verdaderos con el objeto de eliminar su

dependencia y poder hacer tests con comodidad.

¿En que consiste?En crear falsas clases que tendrán respuestas pre-determinadas y que inyectaremos a

nuestro SUT.

¿Cómo podemos hacer esto?Manualmente o con ‘Isolation Frameworks’ (frameworks de mocking)

Page 25: Introducción a Unit Testing y TDD

Dobles / Introducción

¿Distintos tipos de tests doubles?

Hay una fina línea que los diferencia que depende del autor.• Dummy

Objetos que son pasados como relleno de dependencias. Nunca son usados.

• FakeObjetos que tienen una implementación funcional pero con atajos que les impiden ser viables para

usarse en entornos de producción (una base de datos en memoria, por ejemplo).

• StubsObjetos que se preparan para ofrecer respuestas concretas a peticiones concretas. Pueden usar

verificación de estado (Assert).

• MocksObjetos sobre los que se tiene algún tipo de expectativa. Tienen Asserts que verifican

comportamiento.

Page 26: Introducción a Unit Testing y TDD

Dobles / Ejemplo

Page 27: Introducción a Unit Testing y TDD

Dobles / Ejemplo01 public class CustomerService02 {03 private ICustomerRepository _customerRepository;04 private IComplaintRepository _complaintRepository;05 private ICustomerCareNotificationService _customercareNotificationService;06 07 public CustomerService(ICustomerRepository customerRepository,08 IComplaintRepository complaintRepository,09 ICustomerCareNotificationService customerCareNotificationService)10 {11 this._customerRepository = customerRepository;12 this._complaintRepository = complaintRepository;13 this._customercareNotificationService = customerCareNotificationService;14 }15 16 public List<string> Complaints(int clientId)17 {18 var complaints = _complaintRepository.GetAllFromClientId(clientId);19 20 bool isAVipCustomer = _customerRepository.GetCustomerCategory(clientId);21 if (isAVipCustomer)22 SendNotificationToCustomerCare(clientId);23 24 var result = complaints.Select(c => c.Title);25 26 return result.ToList();27 }28 29 private void SendNotificationToCustomerCare(int clientId)30 {31 this._customercareNotificationService.SendNotificationAboutVipCustomerComplaint(clientId);32 }33 }

Page 28: Introducción a Unit Testing y TDD

Hagamos los testsde ejemplo con Dobles

Page 29: Introducción a Unit Testing y TDD

SOLID PrinciplesIntroducción

Page 30: Introducción a Unit Testing y TDD

SOLID / Introducción

Serie de principios de desarrollo en programación orientada a objetos

Originalmente recopilados por Robert C. Martín en 1995

Proporcionan un camino para conseguir código bajamente acoplado,

altamente cohesivo que encapsule las necesidades de negocio correctamente

Page 31: Introducción a Unit Testing y TDD

SOLID / Introducción

No es un framework

No es una librería

No son unos patrones

No son un objetivo

Son unos principios de diseño orientado a objetos

Son un medio para conseguir código desacoplado

Y por tanto un modo de hacer código más mantenible

Page 32: Introducción a Unit Testing y TDD

SOLID Principles

Page 33: Introducción a Unit Testing y TDD

SOLID

Page 34: Introducción a Unit Testing y TDD

SOLID / Single Responsibility Principle (SRP)

“Una clase debería tener una, y solo una, razón para cambiar”

Una clase debería tener una única responsabilidad.

Podemos aplicarlo también a los métodos de la clase.

Beneficios

Proporciona un código más desacoplado y más fácil de mantener.

Proporciona unas clases más pequeñas y limpias.

Page 35: Introducción a Unit Testing y TDD

SOLID / Single Responsibility Principle (SRP)

1 public class Reception2 {3 private string _receptionistName = "Peter";4 public string GetGreeting()5 {6 return string.Format("You are Welcome, my name is {0}", _receptionistName);7 }8 9 public string GetRoomKeys()

10 {11 return "room 101";12 }13 14 public string PrintInvoce(string roomKeys)15 {16 return string.Format("Your invoice for {0}", roomKeys);17 }18 }

Page 36: Introducción a Unit Testing y TDD

SOLID / Single Responsibility Principle (SRP)

1 public class Reception2 {3 private string _receptionistName = "Peter";4 public string GetGreeting()5 {6 return string.Format("You are Welcome, my name is {0}", _receptionistName);7 }8 9 public string GetRoomKeys()

10 {11 return "room 101";12 }13 14 public string PrintInvoce(string roomKeys)15 {16 return string.Format("Your invoice for {0}", roomKeys);17 }18 }

Page 37: Introducción a Unit Testing y TDD

SOLID - SRP

Page 38: Introducción a Unit Testing y TDD

SOLID / Single Responsibility Principle (SRP)1 public class Reception2 {3 private string _receptionistName = "Peter";4 private RoomService _roomService = new RoomService();5 private InvoicePrinter _invoicePrinter = new InvoicePrinter();6 public string GetGreeting()7 {8 return string.Format("You are Welcome, my name is {0}", _receptionistName);9 }10 11 public string GetRoomKeys()12 {13 return _roomService.GetFreeRoom();14 }15 16 public string PrintInvoce(string roomKeys)17 {18 return _invoicePrinter.Print(roomKeys);19 }20 }

Page 39: Introducción a Unit Testing y TDD

SOLID / Open-Closed Principle (OCP)

“Una clase debería estar abierta a extensión pero cerrada a modificación”

Deberíamos poder cambiar o extender el comportamiento de una clase, sin

modificarla en absoluto.

Beneficios

Podemos añadir nueva funcionalidad sin dañar el código existente

Page 40: Introducción a Unit Testing y TDD

SOLID / Open-Closed Principle (OCP)

1 public class InvoicePrinter2 {3 public string Print(string roomKeys)4 {5 return string.Format("Your invoice for room {0}", roomKeys);6 }7 }

1 public class Reception2 {3 private string _receptionistName = "Peter";4 private RoomService _roomService = new RoomService();5 private InvoicePrinter _invoicePrinter = new InvoicePrinter();6 7 public string GetGreeting()8 {9 return string.Format("You are Welcome, my name is {0}", _receptionistName);10 }11 12 public string GetRoomKeys()13 {14 return _roomService.GetFreeRoom();15 }16 17 public string PrintInvoce(string roomKeys)18 {19 return _invoicePrinter.Print(roomKeys);20 }21 }

Page 41: Introducción a Unit Testing y TDD

SOLID - OCP

Page 42: Introducción a Unit Testing y TDD

SOLID / Open-Closed Principle (OCP)

1 public abstract class InvoicePrinter2 {3 public abstract string Print(string roomKeys);4 }

1 public class Reception2 {3 private string _receptionistName = "Peter";4 private RoomService _roomService = new RoomService();5 private InvoicePrinter _invoicePrinter = new InvoiceTextPrinter();6 7 public string GetGreeting()8 {9 return string.Format("You are Welcome, my name is {0}", _receptionistName);10 }11 12 public string GetRoomKeys()13 {14 return _roomService.GetFreeRoom();15 }16 17 public string PrintInvoce(string roomKeys)18 {19 return _invoicePrinter.Print(roomKeys);20 }21 }

Page 43: Introducción a Unit Testing y TDD

SOLID / Open-Closed Principle (OCP)

1 public abstract class InvoicePrinter2 {3 public abstract string Print(string roomKeys);4 }

1 public class Reception2 {3 private string _receptionistName = "Peter";4 private RoomService _roomService = new RoomService();5 private InvoicePrinter _invoicePrinter = new InvoiceHtmlPrinter();6 7 public string GetGreeting()8 {9 return string.Format("You are Welcome, my name is {0}", _receptionistName);10 }11 12 public string GetRoomKeys()13 {14 return _roomService.GetFreeRoom();15 }16 17 public string PrintInvoce(string roomKeys)18 {19 return _invoicePrinter.Print(roomKeys);20 }21 }

Page 44: Introducción a Unit Testing y TDD

SOLID / Liskov Substitution Principle (LSP)

“Sustituir un objeto por una subclase de ese objeto no debería cambiar el

comportamiento o el buen funcionamiento del programa (o de su clase base)”

Si una función recibe un objeto como parámetro, de tipo X y en su lugar le

pasamos otro de tipo Y, que hereda de X, dicha función debe proceder

correctamente.

Una función que no cumple LSP, habitualmente rompe OCP, pues necesita

saber demasiado de la clase ancestro para poder modificar su funcionamiento.

Page 45: Introducción a Unit Testing y TDD

SOLID / Liskov Substitution Principle (LSP)

1 static void Main(string[] args)2 {3 // Management4 InvoiceCalculator invoiceCalculator = new InvoiceCalculator();5 invoiceCalculator.Base = 1000m;6 invoiceCalculator.IVA = 0.21m;7 8 var printerForReception = new InvoiceTextPrinter();9 var reception = new Reception();10 11 // Customer12 Console.WriteLine(reception.GetGreeting());13 var roomKeys = reception.GetRoomKeys();14 15 Console.WriteLine(printerForReception.Print(roomKeys, invoiceCalculator));16 17 Console.ReadKey();18 }

Page 46: Introducción a Unit Testing y TDD

SOLID / Liskov Substitution Principle (LSP)

1 static void Main(string[] args)2 {3 // Management4 InvoiceCalculator invoiceCalculator = new InvoiceForeignCalculator();5 invoiceCalculator.Base = 1000m;6 invoiceCalculator.IVA = 0.21m;7 8 var printerForReception = new InvoiceTextPrinter();9 var reception = new Reception();10 11 // Customer12 Console.WriteLine(reception.GetGreeting());13 var roomKeys = reception.GetRoomKeys();14 15 Console.WriteLine(printerForReception.Print(roomKeys, invoiceCalculator));16 17 Console.ReadKey();18 }

Page 47: Introducción a Unit Testing y TDD

SOLID / Liskov Substitution Principle (LSP)

Cuando un grupo de clases incumple LSP, es muy habitual que el problema

subyacente resida en el diseño y que la única solución sea un rediseño

completo de la jerarquía de clases.

Page 48: Introducción a Unit Testing y TDD

SOLID - LSP

Page 49: Introducción a Unit Testing y TDD

SOLID / Liskov Substitution Principle (LSP)1 class Program2 {3 static void Main(string[] args)4 {5 // Management6 InvoiceCalculator invoiceCalculator = new InvoiceLocalCalculator(1000m, 0.21m);7 InvoiceCalculator invoiceCalculator = new InvoiceForeignCalculator(1000m);8 9 var printerForReception = new InvoiceTextPrinter();10 var reception = new Reception();11 12 // Customer13 Console.WriteLine(reception.GetGreeting());14 var roomKeys = reception.GetRoomKeys();15 16 Console.WriteLine(printerForReception.Print(roomKeys, invoiceCalculator));17 18 Console.ReadKey();19 }20 }

Page 50: Introducción a Unit Testing y TDD

SOLID / Interface Segregation Principle (ISP)

“Una clase cliente no debe ser forzada a depender de un interface que no

necesita”

Si una clase cliente usa un interface con más métodos de los que ella misma

necesita es muy probable que ese interface sirva a varias clases cliente con

responsabilidades diferentes.

ISP y SRP están muy ligados. Un buen SRP habitualmente implica un buen ISP.

Page 51: Introducción a Unit Testing y TDD

SOLID / Interface Segregation Principle (ISP)1 public class Receptionist : IStaff2 {3 private string _name;4 public Receptionist(string name)5 {6 this._name = name;7 }8 9 public string GetName()10 {11 return _name;12 }13 public string GetDrink(string drinkName)14 {15 throw new NotImplementedException();16 }17 public bool CheckReservation(string clientName)18 {19 return true;20 }21 }

1 public class Reception2 {3 ...6 11 public string GetDrink()12 {13 return _receptionist.GetDrink("gin tonic");14 }

Page 52: Introducción a Unit Testing y TDD

SOLID - ISP

Page 53: Introducción a Unit Testing y TDD

SOLID / Interface Segregation Principle (ISP)

Page 54: Introducción a Unit Testing y TDD

SOLID / Dependency Inversion Principle (DIP)

“Módulos de alto nivel no deberían depender de módulos de bajo nivel.

Ambos deberían depender de abstracciones”

“Abstracciones no deberían depender de los detalles. Los detalles deberían

depender de las abstracciones”

Una clase padre, accederá a sus dependencias a través de interfaces o clases

abstractas.

Diseñaremos nuestro sistema de arriba hacia abajo, no al revés.

Page 55: Introducción a Unit Testing y TDD

SOLID / Dependency Inversion Principle (DIP)

Page 56: Introducción a Unit Testing y TDD

SOLID - DIP

Page 57: Introducción a Unit Testing y TDD

SOLID / Dependency Inversion Principle (DIP)

Cumplimos el primer punto del Principio de

Inversión de Dependencia

Page 58: Introducción a Unit Testing y TDD

SOLID / Dependency Inversion Principle (DIP)

Cumplimos los dos puntos

del Principio

Page 59: Introducción a Unit Testing y TDD

Test Driven

DevelopmentIntroducción

Page 60: Introducción a Unit Testing y TDD

TDD / Introducción

TODO CODIGO

FALLA

HASTA QUE SE DEMUESTRE

LO CONTRARIO

Page 61: Introducción a Unit Testing y TDD

TDD / Introducción

• Cuantas veces:• Has empezado a desarrollar con especificaciones confusas

• Has descubierto, demasiado tarde, fallos en la especificación

• Has tenido un código totalmente fiable justo en el momento de terminarlo

• Has desarrollado más código del necesario

• Que nivel de estrés

• Te produce tocar un código desconocido

• Y un código de altas implicaciones/afecciones.

Page 62: Introducción a Unit Testing y TDD

TDD / Introducción

¿Qué ocurre cuando el nivel de estrés se eleva?

Circulo de retroalimentación:

“Kent Beck: Test Driven Development by Example”

Page 63: Introducción a Unit Testing y TDD

TDD¿Qué es? ¿Cómo se hace? ¿Cómo me beneficia?

Page 64: Introducción a Unit Testing y TDD

TDD / ¿ Qué es ?

• Escribir tests antes de escribir el código

• Testear antes como una actividad de diseño de software• No testeamos para validar código, testeamos para diseñarlo

• Testear antes para evidenciar/clarificar qué debe hacer el código

Page 65: Introducción a Unit Testing y TDD

TDD / Pasos

¿Qué queremos que haga el código que vamos a desarrollar?

¿Qué hechos demostrarán que nuestro código funciona?

Page 66: Introducción a Unit Testing y TDD

TDD / Pasos

¿Escribimos el test?

Pensamos en el comportamiento del código y su interface público

El test fallará porque la función todavía no existe

Page 67: Introducción a Unit Testing y TDD

TDD / Pasos

Escribimos el código de producción

SOLO el código necesario para pasar el test

Page 68: Introducción a Unit Testing y TDD

TDD / Pasos

Refactorizamos la funcionalidad desarrollada

Durante la refactorización NO DEBEMOS cambiar la semántica (sentido)

Page 69: Introducción a Unit Testing y TDD

TDD / Beneficios

• Código bajo completa especificación

• Ausencia de YAGNI (You aren’t gonna need it)

• KISS (Keep it simple, stupid). Código más simple y funcional. Se persigue

el objetivo

• Facilidad para aplicar principios SOLID

• Disminución del estrés, aumento de la confianza.

Page 70: Introducción a Unit Testing y TDD

TDDPatrones de Test Driven Development

Page 71: Introducción a Unit Testing y TDD

TDD / Patrones para un buen TDD / Tests List

• Realizar una lista de tests

• por funcionalidad/tarea/historia que debemos realizar

• con lo que debe ser y, también, lo que no debe ser

• si surgen nuevos tests o dudas, apuntarlos en la lista

Page 72: Introducción a Unit Testing y TDD

TDD / Patrones para un buen TDD / Tests First

• escribir los tests antes del código

• romper el circulo de retroalimentación

• si se empiezan a escribir los tests después, se dejará de hacer tests-first

completamente.

• ayuda a definir:

• cual es la respuesta correcta

• cómo voy a chequearla

• donde pertenece esta funcionalidad

• como debería llamarla

Page 73: Introducción a Unit Testing y TDD

TDD / Patrones para un buen TDD / Assert First

• Escribe tu Assert lo primero de todo

Queremos comprobar que el cuentakilómetros de un coche mide correctamente.

Para obtener la medición final, el vehículo debe estar apagado.

Recorremos una distancia concreta y obtenemos esa distancia.

01 [TestClass]02 public void CarTravelDistanceTest()03 {04 Assert.IsTrue(car.IsPowerOff());05 Assert.Equals(300, distance.FromStart());06 }

Page 74: Introducción a Unit Testing y TDD

TDD / Patrones para un buen TDD / Assert First

• Escribe tu Assert lo primero de todo

• crece según sea necesario para alcanzar el objetivo

¿De donde sale la distancia?Del cuenta kilómetros del propio vehículo, desde luego

01 [TestClass]02 public void CarTravelDistanceTest()03 {04 Distance distance = car.DistanceFromStart();05 Assert.IsTrue(car.IsPowerOff());06 Assert.Equals(300, distance.Kilometers());07 }

Page 75: Introducción a Unit Testing y TDD

TDD / Patrones para un buen TDD / Assert First

• Escribe tu Assert lo primero de todo

• crece según sea necesario para alcanzar el objetivo

¿Y el vehículo?Lo creamos y debemos conducirlo a donde queremos ir01 [TestClass]

02 public void CarTravelDistanceTest()03 {04 Car car = new Car("Opel", "blue");05 car.DriveTo("Bilbao");06 Distance distance = car.DistanceFromStart();07 Assert.IsTrue(car.IsPowerOff());08 Assert.Equals(300, distance.Kilometers());09 }

Page 76: Introducción a Unit Testing y TDD

TDD / Patrones para un buen TDD / Test Data

• Usa información que sea fácil de leer

• Recuerda que escribes tests para una audiencia

• Minimiza los datos que usas• Si una lista de 3 elementos es suficiente, no pongas 10

• Como alternativa al “Test Data” está el “Realistic Data”, donde usamos

datos del mundo real.• Sistemas de tiempo real

• Buscas equiparar salidas del sistema actual con el sistema anterior

• Estás refactorizando una simulación y se espera la misma respuesta.

• Sobre todo si la precisión de coma flotante puede ser un problema.

Page 77: Introducción a Unit Testing y TDD

TDD / Patrones para un buen TDD / Evident Data

• Usa datos evidentes

• Estás escribiendo tests para otros, no para el ordenador

• Deja tantas pistas como sea posible• Es posible que alguien esté leyendo tus tests el año que viene

• Y es posible que seas tu mismo

• Es preferible explicitar los cálculos:

Esto:Assert.Equals(300, distance.Kilometers());

Es peor que esto:Assert.Equals(1300 - 1000, distance.Kilometers());

Page 78: Introducción a Unit Testing y TDD

TDDPatrones de barra roja (Red Bar Patterns)

Page 79: Introducción a Unit Testing y TDD

TDD / Patrones de barra roja / Starter Test

• ¿Con cual de los tests de tu lista deberías empezar?• empieza por testear una variante de una operación que no haga nada

• a menudo un Starter Test es un test de alto nivel, como un test de aplicación

var allAccounts = new IDictionary<Company, IList<Accounts>>();

Assert.AreEqual( 0, allCounts.SumAllAccounts());

Page 80: Introducción a Unit Testing y TDD

TDD / Patrones de barra roja / One Step Test

• ¿Cual de los tests de tu lista es el siguiente a implementar?• uno que te enseñe algo del sistema

• sepas que puedes implementar sin problemas

• represente un paso hacía el objetivo global

No se sigue un desarrollo top-down o bottom-up.

Más bien se sigue un proceso de lo conocido a lo desconocido.

Aprendiendo por el camino.

Page 81: Introducción a Unit Testing y TDD

TDD / Patrones de barra roja / Explanation Test

• ¿Cómo difundir el uso de tests automatizados?• pide y da explicaciones en términos de tests

“Veamos si lo he entendido. Por ejemplo si tenemos Foo con este valor y Bar con este otro, la

respuesta debería ser X”

Page 82: Introducción a Unit Testing y TDD

TDD / Patrones de barra roja / Regression Test

• ¿Qué es lo primero que haces cuando un bug/defecto es reportado?• escribe el menor test posible que falle por ese motivo

• una vez ejecutado el test y comprobado su fallo, reparamos el bug

Page 83: Introducción a Unit Testing y TDD

TDDPatrones de barra verde (Green Bar Patterns)

Page 84: Introducción a Unit Testing y TDD

TDD / Patrones de barra verde / Fake it (‘Til you make it)

• ¿Cuál es tu primera implementación para arreglar un test roto?• devuelve justo lo necesario para arreglarlo y nada más

• seguramente una constante es suficiente (gradualmente se convertirá en una

expresión u operación que usará variables)

Fake it causa mucha fricción en las personas. Sobre todo en programadores

experimentados.

¿Por qué hacer algo que sabes que tendrás que quitar?

Porque es vital obtener un verde rápidamente y es mejor tener algo

funcionando que no tener nada o algo que falla.

Page 85: Introducción a Unit Testing y TDD

TDD / Patrones de barra verde / Triangulate

• ¿Cuánto de conservador debo ser con la abstracción de los tests?• abstrae solo cuando tengas dos o más ejemplos

Cuidado con entrar en lo que podemos denominar como el bucle de

triangulación.

[TestMeethod]public void TestSum(){

Assert.Equals(4, Sum(3, 1));}

private int Sum(int x, int y){

return 4}

[TestMeethod]public void TestSum(){

Assert.Equals(4, Sum(3, 1));Assert.Equals(5, Sum(3, 2));

}

private int Sum(int x, int y){

return x + y;}

[TestMeethod]public void TestSum(){

Assert.Equals(4, Sum(3, 1));Assert.Equals(5, Sum(3, 2));

}

private int Sum(int x, int y){

return x + y;}

Page 86: Introducción a Unit Testing y TDD

TDD / Patrones de barra verde / Obvious Implementation

• ¿Cómo implementas operaciones que, para ti, son simples?• simplemente impleméntalas

Fake it y Triangulation son patrones de muy pequeños pasos.

Algunas veces ya sabes cómo se implementa una operación. Adelante!!!

Pero permanece atento a cuan a menudo recibes sorpresas en forma de

barras rojas usando Obvious y, si son demasiadas, vuelve al origen.

Ten en cuenta que Obvious es una “segunda marcha”. Vuelve a la primera

en cuanto “muerdas más de lo que puedes tragar”.

Page 87: Introducción a Unit Testing y TDD

TDD / Patrones de barra verde / One to Many

• ¿Cómo implementas una operación que trabaja con colecciones?• prepara el test y ponlo verde, sin la colección

01 [TestClass]02 public void SumTest()03 {04 Assert.AreEqual(5, Calculations.Sum(5));05 }

01 public static int Sum(int number)02 {03 return number;04 }

Page 88: Introducción a Unit Testing y TDD

TDD / Patrones de barra verde / One to Many

• ¿Cómo implementas una operación que trabaja con colecciones?• prepara el test y ponlo verde, sin la colección

01 [TestClass]02 public void SumTest()03 {04 Assert.AreEqual(5, Calculations.Sum(5, new int[] { 5 }));05 }

01 public static int Sum(int number, int[] values)02 {03 return number;04 }

Page 89: Introducción a Unit Testing y TDD

TDD / Patrones de barra verde / One to Many

• ¿Cómo implementas una operación que trabaja con colecciones?• prepara el test y ponlo verde, sin la colección

01 [TestClass]02 public void SumTest()03 {04 Assert.AreEqual(5, Calculations.Sum(5, new int[] { 5 }));05 }

01 public static int Sum(int number, int[] values)02 {03 int result = 0;04 for (int i = 0; i < values.Length; i++)05 {06 result += values[i];07 }08 return result;09 }

Page 90: Introducción a Unit Testing y TDD

TDD / Patrones de barra verde / One to Many

• ¿Cómo implementas una operación que trabaja con colecciones?• prepara el test y ponlo verde, sin la colección

01 public static int Sum(int[] values)02 {03 int result = 0;04 for (int i = 0; i < values.Length; i++)05 {06 result += values[i];07 }08 return result;09 }

06 [TestClass]07 public void SumTest()08 {09 Assert.AreEqual(5, Calculations.Sum(new int[] { 3, 2 }));10 }

Page 91: Introducción a Unit Testing y TDD

SEATTLE

www.plainconcepts.com

MADRID

General Rodrigo 6Cuerpo alto, 1ª planta28003(+34) 915 346 836

BILBAO

Nervión 36ª planta48001(+34) 946 008 168

1511 Third AvenueSuite 512WA 98101(+1) 206 708 1285

www.plainconcepts.com

SEVILLA

Avd. Innovación 3Hércules, 3º planta, modulo 441020(+34) 955 222 906