Teoría sobre Deseño e realización de probas
Sumario
- 1 Introducción
- 2 El testing
- 2.1 Características
- 2.2 Importancia
- 2.3 Contexto clásico de la prueba de software y fases de la prueba
- 2.4 Error, defecto y fallo
- 2.5 Niveles de testing
- 2.6 Tipos de prueba
- 2.7 Técnicas de prueba
- 2.8 Organización de los casos de prueba y herramientas para su gestión
- 3 Conclusiones
- 4 Anexo I - Herramientas Software para la realización de pruebas
- 5 Anexo II - Ejemplos de técnicas de prueba
- 6 Anexo III - Ejemplos de estrategias de integración
- 7 Anexo IV - Ejemplo de caso de prueba unitario con JUnit
- 8 Anexo V - Herramientas Software para la documentación
- 9 Anexo VI - Ejemplo de documentación con JavaDoc
- 10 Anexo VII - Normas IEEE relacionadas con el software, su calidade, documentación y pruebas
- 11 Bibliografía
- 12 Referencias
Introducción
El testing
Las pruebas de software son las investigaciones empíricas y técnicas cuyo objetivo es proporcionar información objetiva e independiente sobre la calidad del producto a la parte interesada o stakeholder. Es una actividad más en el proceso de control de calidad.
Las pruebas son un conjunto de actividades dentro del desarrollo de software. Por lo tanto el modelos de pruebas será distinto dependiendo del modelo de desarrollo de software.
El objetivo de las pruebas no es asegurar la ausencia de defectos en un software, únicamente puede demostrar que existen defectos en el software. Nuestro objetivo es pues, diseñar pruebas que sistemáticamente saquen a la luz diferentes clases de errores, haciéndolo con la menor cantidad de tiempo y esfuerzo.
Características
Algunas características de una buena prueba son:
- Ha de tener una alta probabilidad de encontrar un fallo. Para alcanzar este objetivo el responsable de la prueba debe entender el software e intentar desarrollar una imagen mental de cómo podría fallar.
- Debe centrarse en dos objetivos. Probar si el software:
- no hace lo que debe hacer
- hace lo que no debe hacer.
- No debe ser redundante. El tiempo y los recursos son limitados, así que todas las pruebas deberían tener un propósito diferente.
- Debería ser la “mejor de la cosecha”. Esto es, se debería emplear la prueba que tenga la más alta probabilidad de descubrir una clase entera de errores
- No debería ser ni demasiado sencilla ni demasiado compleja, pero si se quieren combinar varias pruebas a la vez se pueden enmascarar errores; por lo que en general, cada prueba debería realizarse separadamente.
Importancia
Su importancia es clave porque con este proceso se pretende:
- que el software funciona acorde a los requisitos
- que todos los requisitos hayan sido completados
- validar que el elemento u objeto de nuestras pruebas es el esperado
- incrementar la confianza en el desarrollo
- encontrar fallos y defectos y prevenir su aparición
- reportar al cliente el estado del software en términos de calidad y asegurar el cumplimiento de los acuerdos alcanzados
Todo ello redunda en una reducción de costes, plazos de entrega y riesgos a la par que aumenta la calidad aumentando la satisfacción del cliente.
Contexto clásico de la prueba de software y fases de la prueba
La figura muestra el contexto en el que se realiza la prueba de software. Concretamente la prueba de software se puede definir como una actividad en la cual:
- un sistema o uno de sus componentes se ejecuta en circunstancias previamente especificadas (configuración de la prueba), registrándose los resultados obtenidos.
- seguidamente se realiza un proceso de Evaluación en el que los resultados obtenidos se comparan con los resultados esperados para localizar fallos en el software.
- estos fallos conducen a un proceso de Depuración en el que es necesario identificar la falta asociada con cada fallo y corregirla, pudiendo dar lugar a una nueva prueba.
- como resultado final se puede obtener una determinada predicción de Fiabilidad o un cierto nivel de confianza en el software probado.
Veamos ahora cuáles son las tareas a realizar para probar un software:
- Diseño de las pruebas. Esto es, identificación de la técnica o técnicas de pruebas que se utilizarán para probar el software. Distintas técnicas de prueba ejercitan diferentes criterios como guía para realizar las pruebas. Seguidamente veremos algunas de estas técnicas.
- Generación de los casos de prueba. Los casos de prueba representan los datos que se utilizarán como entrada para ejecutar el software a probar. Más concretamente los casos de prueba determinan un conjunto de entradas, condiciones de ejecución y resultados esperados para un objetivo particular. Como veremos posteriormente, cada técnica de pruebas proporciona unos criterios distintos para generar estos casos o datos de prueba.
- Por lo tanto, durante la tarea de generación de casos de prueba, se han de confeccionar los distintos casos de prueba según la técnica o técnicas identificadas previamente. La generación de cada caso de prueba debe ir acompañada del resultado que ha de producir el software al ejecutar dicho caso.
- Definición de los procedimientos de la prueba. Esto es, especificación de cómo se va a llevar a cabo el proceso, quién lo va a realizar, cuándo, …
- Ejecución de la prueba. Aplicando los casos de prueba generados previamente e identificando los posibles fallos producidos al comparar los resultados esperados con los resultados obtenidos.
- Realización de un informe de la prueba. Con el resultado de la ejecución de las pruebas, qué casos de prueba pasaron satisfactoriamente, cuáles no, y qué fallos se detectaron.
- Proceso de depuración. Tras estas tareas es necesario realizar un proceso de depuración de las faltas asociadas a los fallos identificados.
Dentro del ciclo de vida del software en sus metologías más clásicas, las pruebas serían una fase a realizarse posteriormente al desarrollo:
Nuevos paradigmas: TDD y BDD
El desarrollo guiado por pruebas de software, o Test-driven development (TDD) es una práctica de ingeniería de software que involucra otras dos prácticas:
- Escribir las pruebas primero (Test First Development)
- la refactorización (Refactoring).
Los pasos serían:
- En primer lugar, se escribe una prueba y se verifica que la nueva prueba falla.
- A continuación, se implementa el código que hace que la prueba pase satisfactoriamente
- Seguidamente se refactoriza el código escrito.
El propósito del desarrollo guiado por pruebas es lograr un código limpio que funcione.
La idea es que los requisitos sean traducidos a pruebas; de este modo, cuando las pruebas pasen se garantizará que el software cumple con los requisitos que se han establecido.
Tener un único repositorio universal de pruebas facilita complementar TDD con otra práctica recomendada por los procesos ágiles de desarrollo: la integración continua. Integrar continuamente nuestro trabajo con el del resto del equipo de desarrollo permite ejecutar toda la batería de pruebas y así descubrir, si nuestra última versión es compatible con el resto del sistema.
Características de esta forma de programación:
- evita escribir código innecesario (YAGNI "You Ain't Gonna Need It")
- la generación de pruebas para cada funcionalidad hace que aumente la confianza del programador en el código escrito
El desarrollo guiado por el comportamiento (DGC) o behavior-driven development (BDD) es una práctica en la ingeniería de software que surgió a partir del desarrollo guiado por pruebas.
El desarrollo guiado por el comportamiento combina las técnicas generales y los principios del DGP, junto con ideas del diseño guiado por el dominio y el análisis y diseño orientado a objetos para proveer al desarrollo de software y a los equipos de administración de herramientas compartidas y un proceso compartido de colaboración en el desarrollo de software.1
Error, defecto y fallo
Señalada la importancia de las pruebas, vamos a clarificar algunos de los conceptos asociados más importantes: el error, el defecto y el fallo.
Una persona puede cometer un error, que conlleva la introducción de un defecto en el código o en otras áreas del desarrollo del producto. Cuando un defecto introducido en el código es ejecutado en un test, se produce un fallo
Son muchas las causas que pueden provocar un error:
- La presión del tiempo
- Falta de conocimientos o de experiencia
- Malentendidos en las comunicaciones del equipo
- Complejidad de la solución
- Errores en las Comunicaciones entre sistemas
- Error humano
- Nuevas tecnologías no suficientemente testadas
Niveles de testing
Test unitarios
Es la prueba que se realiza sobre la unidad más básica de nuestro código, métodos, funciones, clases, interfaces,...
Las pruebas unitarias son el método por el cual validamos que cada unidad desarrollada está lista para uso.
Los desarrolladores de software escriben estos casos de prueba para asegurar su funcionamiento en términos de diseño e implementación.
En ocasiones también los QAs pueden escribir estos casos de prueba, pero no es común.
Los test unitarios validan el correcto funcionamiento de la unidad más pequeña de código que utiliza nuestro software, por lo tanto lo que estamos consiguiendo es asegurar que para un conjunto de valores de entrada, nuestra función, método o clase devuelve el valor esperado.
Uno de los métodos utilizados es el de pruebas de caja blanca o TDD (Test Driven Development), entre otras, las cuales se detallaran más adelante.
Entre sus ventajas se encuentran:
- Los defectos aparecen temprano
- Ayuda a mantener el código
- Reduce el coste de solución
- Facilita las tareas de depuración
Hay que tener en cuenta que con su incremento pueden ralentizar los despliegues, y que su uso requiere concimiento: otra mentalidad al momento de escribir las pruebas, aprender el funcionamiento de la librería de pruebas, saber cómo trabajar con datos de prueba, saber abstraer/simplificar unas partes del sistema para poder escribir las pruebas, saber estructurarles, hacerlas resistentes al cambio y comprensibles, etc.
Test de integración
Un test de integración es aquel que combinando diferentes módulos prueba la comunicación entre ellos. Por ejemplo, comunicaciones:
- Interfaz -> BBDD
- Interfaz -> API
- Interfaz -> Interfaz
Como estos sistemas ya tienen sus pruebas unitarias pasadas, los fallos detectados están realacionados con la interoperabilidad y la comunicación entre los mismos.
Normalmente cada equipo, o cada miembro de un equipo, desarrolla una parte del software. Por lo que, deben acordar, por ejemplo el paso de parámetros, o si tenemos que trabajar con una API de terceros, tendremos que seguir lo acordado en el juego de petición respuesta. Uno de los métodos utilizados es el de pruebas de caja negra, caja blanca o caja gris, entre otras, las cuales se detallaran más adelante.
Suelen ser también los desarrolladores los que escriben estos test en fases tempranas del desarrollo, cuando todavía no se implica al QA. Sin embargo, otra práctica habitual, es la de contratar a una empresa tercera especializada en pruebas.
Entre las estrategias de integración, podemos indicar las siguientes:
- Big bang
- Top down
- Bottom up
- Hibrido / sandwich
Test de sistemas
Las pruebas de sistema implican las pruebas del sistema al completo, desde que una acción es activada en el producto hasta que acaba.
De esta manera con todos los elementos integrados comprobaremos si el sistema al completo funciona como se espera o no.
Son los QAs especializados, o independientes, los que diseñan y ejecutan estos casos de prueba.
Los tipos de pruebas se pueden clasificar en funcionales y no funcionales.
Entre sus ventajas:
- No es necesario tener ningún conocimiento de cómo se ha desarrollado el código.
- Reduce los errores post-despliegue
- Valoración de la experiencia de usuario
- Multidisciplinar
- Testing de navegación (Exploratory Testing)
- Entornos para reproducir incidencias
- Se prueban Arquitectura y Requisitos
Test de aceptación
Son las pruebas que se realizan sobre el producto final, si no en el entorno final, en uno practicamente igual.
Esta es la fase en la que el cliente decide el GO/NO GO del producto a un entorno productivo. Es el último paso para finalizar la entrega del producto al cliente.
Entre los objetivos de las pruebas de aceptación se encuentran:
- Ganar confianza en el producto
- Conseguir el OK para el paso a producción
- Conseguir la aceptación del cliente de que lo que se ha diseñado y aprobado en las fases anteriores es realmente lo que el cliente pedía
- Asegurar que el producto sigue los estándares de mercado (Lo prueban diferentes perfiles)
- Comparar el producto con otros similares del mercado
Algunos de los tipos de test de aceptación son:
- UAT (User Acceptance Testing)
- BAT (Business Acceptance Testing)
- CAT (Contract Acceptance Testing)
- RAT (Regulations / Compliance Acceptance Testing)
- OAT (Operational Acceptance Testing)
- Alfa testing
- Beta testing
Tipos de prueba
Funcionales
En ellas se comprueba lo que el sistema hace. La funcionalidad puede estar descrita en:
- Requerimientos
- Especificaciones funcionales
- Casos de uso
- No estar documentadas
Suelen estar relacionadas con las pruebas de caja negra.
Subclasificación según su ejecución: manuales y automáticas
A su vez, según su ejecución, las pruebas funcionales se clasifican en manuales y automáticas.
Las pruebas manuales son las que ejecuta un tester como si fuese un usuario pero siguiendo una serie de pasos establecidos o test plan, diseñado en el análisis de los requisitos para garantizar que hace lo que debe (casos positivos), que no falla (casos negativos) y que es lo que se ha solicitado.
El tester realizará las acciones indicadas en cada step del caso de prueba comprobando que se cumple el resultado esperado.
Si el resultado es distinto al esperado, se reportará un defecto con todo detalle: descripción, datos utilizados, capturas de pantalla, etc. para facilitar la solución del defecto por parte de los desarrolladores.
Las pruebas funcionales automáticas son pruebas funcionales que se automatizan para "ahorrar tiempo de pruebas". El objetivo de las pruebas funcionales automáticas es comprobar que nada de lo probado con anterioridad ha dejado de funcionar como debería.
A partir de los casos de prueba de las pruebas manuales, se automatizan los casos de prueba que se repitan en las ejecuciones. Esos casos suelen ser los más importantes (happy flow) de los módulos o procesos de negocio "vitales" de la aplicación, es decir, los procesos que siempre tienen que funcionar y que bajo ningún concepto pueden fallar.
Para esa automatización, estos deben ser los pasos a seguir:
- Elegir la prueba
- Precondición
- Pasos
- Comprobaciones
- Reporte estado final
No funcionales
Consideran el “comportamiento externo” del sistema comprobando cómo responde en términos de estrés, escalabilidad, carga, seguridad, etc.
Pueden hacer referencia a estándares de calidad, como el conjunto de normas ISO/IEC 25000|SQuaRE, ISO 25000:2014. Esta norma proporciona una guía para el uso de las series de estándares internacionales llamados requisitos y Evaluación de Calidad de Productos Software (SQuaRE). La norma establece criterios para la especificación de requisitos de calidad de productos software, sus métricas y su evaluación, e incluye un modelo de calidad para unificar las definiciones de calidad de los clientes con los atributos en el proceso de desarrollo.
Podemos clasificar las pruebas no funcionales según el tipo de requisito no funcional que abarcan:
- Compatibilidad
- Seguridad
- Estrés
- Usabilidad
- Rendimiento
- Internacionalización y localización
- Escalabilidad
- Mantenibilidad
- Instalabilidad
- Portabilidad
Regresivas
Son cualquier tipo de pruebas de software con el objeto de descubrir errores (bugs), carencias de funcionalidad, o divergencias funcionales con respecto al comportamiento esperado del software, causados por la realización de un cambio en el programa.
Se evalúa el correcto funcionamiento del software desarrollado frente a evoluciones o cambios funcionales. El propósito de éstas es asegurar que los casos de prueba que ya habían sido probados y fueron exitosos permanezcan así. Se recomienda que este tipo de pruebas sean automatizadas para reducir el tiempo y esfuerzo en su ejecución.
Técnicas de prueba
Caja blanca
Las técnicas de pruebas de caja blanca analizan las estructuras internas, las estructuras de datos utilizadas, el diseño interno, la estructura de código y el funcionamiento del software.
En este tipo de pruebas el código es accesible por el probador, por lo que tiene que tener conocimientos de codificación para entenderlo y diseñar las pruebas correspondientes.
Comprueban:
- problemas de seguridad internos
- mala o inexistente calidad en las estructuras de código
- el flujo para cada input en el código
- resultado esperado
- funcionalidad de los bucles condicionales
- prueba de cada declaración, objeto y función de forma individual
Se realizan de forma iterativa siguiendo estos tres pasos:
- Entender el código fuente
- Crear los casos de prueba
- Ejecutar los casos de prueba
Cobertura
Habitualmente es impracticable realizar una prueba exhaustiva de todos los caminos de un programa. Por ello se han definido distintos criterios de cobertura lógica, que permiten decidir qué sentencias o caminos se deben examinar con los casos de prueba. Estos criterios son:
- Cobertura de Sentencias: Se escriben casos de prueba suficientes para que cada sentencia en el programa se ejecute, al menos, una vez.
- Cobertura de Decisión: Se escriben casos de prueba suficientes para que cada decisión en el programa se ejecute una vez con resultado verdadero y otra con el falso.
- Cobertura de Condiciones: Se escriben casos de prueba suficientes para que cada condición en una decisión tenga una vez resultado verdadero y otra falso.
- Cobertura Decisión/Condición: Se escriben casos de prueba suficientes para que cada condición en una decisión tome todas las posibles salidas, al menos una vez, y cada decisión tome todas las posibles salidas, al menos una vez.
- Cobertura de Condición Múltiple: Se escriben casos de prueba suficientes para que todas las combinaciones posibles de resultados de cada condición se invoquen al menos una vez.
- Cobertura de Caminos: Se escriben casos de prueba suficientes para que se ejecuten todos los caminos de un programa. Entendiendo camino como una secuencia de sentencias encadenadas desde la entrada del programa hasta su salida.
De las técnicas expuestas, profundizaremos en tres conceptos asociados a las pruebas del camino básico
Cobertura de Caminos
La aplicación de este criterio de cobertura asegura que los casos de prueba diseñados permiten que todas las sentencias del programa sean ejecutadas al menos una vez y que las condiciones sean probadas tanto para su valor verdadero como falso. Una de las técnicas empleadas para aplicar este criterio de cobertura es la Prueba del Camino Básico. Esta técnica se basa en obtener una medida de la complejidad del diseño procedimental de un programa (o de la lógica del programa). Esta medida es la complejidad ciclomática de McCabe, y representa un límite superior para el número de casos de prueba que se deben realizar para asegurar que se ejecuta cada camino del programa.
Los pasos a realizar para aplicar esta técnica son:
- Representar el programa en un grafo de flujo
- Calcular la complejidad ciclomática
- Determinar el conjunto básico de caminos independientes
- Derivar los casos de prueba que fuerzan la ejecución de cada camino.
Representar el programa en un grafo de flujo
El grafo de flujo se utiliza para representar flujo de control lógico de un programa. Para ello se utilizan los tres elementos siguientes:
- Nodos: representan cero, una o varias sentencias en secuencia. Cada nodo comprende como máximo una sentencia de decisión (bifurcación).
- Aristas: líneas que unen dos nodos.
- Regiones: áreas delimitadas por aristas y nodos. Cuando se contabilizan las regiones de un programa debe incluirse el área externa como una región más.
- Nodos predicado: cuando en una condición aparecen uno o más operadores lógicos (AND, OR, XOR, ...) se crea un nodo distinto por cada una de las condiciones simples. Cada nodo generado de esta forma se denomina nodo predicado. La figura muestra un ejemplo de condición múltiple:
Así, cada construcción lógica de un programa tiene una representación. La figura muestra dichas representaciones:
Cálculo de la complejidad ciclomática
La complejidad ciclomática es una métrica del software que proporciona una medida cuantitativa de la complejidad lógica de un programa. En el contexto del método de prueba del camino básico, el valor de la complejidad ciclomática define el número de caminos independientes de dicho programa, y por lo tanto, el número máximo de casos de prueba a realizar.
Dentro del contexto del método de pruebas del camino básico define el número de caminos independientes de un programa; se entiende como camino independiente aquel que introduce un nuevo conjunto de sentencias o una nueva condición. En términos del grafo, por una arista que no haya sido recorrida antes.
Formas de cálculo
Hay tres formas de realizar el cálculo de la complejidad ciclomática v(G):
1. El número de regiones del grafo es igual a la complejidad ciclomática.
V(G) = Nº de regiones
2. La complejidad ciclomática, V(G), de un grafo de flujo G se define como
V(G) = Aristas – Nodos + 2
3. La complejidad ciclomática, V(G), de un grafo de flujo G se define como
V(G) = Nodos Predicado + 1
Determinar el conjunto básico de caminos independientes
Un camino independiente es cualquier camino del programa que introduce, por lo menos, un nuevo conjunto de sentencias de proceso o una condición, respecto a los caminos existentes. En términos del diagrama de flujo, un camino independiente está constituido por lo menos por una arista que no haya sido recorrida anteriormente a la definición del camino. En la identificación de los distintos caminos de un programa para probar se debe tener en cuenta que cada nuevo camino debe tener el mínimo número de sentencias nuevas o condiciones nuevas respecto a los que ya existen. De esta manera se intenta que el proceso de depuración sea más sencillo.
El conjunto de caminos independientes de un grafo no es único. No obstante, a continuación, se muestran algunas heurísticas para identificar dichos caminos: (a) Elegir un camino principal que represente una función válida que no sea un tratamiento de error. Debe intentar elegirse el camino que atraviese el máximo número de decisiones en el grafo.
(b) Identificar el segundo camino mediante la localización de la primera decisión en el camino de la línea básica alternando su resultado mientras se mantiene el máximo número de decisiones originales del camino inicial.
(c) Identificar un tercer camino, colocando la primera decisión en su valor original a la vez que se altera la segunda decisión del camino básico, mientras se intenta mantener el resto de decisiones originales.
(d) Continuar el proceso hasta haber conseguido tratar todas las decisiones, intentando mantener como en su origen el resto de ellas.
Este método permite obtener V(G) caminos independientes cubriendo el criterio de cobertura de decisión y sentencia.
Derivar los casos de prueba que fuerzan la ejecución de cada camino
El último paso es construir los casos de prueba que fuerzan la ejecución de cada camino. Una forma de representar el conjunto de casos de prueba es como se muestra en la tabla:
Número del camino | Caso de prueba | Resultado esperado |
---|---|---|
Otras técnicas
Otras técnicas conocidas son:
Técnica | Descripción |
---|---|
Prueba de interfaz | Debe ser la primera a realizar. Se basa en analizar el flujo de datos que pasa a través de la interfaz del módulo, tanto externa como interna, para asegurar que la información fluye de forma adecuada tanto hacia el interior como hacia el exterior del módulo que se está probando. |
Pruebas de estructuras de los datos locales | Tienen como objetivo asegurar la integridad de los datos durante todos los pasos de la ejecución del módulo |
Prueba del camino básico | Permite obtener una medida de la complejidad lógica de un programa (complejidad ciclomática) y utilizar esa medida como guía para definir un conjunto básico de caminos de ejecución. Es decir, la prueba del camino básico se orienta a cubrir la ejecución de cada una de las sentencias, cada una de las decisiones y cada una de las condiciones en las decisiones, tanto en su vertiente verdadero como falsa. |
Prueba de bucles | Comprueban la validez de las construcciones de los bucles. |
Prueba de bucles
Profundizaremos un poco más en esta técnica que se centra en la validez de las construcciones de los bucles, ya que son estos la piedra angular de la inmensa mayoría de los algoritmos implementados en software.
Se pueden definir cuatro tipos de bucles diferentes:
- Bucles simples
- Bucles concatenados
- Bucles anidados
- Bucles no estructurados.
Bucles Simples:
A los bucles simples (de n iteraciones) se les tiene que aplicar el conjunto de pruebas siguientes:
- Saltar el bucle
- Pasar sólo una vez por el bucle
- Pasar dos veces por el bucle
- Hacer m pasos del bucle con m < n
- Hacer n-1, n y n+1 pasos por el bucle
Bucles Anidados
Si extendiésemos el conjunto de pruebas de los bucles simples a los bucles anidados, el número de pruebas crecería geométricamente, por lo que Beizer sugiere el siguiente conjunto de pruebas para bucles anidados:
- Comenzar con el bucle más interno, estableciendo los demás bucles a los valores mínimos
- Llevar a cabo las pruebas de bucles simples para el bucle más interno, conservando los valores de iteración de los bucles más externos a los valores mínimos
- Progresar hacia fuera en el siguiente bucle más externo, y manteniendo los bucles más externos a sus valores mínimos
- Continuar hasta que se hayan probado todos los bucles
Bucles Concatenados
Existen dos situaciones
- Si cada bucle es independiente del resto: Probar los bucles concatenados mediante las técnicas de prueba para bucles simples considerándolos como bucles independientes.
- Si un bucle es dependiente de otro(por ejemplo contador del bucle 1 se usa como valor inicial del bucle 2) utilizar el mismo enfoque de bucles anidados
Bucles No Estructurados
Es necesario rediseñar estos bucles para que se ajusten a las construcciones de la programación estructurada.
Caja negra
Se define como una técnica de prueba en la que la funcionalidad de la aplicación bajo prueba, se prueba sin tener en cuenta la estructura del código interno, los detalles de implementación y el conocimiento de las estructuras internas del software. Este tipo de pruebas se basa completamente en los requisitos y especificaciones del software
Técnica | Descripción |
---|---|
Dirigidas por la sintaxis | Usada para examinar el formato y la gramática de los datos de entrada para realizar validaciones |
Partición de equivalencia | Consiste en dividir el dominio de entrada de un programa en clases de equivalencia de los que se pueden derivar casosde prueba, donde la prueba de un valor representativo de la misma sea extrapolable al que se conseguiría probando cualquier valor de la clase. |
Análisis de valores límite | Se elegirán como valores de entrada aquellos que se encuentra en el límite de las clases de equivalencia. Si una condición para un dato de entrada i especifica un rango de valores definido como n <= i <= m, los casos de prueba resultantes de aplicar el análisis de valores límite corresponden a n-1, n, n+1, m-1, m y m+1. Se justifica en la constatación de que para una condición de entrada que admite un rango de valores es más fácil que existan errores en los límites que en el centro. "Los errores se esconden en los rincones y se aglomeran en los límites” [Beizer]. |
Grafos causa efecto | Permite al encargado de la prueba validar complejos conjuntos de acciones y condiciones. |
Pruebas de Casos de uso | Técnica de diseño de prueba de caja negra en la que los casos de prueba están diseñados para ejecutar escenarios de usuario. |
Caja blanca vs caja negra
Caja blanca | Caja negra | |
---|---|---|
¿Qué valida? | La estructura interna y el funcionamiento del código | Los requisitos funcionales |
Respecto al conocimiento del código.... | El conocimiento del lenguaje de programación subyacente es esencial | Proporcionan abstracción del código y se centran en el esfuerzo de probar el comportamiento del sistema de software |
Sobre la comunicación... | No facilitan la comunicación de pruebas entre los módulos | Facilitan la comunicación de pruebas entre los módulos |
Basadas en la experiencia - Alfa y beta testing
El Alpha Testing es un tipo de prueba de aceptación; se realiza para identificar todos los posibles problemas/errores antes de lanzar el producto a los usuarios o al público en general.
El objetivo de esta prueba es simular usuarios reales utilizando técnicas de Caja Negra y Caja Blanca. El objetivo es llevar a cabo las tareas que un usuario típico podría realizar.
El Beta Testing es la segunda fase del Software Testing en la que una muestra de la audiencia objetivo prueba el producto. Las pruebas beta de un software son realizadas por usuarios reales de la aplicación en un entorno real.
Tipo de Beta Testig | Descripción |
---|---|
Tradicionales | El producto se distribuye al mercado objetivo, y los datos relacionados se recopilan en todos los aspectos. Estos datos pueden ser utilizados para mejorar el producto. |
Públicas | El producto se da a conocer públicamente al mundo exterior a través de canales en línea y los datos se pueden obtener de cualquier persona |
Ensayos Técnicos | El producto se entrega al grupo interno de una organización y recoge los comentarios y datos de los empleados de la organización. |
Enfocada | El producto se lanza al mercado para recabar información sobre las características específicas del programa |
Post-Lanzamiento | El producto se lanza al mercado y se recopilan datos para hacer mejoras para el futuro lanzamiento del producto |
Se puede ver una comparativa sobre las características del alfa y beta testing en la siguiente tabla:
Alfa | Beta | |
---|---|---|
Entorno | Interno | Del cliente |
Equipos implicados | Analistas de negocio y desarrolladores | Solamente el cliente final está implicado en las pruebas y en el reporte |
Conocimientos | Equipo altamente cualificado en calidad | Pueden ser usuarios finales ingenuos o competentes del producto |
Caja | Blanca y negra | Negra |
Cuando se realizan | Antes del lanzamiento de un producto de software al mercado | En el momento de la comercialización del producto de software |
Objetivo | Asegurar la calidad del producto | Además recogen las opiniones de los usuarios sobre el producto y aseguran que este está listo para los usuarios en tiempo real |
Fiabilidad y seguridad | No se realizan pruebas de fiabilidad y seguridad | Pruebas de fiabilidad, seguridad y robustez |
Sobre el tiempo de ciclo | Puede ser necesario un ciclo de ejecución largo | Sólo se requieren unas pocas semanas de ejecución |
Sobre cuándo se resuelven los problemas | Los problemas críticos o correcciones pueden ser resueltos por los desarrolladores inmediatamente | La mayoría de los problemas o comentarios que se recogen se implementarán en futuras versiones del producto |
Organización de los casos de prueba y herramientas para su gestión
Es necesario organizar los casos de prueba para:
- Facilitar la comprensión del proyecto, desde un punto de vista de las pruebas.
- Comprender la funcionalidad y la prioridad fácilmente
- Facilitar las regresiones, completas o parciales
- Aumentar la calidad
- Facilitar la escalabilidad del proyecto
Algunos conceptos
Para esa organización, surgen algunos conceptos que deben ser clarificados:
- Plan test:
- Build:
- Test suite:
- Test case:
Conclusiones
Se ha presentado una visión global de las tareas de prueba y documentación ya que son de vital importancia durante el desarrollo de software.
Las pruebas buscan verificar que el software que se está creando es correcto y cumple con las especificaciones impuestas por el usuario, garantizando así la calidad del producto entregado.
Y por otra parte, una correcta documentación durante el desarrollo de software influirá también positivamente en la calidad del software, su utilización, soporte y posterior mantenimiento y evolución.
Anexo I - Herramientas Software para la realización de pruebas
Se presenta a continuación una tabla con varias herramientas que permiten la gestión y automatización de ciertos tipos de pruebas de software
Tipo de prueba | Herramienta | Lenguajes | Comentario |
---|---|---|---|
Unitaria | JUnit 5 | Java | |
Mocha | Javascript | Test framework que corre en Node.js y en el navegador | |
PHPUnit | PHP | La versión 10 está en desarrollo | |
NUnit | .NET | ||
PyUnit | Python | ||
BDD | Behat | PHP | Framework libre de Behavior-Driven Development para PHP |
Cucumber | Herramienta utilizada para ejecutar pruebas de aceptación automáticas creadas en formato BDD. Destaca su capacidad de llevar a cabo descripciones funcionales de texto sin formato (escritas en un lenguaje llamado Gherkin) como pruebas automatizadas. | ||
Chai | Javascript | ||
Karma | Javascript | ||
Funcional y de regresión | Selenium | ||
Cypress | Framework de pruebas todo en uno que facilita la integración continua | ||
Integración | SoapUI | Aplicación de prueba de API para tecnologías SOAP y REST, permite también pruebas funcionales y de rendimiento | |
Postman | Utilizada principalmente para el testing de API REST | ||
Carga y rendimiento | Apache JMeter | ||
Gatling | Herramienta para pruebas de estrés | ||
LoadRunner | |||
Aceptación | FitNesse | Herramienta de automatización de test de aceptación mediante su documentación en wiki | |
Concordion | Framework orientado al desarrollo de tests de aceptación. Funciona a través de tests escritos en HTML | ||
Acunetix | Software de pruebas automáticas de seguridad web | ||
Nessus | Programa de escaneo de vulnerabilidades que permite agilizar pruebas de seguridad | ||
Gestión | TestLink | ||
TestRail | |||
Practitest | |||
Múltiples | Codeception | PHP | Permite realización de pruebas unitarias, integración, aceptación, BDD.... |
TestNG | Java | Framework para pruebas y testing que. Está basado en JUnit (para Java) y NUnit (para .NET) pero introduciendo nuevas funcionalidades que los hacen más poderosos y fáciles de usar. | |
Android Studio | Kotlin (tambien Java y C++) | Entorno de desarrollo integrado oficial para la plataforma Android, que también facilita el proceso de pruebas |
Anexo II - Ejemplos de técnicas de prueba
Mediante tres pequeños ejemplos veremos algunas técnicas de prueba
Ejemplo 1: Días de la semana en formato numérico
- La condición de entrada reflejaría que sólo se podrían introducir números del 1 al 7, ambos inclusive. Identificaríamos 2 clases:
- Clase válida: 1 <= día <= 7
- 2 clases no válidas: una cuando día < 1 y otra para día > 7
Ejemplo 2: Colores RGB en formato String minúscula
- El valor de entrada sólo puede corresponder a uno de los colores RGB escrito en minúscula: «red», «green», «blue». Se supone que cada una de esas entradas se debería manejar de formas distintas en el programa.
- 3 clases de equivalencia válidas, una para cada uno de los valores de entrada «red», «green» y «blue».
- Una clase inválida que incluiría aquellos colores no especificados en la condición.
Ejemplo 3: Nombre con primera letra con mayúscula
- Clase válida para cadenas cuya primera letra es una mayúscula (se cumple la condición)
- Clase no válida para valores que no cumplen la condición: cadenas que comienzan en minúscula.
Partición de equivalencia
En forma de tabla, estas serían las particiones de equivalencia para los tres ejemplos anteriores:
Entrada | Tipo | Clases Válidas | ID | Clases no Válidas | ID |
---|---|---|---|---|---|
Día de la semana | Rango | 1 <= día <= 7 | v_dia | día < 1 | nv_dia_menor |
día > 1 | nv_dia_mayor | ||||
Colores | Conjunto | color = "red" | v_color_r | color distinto de los válidos | nv_color |
color = "green" | v_color_g | ||||
color = "blue" | v_color_b | ||||
Nombre de usuario | Condición lógica | Empieza por mayúscula | v_mayúscula | No empieza por mayúscula | nv_mayúscula |
Análisis de valores límite
En el ejemplo 1 anterior, deberíamos definir el rango de valores válidos como: 1 <= día <= 7. En ese caso, los casos de prueba resultantes a aplicar serían 0, 1, 2, 6, 7 y 8.
Caminos básicos y complejidad ciclomática
Bucles y cobertura
Anexo III - Ejemplos de estrategias de integración
Supongamos un ejemplo con los siguientes módulos:
Estas serían las opciones para la realización de pruebas de integración.
Descendente, de arriba a abajo o top-down
- El primer componente que se desarrolla y prueba es el primero de la jerarquía (A).
- Los componentes de nivel más bajo se sustituyen por componentes auxiliares para simular a los componentes invocados.
- En este caso no son necesarios componentes conductores.
- Una de las ventajas de aplicar esta estrategia es que las interfaces entre los distintos componentes se prueban en una fase temprana y con frecuencia.
Ascendente, de abajo a arriba o bottom-up
- En este caso se crean primero los componentes de más bajo nivel (E, F) y se crean componentes conductores para simular a los componentes que los llaman. * A continuación se desarrollan los componentes de más alto nivel (B, C, D) y se prueban.
- Por último dichos componentes se combinan con el que los llama (A).
- Los componentes auxiliares son necesarios en raras ocasiones.
- Este tipo de enfoque permite un desarrollo más en paralelo que el enfoque de arriba abajo, pero presenta mayores dificultades a la hora de planificar y de gestionar.
Sandwich, híbridas o combinadas
- A menudo es útil aplicar las estrategias anteriores conjuntamente.
- De este modo, se desarrollan partes del sistema con un enfoque «top-down«, mientras que los componentes más críticos en el nivel más bajo se desarrollan siguiendo un enfoque «bottom-up«.
- En este caso es necesaria una planificación cuidadosa y coordinada de modo que los componentes individuales se «encuentren» en el centro.
Big-Bang (gran explosión)
- Esta última sería no incremental.
- Se prueba cada componente por separado y posteriormente se integran todos de una vez realizando las pruebas pertinentes.
Anexo IV - Ejemplo de caso de prueba unitario con JUnit
Ejemplo de clase Calculadora con un método suma que devuelve como float la suma de dos parámetros de entrada float public class Calculator { float add(float a, float b) { return a + b; }
Caso de prueba para método add valida que 1 + 1 = 2 class MyFirstCalculatorTest { private final Calculator calculator = new Calculator(); @Test void additionTest() { assertEquals(2, calcultaor.add(1,1), "La salida debe ser la suma de los dos argumentos: 1 +1 = 2"); } }
Anexo V - Herramientas Software para la documentación
Herramienta | Comentario | |
---|---|---|
Atlassian Confluence | Módulo de Jira que permite documentar los how-to y las referencias técnicas llegando a asociar Ticket de Jira - Documentación de código – Rama de Git (o Subversion). | |
Read the Docs | Plataforma gratuita para el alojamiento de documentación de software con código fuente; facilita la redacción de documentación técnica al automatizar la creación y el control de versiones. | |
Huddle | Centro de colaboración todo-en-uno para los equipos. Utilizado por empresas grandes que necesitan herramientas estar sincronizadas, incluidos el almacenamiento de archivos, la gestión de proyectos y las herramientas de colaboración. | |
Sphinx | Software generador de documentación que convierte ficheros reStructuredText en sitios web HTML y otros formatos, incluyendo PDF, EPub y man | |
Markdown | Lenguaje de marcado ligero que trata de conseguir la máxima legibilidad y facilidad de publicación tanto en su forma de entrada como de salida |
Herramienta | Comentario |
---|---|
Javadoc | Permimte generar documentación de API en formato HTML desde el código fuente de Java. |
phpDoc | Es una adaptación de javadoc para php que define un estándar oficial para comentar código php. |
Swagger | Conjunto de herramientas de software de código abierto para diseñar, construir, documentar, y utilizar servicios web RESTful. Fue desarrollado por SmartBear Software e incluye documentación automatizada, generación de código, y generación de casos de prueba |
Anexo VI - Ejemplo de documentación con JavaDoc
/** * Una clase para representar círculos situados sobre el plano. * Cada círculo queda determinado por su radio junto con las * coordenadas de su centro. * @version 1.2, 03/02/21 * @author José López Villar */ public class Círculo { protected double x,y; // coordenadas del centro protected double r; // radio del círculo /** * Crea un círculo a partir de su origen su radio. * @param x La coordenada x del centro del círculo. * @param y La coordenada y del centro del círculo. * @param r El radio del círculo. Debe ser mayor o igual a 0. */ public Circulo(double x, double y, double r) { this.x=x; this.y = y; this.r = r; } /** * Cálculo del área de este círculo. * @return El área (mayor o igual que 0) del círculo. */ public double área() { return Math.PI*r*r; }
Anexo VII - Normas IEEE relacionadas con el software, su calidade, documentación y pruebas
Herramienta | Comentario |
---|---|
Google Analytics | Permite el análisis de CTR, Tasa de rebote, tiempo en página, etc. |
hotjar | Permite comprender como los usuarios experimetan y evalúan la documentación analizando su comportamiento mediante encuestas y NPS |
Estándar | Nombre de la norma |
---|---|
IEEE 730 | Planes de aseguramiento de la calidad del software. |
ISO/IEC/IEEE 29119 | Estándar de pruebas aplicable a todo tipos de sistemas y productos software. Cinco partes (Conceptos, procesos, documentación, Técnicas de prueba y Pruebas dirigidas por palabras clave). Reemplaza al estándar de documentación de pruebas de software IEEE 829 |
IEEE 982.1 | Diccionario estándar de medidas para producir software fiable. |
IEEE 982.2 | Guía para el uso del diccionario estándar de medidas para producir software fiable. |
IEEE 1008 | Probas unitarias de software. |
IEEE 1012 | Verificación y validación de software. |
IEEE 1028 | Revisiones de software. |
IEEE 1044 | Clasificación estándar para anomalías do software. |
IEEE 1061 | Estándar para una metodología de métricas de calidad del software. |
IEEE 1228 | Planes de seguridad del software |
ISO/IEC 25010 | Modelo de calidad del producto compuesto por ocho características |
Bibliografía
- Pressman, R. S. Ingeniería del Software: Un enfoque práctico. Editorial McGraw-Hill
- Sommerville, I. Ingeniería del software. Editorial Addison Wesley
- Norma ISO/IEC/IEEE 29119(Estándar para pruebas del software).
- Métrica versión 3. Metodología de planificación, desarrollo y mantenimiento de sistemas de información. Ministerio para las Administraciones Públicas.
- International Software Testing Qualifications Board
- Ammann, P., & Offutt, J. (2016). Introduction to Software Testing (2.ª ed.). Cambridge University Press. Cambridge University Press.
Referencias
- Curso de introducción al testing en OpenWebinars
- ¿Qué es un tester de software?
- Qué es y para qué sirve el Testing de Software
- Por qué hacer Testing de Software en el Desarrollo de Apps
- Tipos de prueba software
- https://www.preparadorinformatica.com/images/pdf/Tema-30.pdf
- Software Testing Dictionary
- https://www2.infor.uva.es/~jvalvarez/docencia/tema7.pdf
- Curso básico sobre testeo de software
- http://www.lsi.us.es/docencia/get.php?id=361
- http://www.lsi.us.es/~javierj/cursos_ficheros/05.SR.pdf
- https://manuel.cillero.es/doc/metodologia/metrica-3/tecnicas/pruebas/integracion/
- https://educandocontic.com/entornos-de-desarrollo/
- https://es.itpedia.nl/2018/07/20/stlc-software-testing-life-cycle/
- Testing a través del ciclo de vida del software – I
- https://trans-ti.com/2021/01/11/software-testing-conoce-el-ciclo-de-vida-de-las-pruebas-de-software/
- ISO/IEC/IEEE 29119 El nuevo estándar internacional para pruebas de software
Libros
JUnit
- http://www.chuidiang.org/java/herramientas/test-automaticos/ejemplo-junit.php
- http://www.jtech.ua.es/j2ee/publico/lja-2012-13/sesion04-apuntes.html
- https://www.vogella.com/tutorials/JUnit/article.html
- https://www.tutorialspoint.com/junit/index.htm
- https://www.adictosaltrabajo.com/2016/11/24/primeros-pasos-con-junit-5/
- https://junit.org/junit5/docs/current/user-guide/