Pruebas unitarias en Flutter: desde los aspectos esenciales del flujo de trabajo hasta escenarios complejos

By raman 17 Min Read

La cantidad de interés mostrado en Flutter ha alcanzado un máximo histórico, lo que es tanto bienvenido como necesario desde hace tiempo. Android, iOS, macOS, web, Windows y Linux son todos compatibles con el kit de desarrollo de software (SDK) de código abierto de Google. Todos estos están soportados por una única base de código para Flutter. Y las pruebas unitarias son esenciales para proporcionar un programa Flutter que sea confiable y consistente. Esta prueba protege la aplicación de errores, fallas y otro tipo de defectos al mejorar de manera proactiva la calidad del código antes de que se ensamble.

¿Qué es la prueba automatizada?

El proceso de revisar y verificar que una aplicación de software hace lo que está destinada a hacer se conoce como prueba automatizada de software. Elimina errores y reduce el coste general de desarrollo.

Para entender, hay algo que necesita ser comprendido. El único propósito de las pruebas automatizadas es evitar que el software tenga errores ya predeterminados. No significa que el software esté completamente libre de errores o fallos. Simplemente denota que el software no incluye errores típicos.

Tras la fase de desarrollo, pasamos a escribir los casos de prueba esperados (TDD es una excepción). En la mayoría de las circunstancias, enviaremos el software una vez que haya pasado con éxito todos los casos de prueba. Sin embargo, supongamos que se descubre un error mientras el software se está utilizando en producción. En ese caso, lo corregiremos y luego escribiremos los casos de prueba para evitar que el software incluya el mismo error en el futuro.

La prueba no es más que el acto de verificar algo. Al desarrollar una nueva característica o reparar un error existente, los casos de prueba nos ayudan a determinar si todas las características y unidades implementadas previamente funcionan como se pretende. Garantiza que el desarrollo en curso no comprometerá ninguna de las funciones que ya están en su lugar.

«La prueba demuestra que hay errores, no que no los hay. — Edsger Dijkstra

La prueba unitaria se implementa en Flutter de una manera muy similar a como se implementa en otras pilas tecnológicas. En Flutter, sigues los siguientes procesos:

  1. Analizar el código.

  2. Configurar la simulación de datos (mocking).

  3. Definir la prueba para el grupo(s).

  4. Definir la firma de la función de prueba (o firmas) para cada grupo de prueba.

  5. Escribir las pruebas.

¿Qué es la Prueba Unitaria?

El proceso de prueba automatizada incluye un paso probado como «prueba unitaria», que verifica la confiabilidad de fragmentos de código más pequeños ejecutándolos a través de varios casos de uso. Una unidad puede ser cualquier cosa, desde una variable hasta una función, un método, una clase o un estado.

El primer y más fundamental nivel de prueba se llama prueba unitaria. En este nivel, probamos la funcionalidad de los componentes subyacentes de cada característica.

Una prueba unitaria se compone de tres etapas:

  • Organizar (Arrange)

  • Actuar (Act)

  • Afirmar (Assert)

Lo que debe hacerse durante la fase de Organizar es establecer el objeto de la unidad que necesita ser probada y preparar los prerrequisitos para nuestra prueba. Estas preparaciones incluyen configurar la variable de estado y simulaciones (mocks), entre otras cosas. Por supuesto, dependiendo de los requisitos, la fase de Organizar podría no ser necesaria en absoluto.

Durante la fase de Actuar, ponemos a prueba la unidad pasando argumentos y modificando algún estado antes de almacenar el resultado, si lo hay.

Durante el paso de Afirmar, verificamos si la unidad se comporta como anticiparíamos. Por ejemplo, podríamos anticipar que se llamará a un método determinado, o que el resultado será el mismo que lo que se anticipó.

¿Es Importante la Prueba Unitaria?

  • Escribir y ejecutar pruebas unitarias es un proceso simple. Esto resulta en un ahorro de tiempo significativo.

  • A través de las pruebas unitarias, podemos descubrir errores en una etapa más temprana. Esto resulta en un ahorro significativo de costos y tiempo.

  • Debido a que escribimos sobre todos los resultados posibles de la unidad, es fácil para todos entender de qué se trata la unidad. Como resultado, esto da lugar a una documentación mejorada.

  • Debido a que hacerlo podría hacer que la unidad se vuelva inutilizable, no refactorizamos tu código con demasiada frecuencia. En cambio, la presencia de pruebas unitarias nos da la confianza necesaria para retrabajar nuestro código.

  • La depuración es sencilla. Dado que tenemos conocimiento completo de las situaciones fallidas, podemos centrarnos en la unidad específica que es la raíz del error.

  • Simplemente al mirar los casos de prueba obtenemos una imagen clara de lo que la unidad está destinada a entender. Como resultado, el mantenimiento a largo plazo se simplifica.

¿Qué podemos probar con las pruebas unitarias?

Para construir un conjunto confiable de pruebas unitarias, primero debemos comprender los elementos que deben ser validados dentro de cada unidad individual.

La prueba unitaria a menudo se concentra en los siguientes elementos:

  • Variables de estado

  • Llamadas a funciones/variables

  • Los argumentos de la función

  • Retornos de funciones

Las variables que pertenecen al estado son variables que existen fuera del ámbito local. Esto puede ser una propiedad de clase o una variable global a la que más de una unidad puede acceder. En la mayoría de los casos, mantiene un estado.

En una unidad, vigilamos los siguientes escenarios, entre otros:

  • Verificar si el valor de la constante o la variable final es correcto.

  • Valores al inicio de las variables de estado.

  • Verificar si una función particular es llamada 1…n veces por la unidad.

  • Verificar si la unidad nunca llama a una función particular.

  • Verificar que las variables de estado se estén actualizando de la manera que anticipas.

  • El resultado de la unidad fue exactamente el mismo que lo que se anticipó.

  • Asegúrate de verificar situaciones vacías whenever una cadena, lista o cualquier otro tipo de estructura de datos (DS) compleja esté involucrada; esto es especialmente importante cuando recorremos la DS.

  • Verificar casos de nulo (Solo para tipos que pueden ser nulos). Dart es ahora seguro contra nulos.

  • Verificar el tipo de la variable o el argumento (aunque esto puede no ser necesario si usamos efectivamente el sistema de tipos de Dart).

Unos puntos sobre el funcionamiento de Flutter

Cuando se forma un proyecto, el proceso de prueba se simplifica gracias al marco gracias a la carga automática de la biblioteca flutter test. Flutter ahora puede leer, ejecutar y evaluar pruebas unitarias debido a las contribuciones de la biblioteca. Además, la carpeta test utilizada para almacenar pruebas también es creada automáticamente por Flutter. Por lo tanto, es de suma importancia no renombrar o reubicar la carpeta test, ya que hacerlo interferirá con su funcionalidad y, como resultado, con nuestra capacidad para ejecutar pruebas. Además, es vital agregar el sufijo _test.dart a los nombres de nuestros archivos de prueba. Esto se debe a que Flutter usa este sufijo para identificar archivos de prueba.

Estableceremos un área de almacenamiento ordenada para los archivos de prueba que escribiremos, un sistema en el que diferentes grupos de pruebas tendrán cada uno sus «hogares» que son inmediatamente reconocidos. En vista de la necesidad impuesta por Flutter de ubicar las pruebas dentro de la carpeta test, repliquemos la estructura de carpetas de nuestro código fuente y coloquémosla bajo test. Después de eso, cada vez que escribamos una nueva prueba, la pondremos en la subcarpeta relevante, que son las siguientes: Las pruebas unitarias de las clases Modelo deben colocarse en una carpeta titulada model, así como los calcetines limpios deben colocarse en el cajón de calcetines de tu cómoda y las camisas dobladas deben colocarse en el cajón de camisas.

Adoptar este formato de archivo trae transparencia al proyecto. Proporciona al grupo un método sencillo para determinar qué partes de nuestro código tienen pruebas correspondientes.

¿Cuáles son algunas de las mejores prácticas para las pruebas unitarias?

  • Las pruebas unitarias necesitan ser rápidas.

  • Las pruebas unitarias deberían ser sencillas.

  • Las pruebas unitarias deberían ser predeterminadas.

  • El énfasis debe colocarse en las pruebas unitarias.

  • En las pruebas unitarias, es aceptable repetir código.

  • La descripción de la prueba debe ser sencilla.

Las pruebas unitarias deben ser rápidas. Debido a que ejecutaremos todo el conjunto de pruebas nosotros mismos a lo largo de la fase de desarrollo, cada prueba unitaria en nuestro conjunto de pruebas debería poder ejecutarse en menos de un minuto. Esto ayuda en la detección y corrección temprana de errores. Si toma más tiempo, normalmente incorporaremos esa tarea en una canalización de algún tipo.

Las pruebas unitarias deberían ser sencillas. Cuando revisamos un caso de prueba unitario, toda la información requerida debe estar contenida dentro de ese caso de prueba. No es aceptable que naveguemos el código para entender una sola prueba. Por lo tanto, la prueba unitaria no debería requerir una explicación.

El determinismo debe aplicarse a las pruebas unitarias. Sin hacer ningún cambio al código fuente, una prueba unitaria siempre debería replicar exactamente el mismo comportamiento sin importar dónde o cuándo se pruebe. Los resultados de una prueba unitaria no deberían depender de variables o condiciones externas, como la hora actual, una base de datos, la web o una API nativa. En la mayoría de los casos, nos burlamos de ellos (usamos mocks).

El enfoque debe estar en las pruebas unitarias. Una sola unidad debería servir como el único foco de una prueba unitaria. Dentro del contexto de la prueba unitaria, no deberíamos probar las dependencias.

En las pruebas unitarias, es aceptable repetir código. El objetivo de una prueba unitaria debería ser asegurar que el código que se está probando sea lo más sencillo posible. Debería ser posible para cualquiera entender el caso de prueba sin la necesidad de investigar sus dependencias o el estado presente de la unidad. Por lo tanto, repetir ciertos fragmentos de código es aceptable si hacerlo hace el programa más fácil de comprender y más sencillo.

La descripción de la prueba unitaria debe ser sencilla. Una buena descripción debe contener cuatro partes:

  1. La unidad que se pondrá a prueba.

  2. La condición en la que se encuentra la unidad en el momento.

  3. La contribución que haremos.

  4. La reacción que estamos preparando.

Simulación (Mocking)

El objetivo principal de las pruebas unitarias es compartimentalizar y enfocarse en la unidad que está siendo evaluada en lugar de concentrarse en probar cualquier otra dependencia que pueda estar presente. Sin embargo, en la mayoría de las circunstancias, debemos confiar en otras dependencias como servidores de bases de datos, servidores web, APIs de plataforma y otros dispositivos y componentes externos.

Supongamos por un momento que nuestra unidad actual es dependiente de una API web. La prueba se completa lentamente pero con éxito cuando se ejecuta en un servidor en vivo. Sin embargo, la prueba unitaria fallará si el servidor no está disponible. Esto resulta en impredictibilidad en la prueba unitaria. Porque ya no tendremos control sobre el servidor web. Cuando el servidor web experimenta una interrupción, no es nuestra culpa. El uso de la simulación (mocking) ocurre en este punto.

En el contexto de las pruebas unitarias, «simular» (mocking) se refiere al proceso que se lleva a cabo cada vez que la unidad que se está probando depende de recursos externos. La simulación se usa para aislar y concentrarse en el código que se está probando en lugar de en el comportamiento de cualquier dependencia externa.

MockTail es una abreviatura de «Sin Generación de Código».

El objetivo principal de Mocktails es proporcionar una API sencilla y conocida para el desarrollo de simulaciones (mocks) en Dart, completa con seguridad de nulos, sin requerir la creación manual de simulaciones o la generación de código.

Felix Angelov, la misma persona que produjo bloc, equatable y otros programas similares, es el autor de esta librería. Aún más impresionante que sus otros paquetes es el hecho de que esta librería tiene una cobertura completa de su código.

Para tus mejores servicios de pruebas unitarias, y para consultar con expertos en pruebas unitarias, ¡contáctanos ahora!

Preguntas Frecuentes (FAQs)

¿En Flutter, qué es una Prueba Unitaria?

Las pruebas unitarias son muy útiles cuando se verifica el funcionamiento de un único método, clase o función. El paquete test proporciona la infraestructura básica para desarrollar pruebas unitarias, y el paquete flutter_test contiene utilidades complementarias para probar widgets.

¿Cuántos tipos de pruebas unitarias admite el framework Flutter?

Tres tipos distintos de pruebas pueden ejecutarse con Flutter. Primero, la operación de un método o clase es validada por una prueba unitaria. Sin ejecutar realmente la aplicación en sí, la funcionalidad de los widgets de Flutter puede ser validada con el uso de una prueba de widget. Finalmente, toda la aplicación se somete a lo que se conoce como una prueba de integración, que también se conoce como prueba de extremo a extremo o prueba GUI.

¿En Flutter, qué se necesita para crear una prueba unitaria?

El proceso para realizar pruebas unitarias en Flutter es idéntico al procedimiento que se usa en la mayoría de otros marcos. Después de establecer las clases y funciones que necesitan ser probadas (los casos de prueba), el siguiente paso es evaluar el código, configurar la simulación de datos (mocking), definir los grupos de prueba, definir las firmas de las funciones de prueba para cada grupo de prueba, escribir las pruebas y ejecutarlas.

¿Por qué es vital realizar pruebas unitarias?

Las pruebas unitarias pueden eliminar o reducir significativamente la cantidad de errores en una aplicación, lo que resulta en una experiencia de usuario mejorada desde el momento en que una aplicación está disponible para el público. Además, leer pruebas unitarias es una forma excelente de ayudar a los nuevos desarrolladores a aprender y entender tu código, lo que es un beneficio adicional.

Share This Article
Leave a comment