Fundamentos de testing: preguntas y respuestas

13/11/2020
Artículo original

Imagen ornamental, un circuito electrónico simple con cables y un medidor, de Nicolas Thomas, CC0 en Unsplash 

Nota: este artículo es una traducción de "Software Testing Fundamentals - Questions and Answers" de Amir Ghahrai, con su permiso expreso. Amir es el fundador de DevQA.io un sitio especializado en ayudar a otros desarrolladores a convertirse en testers técnicos.

Las pruebas de software constituyen una actividad más dentro del proceso de desarrollo de software. Se trata de averiguar si el software ofrece la calidad esperada a las partes interesadas.

¿Qué son las pruebas de software o testing de software?

Diferentes personas han dado diferentes definiciones acerca del testing, pero, en general, su objetivo es:

  • Asegurar que el software cumpla con los requisitos y el diseño acordados.
  • Que la aplicación funcione como se esperaba.
  • Que la aplicación no contenga graves errores.
  • Que cumpla con el uso previsto según las expectativas del usuario.

Las pruebas de software se utilizan a menudo junto con los términos verificación y validación.

  • Validación: ¿estamos haciendo el trabajo correcto?
  • Verificación: ¿estamos haciendo bien el trabajo?

La verificación es la comprobación o test de elementos, incluido el software, para constatar su conformidad y coherencia con una especificación asociada.

La validación es el proceso de comprobar que lo que se ha especificado es lo que realmente quería el usuario.

Las pruebas de software son solo un tipo de verificación, que también utiliza técnicas como revisiones, análisis, inspecciones y recorridos.

¿Qué son las pruebas exploratorias y cuándo deben realizarse?

Una prueba exploratoria consiste en hacer simultáneamente un test de diseño y ejecución de una aplicación. Esto significa que el evaluador (tester) usa su conocimiento y experiencia en pruebas para predecir dónde y bajo qué condiciones el sistema podría comportarse inesperadamente. A medida que el evaluador comienza a explorar el sistema, se le ocurren sobre la marcha nuevas ideas de diseño de prueba y se ejecutan en el software que se está probando.

En una sesión de prueba exploratoria, el evaluador ejecuta una cadena de acciones contra el sistema, cada acción depende del resultado de la acción anterior, por lo tanto, el fruto del resultado de las acciones podría influir en lo que hace el evaluador a continuación, es decir, no hay dos sesiones de prueba idénticas.

Esto contrasta con Scripted Testing, donde las pruebas se diseñan de antemano utilizando los requisitos o los documentos de diseño, generalmente antes de que el sistema esté listo y se ejecutan esos mismos pasos exactos contra el sistema más tarde.

Las pruebas exploratorias generalmente se realizan a medida que el producto evoluciona (ágil) o como una verificación final antes de que se lance el software. Es una actividad complementaria a las pruebas de regresión automatizadas.

¿Qué técnicas de testing existen y cuál es su propósito?

Las técnicas de testing se utilizan principalmente con dos propósitos: para ayudarnos a identificar defectos y para reducir el número de casos a verificar.

  • La partición de equivalencia se utiliza principalmente para reducir el número de casos a verificar identificando diferentes conjuntos de datos que no son iguales y ejecutando solo un test de cada conjunto de datos.
  • El análisis de valor límite se utiliza para verificar el comportamiento del sistema en los límites de los datos permitidos.
  • Las pruebas de transición de estado se utilizan para validar estados permitidos y no permitidos y transiciones de un estado a otro mediante varios datos de entrada.
  • La prueba por pares o todos los pares es una técnica de testing muy poderosa y se utiliza principalmente para reducir el número de casos a verificar mientras aumenta la cobertura de combinaciones de funciones.

¿Por qué es necesario hacer test de software?

Las pruebas son necesarias para identificar cualquier defecto presente en el software que pueda causar algún perjuicio a los usuarios. Sin las pruebas adecuadas, podríamos lanzar un software que podría funcionar mal y causar problemas graves.

Algunos ejemplos son:

  • Software en una máquina de soporte vital que puede causar daños graves a un paciente.
  • El software en una planta nuclear que monitorea la actividad nuclear puede causar daños al medio ambiente.
  • La aplicación bancaria o financiera que calcula los tipos de cambio puede causar pérdidas financieras a una empresa.

Imagen ornamental de una oruga (bug) por Yoal Desurmont en Unsplash, CC0

¿Cuál es la diferencia entre bug, defecto (defect), error (error), falla (failure), fallo (fault), y equivocación (mistake)?

Error y equivocación es lo mismo. Bug, defecto y fallo, también es lo mismo.

En general, una persona comete una equivocación (error) que produce un defecto (bug, fallo) en una aplicación que puede causar una falla (avería).

Los defectos ocurren porque los seres humanos son propensos a equivocarse, además, una aplicación puede ser muy compleja, por lo que la integración de diferentes componentes puede provocar comportamientos extraños.

¿Cuántas pruebas son suficientes?

No hay una respuesta definitiva a esta pregunta. Las pruebas no son absolutas y no tienen límites. Sin embargo, podemos usar métricas de riesgo (test basados en riesgos) para identificar los escenarios probables que pueden causar el mayor daño o las partes del software que se utilizan principalmente, para así concentrar nuestro tiempo y esfuerzo en las partes que son más importantes.

Los test deben proporcionar suficiente información sobre el estado o la salud de una aplicación, para que las partes interesadas puedan tomar una decisión informada sobre si lanzar el software o dedicar más tiempo a las pruebas.

¿Qué es el proceso de prueba fundamental?

Para aprovechar al máximo los test, se debe seguir un proceso definido. Pero antes de que comience cualquier test, se debe emplear gran parte del esfuerzo en crear un buen plan de testing. Un buen plan de testing es de gran ayuda para garantizar que las pruebas se alineen con lo que se pretende lograr.

Esto quizás sea más aplicable a un entorno de pruebas bastante formal (como una misión crítica). La mayoría de las organizaciones comerciales tienen procesos de prueba menos rigurosos. Sin embargo, cualquier esfuerzo de prueba puede utilizar estos pasos de alguna forma.

El proceso de prueba fundamental consta de 5 actividades:

  • Planificación
  • Especificación
  • Ejecución
  • Grabación
  • Comprobación de la finalización del test

El proceso de prueba siempre comienza con la planificación de la prueba y termina con la verificación de la finalización de la prueba.

Todas y cada una de las actividades pueden repetirse (o al menos volver a visitarse) ya que pueden ser necesarias varias iteraciones antes de que se cumplan los criterios de finalización definidos durante la actividad de planificación de pruebas.

Siete principios de testing

A continuación se muestran los siete principios de testing:

1. Los test muestran la presencia de errores

Probar una aplicación solo puede revelar que existen uno o más defectos en la aplicación, sin embargo, el test por sí solo no puede probar que la aplicación esté libre de errores. Por lo tanto, es importante diseñar casos de prueba que encuentren tantos defectos como sea posible.

2. Es imposible hacer test exhaustivos

A menos que la aplicación bajo prueba (AUT – application under test) tenga una estructura lógica muy simple y una entrada limitada, no es posible probar todas las combinaciones posibles de datos y escenarios. Por esta razón, el riesgo y las prioridades se utilizan para concentrarse en los aspectos más importantes a probar.

3. Pruebas tempranas

Cuanto antes comencemos con los test, mejor aprovecharemos el tiempo disponible. Tan pronto como estén disponibles los productos iniciales, tales como los requisitos o los documentos de diseño, podemos comenzar a hacer test. Es común que la fase de prueba se reduzca al final del ciclo de vida del desarrollo, es decir, cuando el desarrollo ha finalizado, por lo que al comenzar las pruebas temprano, podemos preparar las pruebas para cada nivel del ciclo de vida del desarrollo.

Otro punto importante sobre las pruebas tempranas es que, cuando los defectos se encuentran al principio del ciclo de vida, son mucho más fáciles y económicos de corregir. ¡Es mucho más económico cambiar un requisito incorrecto que tener que cambiar una funcionalidad en un sistema grande que no funciona según lo solicitado o diseñado!

4. Agrupación de defectos

Durante las pruebas, se puede observar que la mayoría de los defectos detectados están relacionados con una pequeña cantidad de módulos dentro de un sistema. Es decir, un pequeño número de módulos contiene la mayoría de los defectos del sistema. O sea, podemos aplicar el principio de Pareto a las pruebas de software: aproximadamente el 80% de los problemas se encuentran en el 20% de los módulos.

5. La paradoja de los pesticidas

Si sigues ejecutando el mismo conjunto de pruebas una y otra vez, es probable que en esos test no descubran defectos nuevos. Esto es debido a que a medida que el sistema evoluciona, muchos de los defectos detectados anteriormente se habrán solucionado y los antiguos casos de prueba ya no aplican.

Cada vez que se soluciona un defecto o se agrega una nueva funcionalidad, necesitamos hacer pruebas de regresión para asegurarnos de que el nuevo software modificado no haya roto ninguna otra parte del mismo. Sin embargo, esos casos de prueba de regresión también deben modificarse para reflejar los cambios realizados en el software para que sean aplicables y, con suerte, detectar nuevos defectos.

6. Los test dependen del entorno

Las diferentes metodologías, técnicas y tipos de pruebas están relacionadas con el tipo y la naturaleza de la aplicación. Por ejemplo, una aplicación para un dispositivo médico necesita más pruebas que un software de juegos.

Y lo que es más importante aún, un software de dispositivo médico requiere pruebas basadas en riesgos, cumplir con las regulaciones de la industria médica y posiblemente técnicas de diseño de pruebas específicas.

Del mismo modo, un sitio web muy popular debe pasar por rigurosas pruebas de rendimiento, así como pruebas de funcionalidad para asegurarse de que el rendimiento no se vea afectado por la carga en los servidores.

7. Ausencia de errores: ¡falacia!

Solo porque las pruebas no hayan encontrado ningún defecto en el software, no significa que el software esté listo para entrar en producción. ¿Fueron las pruebas que ejecutamos diseñadas realmente para detectar la mayoría de los defectos? ¿O para ver si el software se ajustaba a los requisitos del usuario? Hay muchos otros factores a considerar antes de tomar la decisión de enviar el software.

Imagen ornamental, caja de color blanco, por Daniele Levis Pelusi, CC0 en Unsplash

¿Qué es el test de la caja blanca?

Las pruebas de caja blanca tratan con la lógica interna y la estructura del código. Las pruebas de caja blanca también se denominan pruebas de cristal, estructurales, de caja abierta o de caja transparente. Los test escritos en base a la estrategia de prueba de caja blanca incorporan medidas como la cobertura del código escrito, de las ramas, las rutas, las declaraciones, la lógica interna del código, etc.

Para implementar las pruebas de caja blanca, el evaluador debe lidiar con el código y, por lo tanto, debe poseer conocimientos de codificación y lógica, es decir, el funcionamiento interno del código. La prueba de caja blanca también necesita que el evaluador busque en el código y descubra qué unidad/declaración/parte del código no funciona correctamente.

Test unitarios

El desarrollador lleva a cabo pruebas unitarias para comprobar si el módulo o la unidad de código en particular está funcionando bien. Los test unitarios se producen a un nivel muy básico, ya que se lleva a cabo a medida que se desarrolla la unidad del código o se construye una funcionalidad en particular.

Análisis estático y dinámico

El análisis estático implica revisar el código para descubrir cualquier posible defecto en el mismo. El análisis dinámico supone ejecutar el código y analizar la salida.

Cobertura de instrucciones

En este tipo de prueba, el código se ejecuta de tal manera que cada instrucción en la aplicación se ejecuta al menos una vez. Ayuda a asegurar que todas las declaraciones se ejecuten sin ningún efecto secundario.

Cobertura de ramas

Ninguna aplicación es posible escribirla de un tirón, en algún momento necesitamos abrir una rama de código para realizar una funcionalidad particular. Las pruebas de cobertura de ramas ayudan a validar todas las ramas en el código y asegurarse de que ninguna ramificación dé lugar a un comportamiento anormal de la aplicación.

Pruebas de seguridad

Las pruebas de seguridad se llevan a cabo con el fin de averiguar cómo de bien el sistema puede protegerse frente a accesos no autorizados, piratería, cualquier daño en el código, etc.. Este tipo de test requiere de técnicas sofisticadas.

Pruebas de cambio

Un tipo de test en el que se prueba la aplicación en busca del código que se modificó después de corregir un error o defecto en particular. También ayuda a descubrir qué código y qué estrategia de codificación pueden ayudar a desarrollar la funcionalidad de manera efectiva.

Ventajas de los test de caja blanca

Como el conocimiento de la estructura de código interna es un requisito previo, resulta muy fácil descubrir qué tipo de entrada / datos pueden ayudar a probar la aplicación de manera eficaz. La otra ventaja de las pruebas de caja blanca es que ayuda a optimizar el código. Ayuda a eliminar las líneas adicionales de código, que pueden provocar defectos ocultos.

Desventajas de los test de caja blanca

Como el conocimiento del código y la estructura interna es un requisito previo, se necesita un evaluador capacitado para llevar a cabo este tipo de pruebas, lo que aumenta el coste. Y es casi imposible examinar cada fragmento de código para descubrir errores ocultos, que pueden crear problemas y provocar fallas en la aplicación.

Imagen ornamental, una caja de color negro intenso sobre fondo negro, por an_vision, CC0 en Unsplash

¿Qué es el test de la caja negra?

En las pruebas de la caja negra, el evaluador prueba una aplicación sin conocer el funcionamiento interno de la misma.

Debido a que las pruebas de caja negra no se relacionan con el código subyacente, las técnicas pueden derivarse de los documentos de requisitos o especificaciones de diseño y, por lo tanto, pueden comenzar tan pronto como se escriban los requisitos.

Técnica de prueba de análisis de valor límite

El análisis de valor límite (BVA – boundary value analysis), prueba el comportamiento de un programa en los límites. Al verificar un rango de valores, después de seleccionar el conjunto de datos que se encuentran en las particiones válidas, lo siguiente es verificar cómo se comporta el programa en los valores límite de las particiones válidas. El análisis de valor límite es más común cuando se verifica un rango de números.

Técnica de transición de estado

La técnica de prueba de transición de estado se utiliza cuando algún aspecto del sistema puede describirse en lo que se denomina una “máquina de estados finitos”. Esto simplemente significa que el sistema puede estar en un número (finito) de estados diferentes, y las transiciones de un estado a otro están determinadas por las reglas de la “máquina”.

En este modelo se basan el sistema y los test. Cualquier sistema en el que obtenga una salida diferente para la misma entrada, dependiendo de lo que haya sucedido antes, es un sistema de estado finito.

Técnica de prueba de partición de equivalencia

La idea detrás de la técnica de prueba de partición de equivalencia es eliminar el conjunto de datos de entrada que hacen que el sistema se comporte de la misma manera y produzca el mismo resultado al probar un programa.

El proceso de la técnica de partición de equivalencia implica identificar el conjunto de datos como una condición de entrada que dan el mismo resultado al ejecutar un programa y clasificarlos como un conjunto de datos equivalentes (porque hacen que el programa se comporte de la misma manera y genere la misma salida) y particionándolos de otro conjunto equivalente de datos.

Ventajas de los test de caja negra

  • La prueba es imparcial porque el diseñador y el evaluador son independientes entre sí.
  • El evaluador no necesita tener conocimientos de ningún lenguaje de programación específico.
  • El test se realiza desde el punto de vista del usuario, no del diseñador.
  • Los casos de prueba se pueden diseñar tan pronto como se completen las especificaciones.

Desventajas de los test de caja negra

  • La prueba puede ser redundante si el diseñador de software ya ha ejecutado un caso de prueba.
  • Los casos de prueba son difíciles de diseñar.
  • Probar cada flujo de entrada posible no es realista porque llevaría una cantidad de tiempo excesiva; por lo tanto, muchas rutas de programas no se verificarán.