Obtenga algo de práctica con el desarrollo basado en pruebas en C #

Así que hablemos de TDD, ¿qué es?

TDD son las siglas de Test Driven Development , y es un proceso de diseño en el desarrollo de software. Se basa en la repetición de un ciclo de desarrollo muy corto y los requisitos se convierten en casos de prueba muy específicos.

Hay un par de pasos en el proceso TDD:

  1. Escribe una prueba unitaria que falle.
  2. Escriba suficiente código para aprobar la prueba; en este paso, no nos importa un buen código.
  3. Refactorice su código del paso anterior.

¿Cuáles son los beneficios de este enfoque?

En primer lugar, comprende mejor el código real antes de escribirlo. Este es uno de los mayores beneficios de TDD. Cuando escribe los casos de prueba primero, piensa más claramente en los requisitos del sistema y de manera más crítica en los casos de esquina .

Además, cuando se habla de dependencias , es importante mencionar que trabajar con TDD le permite concentrarse en la lógica de sus clases. De esta forma, mantienes todas las dependencias fuera de tus clases. También es importante mencionar que su código se ejecutará de manera más segura, ya que la lógica no tendrá que manejar dependencias diferentes como conexiones de bases de datos, sistemas de archivos, etc.

También es una forma más segura de refactorizar el código. Al escribir TDD, hay pruebas para cierta lógica. Cuando refactoriza el código, puede romper algo, pero con este enfoque sabe que las pruebas lo respaldarán.

Cuando usa TDD, también tiene una forma más rápida de comprender lo que hace el código. Cuando comienzas a trabajar en un fragmento de código con el que no estás familiarizado, puedes leer los casos de prueba de ese fragmento de código y comprender su propósito. Esas pruebas también son la documentación de su código.

Y finalmente, puede concentrarse en construir los componentes más pequeños de la mejor manera y evitar el dolor de cabeza del panorama general. Entonces, ¿cómo ayuda esto? Escribirá una prueba fallida y se concentrará únicamente en eso para que pase. Te obliga a pensar en partes más pequeñas de funcionalidad a la vez en lugar de en la aplicación en su conjunto. Luego, puede desarrollar gradualmente una prueba aprobada, en lugar de tratar de abordar el panorama general desde el principio, lo que probablemente resultará en más errores.

Antes de empezar a escribir TDD ...

Para ser honesto, hay más artículos en los que puede leer aún más profundamente sobre TDD. Por lo tanto, evité escribir aquí toda la teoría de TDD porque tomaría mucho tiempo leerlo todo.

Por lo tanto, acabo de explicar la idea general y las ventajas del proceso de diseño TDD.

Es hora de escribir algunas pruebas, así que hagámoslo.

Descripción y requisitos

Usaremos C # para escribir una implementación de Stack. ¿Por qué C #? Bueno, porque me encanta C #, ¿por qué no? ?

Entonces, nuestros requisitos son bastante simples: queremos implementar una clase Stack, por lo que los requisitos son:

  1. Limite el tamaño de la pila.
  2. Agregar elemento. (empujar)
  3. Quitar elemento. (popular)
  4. Compruebe cuál fue el último elemento. (ojeada)
  5. Obtenga el tamaño actual de la pila.
  6. Tener una clase que pueda aceptar cualquier tipo de datos.
  7. Cuando el cliente excede el tamaño de la pila, necesitamos lanzar una excepción apropiada.

Una vez que sepamos cuáles son los requisitos del sistema, podemos comenzar a definir cómo resolveremos esto. Lo implementaremos usando una matriz.

Implementación de pila en TDD - Infraestructura de edificios

Yo uso Visual Studio 2017. En él, abriré un nuevo proyecto:

Archivo -> Nuevo -> P royecto, seleccione la aplicación de consola (.NET Framework).

Elija un nombre de proyecto, como "Pila".

Ahora abriremos otro proyecto solo para las pruebas y lo llamaremos “StackTests”.

Abra el explorador de soluciones. Tenemos un proyecto allá llamado "Stack". Ahora haga clic derecho en Solución y elija Agregar -> Nuevo proyecto y elija Biblioteca de clases (.NET Framework).

Instalemos nuestras pruebas unitarias: haga clic con el botón derecho en el proyecto StackTests , elija Administrar paquetes NuGet , navegue hasta "Examinar" e instale los siguientes paquetes:

  • NUnit
  • NUnit3TestAdapter

Agregue una nueva clase al proyecto StackTests y llámelo StackTest. Ahora la solución debería verse así:

El package.config debería verse así:

Implementación de pila en TDD - Código de escritura

Comenzaremos a escribir unidades de prueba en el proyecto StackTests en la clase StackTest.

Antes de que podamos comenzar a escribir el código, necesitamos aprender 3 cosas importantes: TestFixture, Test y Assert.

TestFixture es el atributo que marca una clase que contiene pruebas y, opcionalmente, métodos de instalación o desmontaje.

El atributo Test es una forma de marcar un método dentro de una clase TestFixture como prueba.

La clase Assert es una colección de clases auxiliares para probar varias condiciones dentro de las pruebas unitarias. Si no se cumple la condición que se está probando, se lanza una excepción.

Importe “NUnit.Framework” y coloque el atributo [TestFixture] encima de la definición de su clase.

Prueba de creación

Bien, es hora de escribir nuestra primera función. Escribiremos una prueba de creación, que creará un nuevo objeto de nuestro Stack, y comprobará que el tamaño del Stack es 0 al principio.

Ahora que hemos escrito nuestra primera prueba, ejecutémosla.

En la barra de herramientas, haga clic en Prueba -> Ejecutar -> Todas las pruebas.

Si su Explorador de pruebas no está abierto, haga clic en Prueba -> Windows -> Explorador de pruebas , y esto expandirá el explorador de pruebas.

Como puede ver, ni siquiera tenemos nuestra clase Stack definida, por lo que estamos obteniendo un error de compilación. Ahora escribamos suficiente código para que la prueba pase.

Hagamos que nuestra primera prueba funcione:

  • Cree una nueva clase en el proyecto Stack y llame a esta clase "Stack". Haga de esta clase una clase de tipo genérico (tipo T).
  • Definimos esta clase (Stack) para ser implementado como una matriz, por lo tanto, vamos a definir el campo como un miembro de matriz de tipo T .
  • Requerimos pasar la longitud máxima de la pila en el constructor, por lo tanto, crearemos un constructor que tome un argumento de tamaño.
  • Y dado que requerimos que recibamos el tamaño actual de la pila en cualquier punto, definiremos una propiedad de "Tamaño". Por supuesto, ninguno podrá cambiar el tamaño, por lo tanto, será un conjunto privado .

Ahora ejecutemos las pruebas nuevamente (verifique arriba cómo ejecutar las pruebas) y veamos los resultados.

¡Y ahí vamos, hemos hecho nuestra primera iteración con el diseño TTD! Ahora deberíamos refactorizar nuestro código, pero en este punto, realmente no tenemos nada que refactorizar, así que seguiremos adelante.

Prueba Push & Pop

Ahora queremos probar la funcionalidad push y pop, así que creemos el caso de prueba.

  • Push tomará un argumento y lo agregará a la parte superior de la pila.
  • Pop eliminará el elemento de la pila y lo devolverá.

Agregaremos 3 elementos a la pila, luego sacaremos el último elemento. En este punto comprobaremos que el último elemento es el exacto que esperamos obtener y que el tamaño de la pila ha disminuido.

Como puede ver, las funciones push y pop ni siquiera existen, por lo que cuando ejecutamos pruebas obtenemos una falla en nuestroresultados de la prueba. Vayamos a la clase Stack e impleméntelos.

Ejecutemos nuestras pruebas de nuevo y boom, ¡todo funciona perfectamente! ¿Todas las pruebas pasaron con éxito?

Error al exceder el tamaño permitido

Queremos lanzar excepciones personalizadas cuando:

  1. Empuje nuevo elemento cuando la pila esté llena.
  2. Pop elemento cuando no hay elementos en la pila.

Entonces, como ya sabes ... ¿qué deberíamos estar haciendo ahora?

¡Correcto! Definimos casos de prueba y luego hacemos que el código funcione.

Como puede ver, necesitamos crear dos nuevas excepciones personalizadas.

  • ExpenditureProhibitedException : esta excepción se producirá cuando la pila esté vacía y el cliente intente sacar un nuevo elemento.
  • ExceededSizeException : esta excepción se producirá cuando la pila esté llena y el cliente intente agregar un nuevo elemento a la pila.

Vaya a Stack Project y cree una nueva clase llamada CustomExceptions. En esta clase definiremos nuestras nuevas excepciones y heredarán de la clase Exception.

Modifique nuestra funcionalidad push and pop actual para lanzar una excepción cuando sea necesario.

Así que ahora, como parte del ciclo de vida de TDD, estamos ejecutando las pruebas ... y ¡Hurra! Todas las pruebas han pasado satisfactoriamente.

Mira el último elemento

Estamos a punto de terminar con las últimas pruebas. Queremos echar un vistazo al último elemento de la pila. Si la pila está vacía, lanzaremos una excepción ExpenditureProhibitedException, de lo contrario, devolveremos el último elemento.

Creemos nuestros casos de prueba.

  1. Intente echar un vistazo al elemento cuando la pila esté vacía. En esta prueba lanzaremos una excepción personalizada.
  2. Inserte algunos elementos en la pila, luego eche un vistazo a un elemento, asegúrese de que este sea el elemento correcto y verifique que el tamaño de la matriz no haya cambiado.

Cuando ejecutamos las pruebas, fallarán: el método de inspección ni siquiera existe y no hay ninguna funcionalidad.

Vamos a crear la función de la ojeada a la clase Pila .

Ahora, cuando volvemos a ejecutar las pruebas, podemos ver que todas pasan correctamente.

En conclusión

Como puede ver, la idea no es complicada y hay muchas herramientas que ayudan a implementar los principios TDD.

Puede ver el código completo en Pastebin.

Clase de pila: esta clase contiene todas las implementaciones de pila.

Clase StackTests: contiene todos los casos de prueba.

Clases CustomExceptions: contiene las excepciones que el sistema requería para el diseño TDD.

Todos los comentarios y sugerencias son bienvenidos; si es necesario, arreglaré el artículo.

No dude en contactarme directamente en LinkedIn - Haga clic aquí.