El desarrollo basado en pruebas (TDD) es un enfoque esencial para asegurar la calidad del software desde las primeras etapas del desarrollo. En esta clase, exploraremos cómo implementar pruebas utilizando TDD junto con Moq en C#. Este proceso no solo nos ayuda a garantizar que nuestros productos están regresando el contenido esperado, sino que además verifica que cumple con las reglas de negocio necesarias.
¿Cómo usar Moq para correr pruebas?
En TDD, Moq se utiliza para crear objetos simulados o "substitutes" que nos permiten validar comportamientos sin tener que depender de la implementación real. La clase del test utiliza sustitutos de la librería Moq para simular el comportamiento de las dependencias.
var productMock =newMock<IProduct>();productMock.Setup(p => p.GetContent()).Returns("Contenido esperado");
Esta técnica es práctica para tests aislados donde la implementación del objeto no está disponible o está incompleta.
¿Cómo darle funcionalidad al producto?
Para que un producto pase las pruebas, debe implementar correctamente su interfaz, como IProduct. Esto implica definir correctamente las propiedades públicas, como el nombre, fabricante, y SKU, y asegurarse de que el método GetContent esté bien implementado.
Por ejemplo, si tenemos una clase Product:
publicclassProduct:IProduct{publicstring Name {get;set;}publicstring Manufacturer {get;set;}publicstring SKU {get;set;}publicstringGetContent(){return$"{Name} by {Manufacturer}";}}
Esto establece claramente cómo debería ser la estructura interna de la clase para asegurar la ejecución correcta de la prueba.
¿Cómo gestionar nombres conflictivos en C#?
Cuando nos encontramos con problemas de nombres conflictivos, como tener el mismo nombre para una clase y un namespace, podemos ajustar las declaraciones de los namespaces y nombres de clases para evitar los conflictos:
Una buena prueba debe considerar las reglas de negocio y el contexto de uso específico de la aplicación. Con TDD, primero escribimos el test que sabemos que fallará, y luego escribimos la mínima cantidad de código necesario para pasarlo.
Pruebas Personalizadas: Si tu producto es una cámara que debe incluir features, puedes escribir una prueba para verificar que estas características están correctamente incluidas:
var cameraMock =newMock<ICamera>();cameraMock.Setup(c => c.GetContent()).Returns("Características específicas");
Implementación de Métodos de Interfaces: Asegúrate de que cada método cumpla con las especificaciones y realiza validaciones con contenido predefinido.
¿Cuál es la importancia de organizar correctamente los tests?
Organizar tus tests en categorías claras facilita el manejo y depuración de problemas. Por ejemplo, puedes separar los tests de productos de los de reviews en archivos separados (ProductTest.cs, ReviewTest.cs). Esto ayuda a mantener el código limpio y hace más fácil identificar errores:
Tests de Producto: Asegúrate de que las propiedades del producto y las implementaciones de métodos como GetContent cumplen con las expectativas.
Tests de Review: Verifica que las implementaciones de las reviews coinciden correctamente con los productos y sus características.
¿Cuál es el siguiente paso para mejorar tu sistema?
Designa un Structure Consistente: Asegúrate de que el formato de los datos sea siempre el mismo, por ejemplo, usando JSON o diccionarios.
Desarrolla más Tests: Cubre todas las reglas de negocio posibles con tests adicionales.
Pide Feedback: Consulta a un colega o amigo para revisar tus tests y asegúrate de que cubran todas las áreas requeridas del sistema.
Implementar un enfoque TDD correctamente convertirá tu sistema en uno más seguro y fiable, siempre y cuando los tests validen efectivamente las funcionalidades y las reglas del negocio. Sigue explorando y profundizando en este método para mejorar tu habilidad y confianza como desarrollador.
Con PHP podemos usar la función str_contains para verificar que un string contenga cierto string, SOLO FUNCIONA EN PHP 8, para versiones anteriores se usa str_pos.
.
No entendí muy bien el reto y en los archivos de la clase no está la solución, pero lo que yo hice fue que la clase Review implementa un arreglo asociativo (mapa) como contenido, y ese arreglo contiene el título, el autor y otro arreglo de productos.
.
Mi test lo que hace es verificar que el "product" que haya sido pasado a través de setProduct se encuentre dentro de mi contenido (getContent)
.
Aquí el enlace del commit con la solución de este reto en PHP:
.
https://github.com/RetaxMaster/arquitectura-backend/tree/57ab9cefd69e195b9485fc99292acaee6972f24f
.
Y también dejo el archivo de mi test (el resto del código está en mi repositorio):
publicfunctiontest_review_content_match_with_product(){// setup $cameraProduct =newCamera(); $cameraProduct->setName("Canon 60D"); $cameraProduct->setType("FullFrame"); $cameraProduct->setCropFactor(1); $review =newReview(); $review->setTitle("Titulo del review"); $review->setAuthor("Un autor"); $review->setProduct($cameraProduct);// exec $content = $review->getContent();// assert $this->assertTrue(in_array($cameraProduct, $content["products"]),"Should match content with the product.");}
Para los que utilizaron C#. Soy yo o las interfaces no sirvieron de nada pues no se utilizaron ni en las clases ni el los tests. ¿Alguien tiene algún comentario al respecto?
Por el momento no se usan las interfaces
Las interfaces se pueden usar para las pruebas unitarias, en donde tengas que modificar el comportamiento y tienes que tener tu propia implementación de IProduct para pruebas
No entendí para qué se crea la interfáz si desde un principio se puede generar como clase.
Una interfaz es una abstracción de lo que sería una clase, esta permite definir con anterioridad que atributos y métodos debe tener la clase, sin la necesidad directa de crear todo el código. Se podría entender como un borrador de la clase. Para la metodología TDD es necesario hacer una prueba que falle con un mock y luego implementando la clase, repetir la prueba
y debe pasar. Yo aprendí de interfaces cuando estudie Java, si te sirve te dejo este enlace: Interface con Java
Exacto, y si te das cuenta nunca usa la interfaz.
Me perdi bastante en esa clase creo que no esta bien colocada en la escuela de desarrollo, ya que orienta mucho a los metodos del lenguaje en si , haciendo dificil seguirlo en otro lenguaje sin tenerlo bien dominado
Recuerda que como dice el propósito es crear una arquitectura de backend, siendo esta agnóstica al lenguaje.
Tener tests para cada una de las reglas de negocio, asi se asegura que se cumple con todos los requerimientos y ademas en caso de aplicar cambios garantizamos que siga funcionando correctamente
en realidad se usan las interfaces solo que cuando el las uso no tenia una clase que implemente esa interfaz. No es buena practica usar la clase directamente, se suele usar la interfaz en las pruebas pero cuando ya esta implementada en la clase a que hace referencia
La clase se centra en la implementación de objetos utilizando Test Driven Development (TDD). Se inicia creando una estructura de prueba para un objeto, luego se implementa la funcionalidad necesaria para que las pruebas pasen. Se utiliza una interfaz y un sustituto de librería para simular comportamientos. Se enfatiza la importancia de tener pruebas que cubran todas las reglas del negocio. El enfoque incluye crear implementaciones específicas, como una cámara, y se sugieren tareas adicionales para implementar entidades y pruebas de forma organizada.
La implementación jajajajaja
solución completa........
Se le dañó la primera prueba al cambiar el método de GetContent en Product, por NotImplementedException para sobreescribirlo en la clase Product debe dejarlo como virtual y en la clase Camera ponerle el override
Muchas gracia Jorge solo compre la membresía de Platzi por este cuso saludos!