Blog

Diferencias entre testing funcional y no funcional

En este artículo, nos proponemos hacer foco en las diferencias del testing funcional y el no funcional, con el fin de lograr una comprensión cabal de estas temáticas y poder profundizar desde diferentes ángulos y perspectivas. Esta vez, con una entrevista a Alejandro Aires.

Foto de Windows en Unsplash

Antes de adentrarnos en las diferencias entre pruebas funcionales y no funcionales, es importante destacar que ambos tipos de testing son necesarios para la creación de software de calidad. Se enfocan en aspectos diferentes, pero en definitiva son complementarios.

¿Qué es el testing funcional?

El testing funcional se ocupa de verificar que el sistema y sus funcionalidades funcionen como se espera y para lo cual fueron desarrollados.

“Bajándolo un poco a tierra, en un sistema web como por ejemplo una tienda online es fundamental que el usuario sea capaz de realizar las compras, ya que es lo que le da sustento al negocio. Para ello, se precisa realizar testing funcional, con foco en verificar que el flujo de compra cumpla su objetivo, su funcionalidad”

Alejandro Aires, tester de software en Abstracta y miembro del equipo de Performance

¿Qué es el testing no funcional?

El testing no funcional, por su lado, se enfoca en factores transversales, relacionados con la experiencia de uso del usuario. Algunos ejemplos de ello son la usabilidad, seguridad, accesibilidad y performance.

Alejandro Aires propuso un ejemplo para lograr figurar mejor la temática: “Supongamos que estamos probando realizar una transferencia bancaria. El testing funcional se encarga de probar que la transferencia se haga bajo los requisitos previamente establecidos (que llegue al destino correcto, con el monto correcto, etc.), mientras que el no funcional puede verificar otras cuestiones, como que el sistema soporte muchas transacciones simultáneas o que sea amigable para el usuario”.

Hay otro caso interesante para analizar, que es el del airbag. Si un airbag no funciona rápido, con buena performance, entonces no cumple su funcionalidad. Ejemplos como este son los que hacen que la separación no sea tan clara en algunos casos.

Otra diferencia se encuentra en los requisitos para comenzar con las pruebas. “Por lo general, las pruebas no funcionales suelen requerir que el sistema tenga cierta estabilidad, es decir que ya se haya avanzado con las pruebas y ajustes funcionales”, especificó Alejandro. “Aún así, esto depende del sistema, no siempre es de ese modo”, añadió.

En definitiva, se trata de pruebas que se complementan en busca de incrementar la calidad desde una visión holística, teniendo en cuenta distintos factores de calidad.

Alejandro Aires, Software Tester en Abstracta

¿Qué tipos de testing existen dentro de funcional?

Existen muchos enfoques y clasificaciones. Por ejemplo, podríamos comenzar hablando de testing exploratorio o planificado (o guionado, scripted en Inglés). Existen distintas técnicas de testing funcional para diseñar casos o datos de prueba relevantes, que pueden ser utilizadas tanto en un enfoque exploratorio como en uno guionado, pero por lo general se las asocia más con el guionado ya que se les suele llamar técnicas para diseñar casos de prueba.

La particularidad del testing exploratorio es que presenta una estructura externa que es sencilla de describir, en la que durante un lapso de tiempo preestablecido (de no más de dos horas) un tester interactúa con un producto para cumplir con el objetivo de una misión. El objetivo de esto es poder luego presentar y reportar los resultados del proceso, los cuales serán utilizados por el resto de los actores del proyecto para tomar decisiones a conciencia.

Por otra parte, podemos clasificar según el nivel al que realizamos las pruebas o el momento en el ciclo de desarrollo. Así es que podemos distinguir entre pruebas unitarias, pruebas de componentes, pruebas de humo, pruebas de integración, pruebas de sistemas, de regresión, pruebas de aceptación del usuario y más. Me enfocaré aquí en algunas de ellas:

  • En las pruebas unitarias, se prueban las diferentes unidades de modo individual, generalmente acá hablamos de unidades a nivel de código. Se trata de pruebas muy específicas, para las cuales es preciso aislar un fragmento del código, el cual corresponde exclusivamente a lo que se quiere probar. En la gran mayoría de los casos, los desarrolladores son los responsables de llevar adelante este tipo de pruebas. Realizar este tipo de pruebas busca detectar errores tempranamente y evitar que escalen.
  • Realizamos pruebas de integración cuando necesitamos integrar una funcionalidad al sistema y verificarla en conjunto con el resto de componentes del sistema que estamos probando, con el fin de evaluar si funcionan correctamente en conjunto. Esto puede darse a nivel de integración de unidades de código, a nivel de servicios (a nivel de la API de un sistema en capas) o incluso a nivel de sistema, cuando estamos integrando los cambios en distintos componentes.
  • Las pruebas de regresión son un subconjunto de las pruebas planificadas que se seleccionan para ejecutar periódicamente, por ejemplo ante cada nueva liberación del producto. Tienen el objetivo de verificar que el producto no haya sufrido regresiones.

En otras palabras, y en línea con el punto previo, si queremos verificar que las integraciones que realizamos no hayan afectado otra funcionalidad previamente testeada, precisamos realizar testing de regresión. Además, son pruebas muy relevantes para verificar que lo que antes andaba bien ahora siga funcionando.

¿Qué técnicas se pueden utilizar para diseñar casos de prueba en testing funcional?

Hay muchas. Existen técnicas muy conocidas tales como particiones de equivalencia, valores límites, combinaciones por pares o tablas de decisión. También existen técnicas más avanzadas como la que implica el uso de máquinas de estado.

En lugar de entrar a detallar estas técnicas, que para ello pueden revisar el libro de Federico Toledo, quisiera distinguir cómo se clasifican, con base en distintos criterios, viendo así de que se tratan los enfoques de caja blanca y caja negra, los casos de prueba específicos y abstractos, y el enfoque de pruebas dirigidas por datos.

White-box (caja blanca)

Si para diseñar las pruebas nos basamos en información interna del sistema que estamos probando, tal como el código, esquema de base de datos, etc., entonces se dice que estamos siguiendo una estrategia de caja blanca. Lo más común es basar el diseño en el código fuente para lograr determinados niveles de cobertura. Para figurar esto, podemos decir que el más simple de estos niveles implicaría intentar cubrir todas las líneas de código.

A veces, algunas personas hablan de “caja transparente” en lugar de caja blanca. Esto hace referencia a que el objetivo de esta estrategia es poder mirar qué hay dentro de esa caja que estamos probando.

Black-box (caja negra)

Contrariamente a caja blanca, la expresión “caja negra” intenta figurar que el sistema es una caja cuyo interior no puede ser observado desde afuera. En este modo de trabajo, nos basamos únicamente en la observación de entradas y salidas del sistema. Esto puede ser a nivel de sistema, unidad, componente, API, etc.

Podríamos decir que con caja blanca nos preocupamos por lo que pasa dentro de la caja y con caja negra nos preocupamos por lo que pasa fuera de ella. Muchas veces el límite no está claro, o tal vez estamos siguiendo un enfoque de caja negra, pero como sabemos algo de lo que sucede dentro entonces aprovechamos esa información. En este sentido, hay quienes hablan también de “caja gris”, que es justamente cuando se combinan ambos enfoques.

Casos de prueba abstractos y específicos

Se trata de una clasificación que refiere a la especificidad con la que está detallado el caso de prueba.

Un caso de prueba abstracto se caracteriza por no tener determinados los valores para las entradas y salidas esperadas, por lo cual se utilizan variables y se describen con operadores lógicos ciertas propiedades que deben cumplir.

Un caso de prueba específico es una instancia de un caso de prueba abstracto, en la que se determinan valores específicos para cada variable de entrada y para cada salida esperada. No es lo mismo especificar un caso de prueba donde se agrega un producto de valor mayor a 1000 pesos al carrito de compra a indicar específicamente que se debe agregar el producto de identificador XYZ, que ya se sabe que tiene un costo establecido mayor a 1000 pesos.

Cada caso de prueba abstracto puede ser instanciado con distintos valores (siguiendo el ejemplo, con cualquier producto que vale más de 1000 pesos), por lo que podrá haber distintos casos de prueba específicos al momento de ser ejecutado o diseñado a bajo nivel. Se asigna un valor concreto a cada variable, tanto de entrada como de salida, de acuerdo a las propiedades y restricciones lógicas que tiene determinadas.

Data-Driven Testing (pruebas dirigidas por datos)

Es una técnica para construir casos de prueba, en la cual básicamente se separan los datos de entrada y salida del flujo que se ejecuta en la aplicación. Dicho de otra manera, se parametrizan los casos de prueba. Para ello, se representa el flujo (la serie de pasos para ejecutar el caso de prueba), y se almacenan los datos de entrada y salida esperados en una fuente típicamente externa (en un archivo csv, planilla, base de datos).

Esto permite agregar nuevos casos de prueba fácilmente, mediante el ingreso de nuevos datos de entrada y de salida esperados que sirvan para ejecutar el mismo flujo.

El flujo de la aplicación se define con casos de prueba abstractos, que al momento de ser ejecutados con un juego específico de datos se convierten de alguna manera en casos de prueba específicos.

¿Qué tipos de testing existen dentro del no funcional?

Cada tipo de pruebas se asocia a un factor de calidad. Algunos de los más destacados son:

Testing de usabilidad

Las pruebas de usabilidad evalúan el grado en que el sistema puede ser utilizado por usuarios específicos con efectividad, eficiencia y satisfacción en un contexto de uso específico. Existen varias técnicas para analizar la usabilidad, las cuales buscan detectar mejoras posibles en características asociadas a la experiencia de usuario, como por ejemplo que un sistema sea más intuitivo y fácil de utilizar, entre otras cosas.

Testing de accesibilidad

Es parte del testing de usabilidad, pero su foco es que todas las personas puedan utilizar el sistema, incluyendo en todos los casos a quienes tienen algún tipo de discapacidad, contextual, temporal o permanente.

El testing de accesibilidad ayuda a detectar los errores y barreras que pueden existir en el software, pero que no son fácilmente detectables si no se realizan pruebas específicas para encontrarlas. Las personas expertas en accesibilidad hablan de la importancia de la incorporación de la accesibilidad en todo el ciclo de vida del desarrollo de software.

Testing de seguridad

Foto de FLY:D en Unsplash

El objetivo de las pruebas de seguridad es buscar posibles vulnerabilidades o amenazas que puedan afectar la protección, disponibilidad e integridad de los datos o la funcionalidad del sistema. El testing de seguridad es importante como mecanismo preventivo, en búsqueda de posibles vulnerabilidades.

De todos modos, no es posible prevenir todo y es crucial contar con protocolos específicos para ser utilizados ante eventuales ataques informáticos.

Según el Informe de Riesgos Globales 2022 del Foro Económico Mundial, el malware aumentó un 358% en 2020, mientras que el ransomware se incrementó en un 435%.

Testing de performance

Se analizan tanto los tiempos de respuesta como el consumo de recursos. Para ello, se simulan múltiples usuarios concurrentes y se analiza el rendimiento de la aplicación bajo prueba. Cuanto más expuesta, más usuarios y variables haya en torno a una aplicación, más importante se torna realizar testing de performance.

Para analizar estos comportamientos, se suele poner al sistema bajo una gran cantidad de usuarios en concurrencia mientras se mide el uso de recursos en búsqueda de cuellos de botella. Dentro de esta categoría, podemos encontrar pruebas de carga, volumen y estrés entre otras.

Para concluir, nuestro COO Federico Toledo sostuvo que lo ideal es siempre diseñar una estrategia en la que se combinen ambos tipos de testing desde fases tempranas (shift left), trabajarlas en todo el proceso (testing continuo), monitorear en producción, y usar esa información para mejorar la calidad del software y la calidad de nuestras pruebas (shift right).


¿Cómo ha sido tu experiencia haciendo testing funcional y no funcional? ¡Cuéntanos en los comentarios!

¡Síguenos en LinkedInTwitterFacebookInstagram y Youtube para ser parte de nuestra comunidad y afianzar tus conocimientos en testing y calidad de software!


Otros contenidos relacionados

Testing Manual vs. Automatizado: ¿cuál elegir para tu proyecto?

Los 7 Principios Esenciales del Testing de Software

Cómo crear la Estrategia de Pruebas adecuada para tu proyecto

Shift Left Testing y Shift Right Testing, una estrategia posible


141 / 202