Testing combinatorio Para comprender mejor esta lección es importante repasar la lección Cubrimiento y la sección Modelar la realidad con variables de la lección Modelos. En esta sección enunciábamos por ejemplo el siguiente criterio de cubrimiento: Cubrir en profundidad una funcionalidad significa que todos los valores posibles de cada variable sean utilizados en algún caso de prueba. Sin embargo, si reflexionamos un poco, podemos verificar que es un criterio muy leve, ya que cada valor posible de cada variable sólo estaría combinado una única vez con algunos de los valores posibles de las otras variables. Cuando tenemos varias variables y utilizamos la técnica de clases de equivalencia se procede de la siguiente forma: Se parte el dominio de cada variable en clases de equivalencia Para diseñar los casos de prueba o Se combinan la mayor cantidad de representantes de clases válidas en un caso de prueba o Se crea un caso de prueba por cada clase inválida combinando su representante con representantes de clases válidas de las otras variables El criterio de cubrimiento, en este caso, es cubrir todas las clases de equivalencia de cada variable y no cubrir combinaciones de valores posibles. El número a lo sumo variables. valores de casos de prueba que cubren las clases de equivalencia válidas es igual al número máximo de clases válidas que tengan las distintas Puede suceder por lo tanto, que omitamos combinaciones de interesantes a los efectos de detectar incidentes. Si el énfasis se pone en cubrir con determinado criterio las combinaciones de valores posibles, estamos hablando de Testing Combinatorio. Continuando la reflexión Si combinar los valores posibles de cada variable con valores posibles de las otras variables al menos una vez, nos resulta insuficiente, entonces podríamos intentar todas las combinaciones posibles, o sea cada valor posible de cada variable con todos los valores posibles de las otras variables. Supongamos que tenemos un producto configurable (como actualmente lo son la enorme mayoría) mediante la asignación de valores a 10 variables (muy pocos si los comparamos con la realidad). Cada variable tiene 10 valores posibles. Calculemos todas las combinaciones posibles: 10*10*10*…*10 = 1010 = 10.000.000.000 Obtendríamos una cantidad de casos de prueba imposible de ejecutar manualmente. Téngase en cuenta que para diseñar los casos de prueba no alcanza con la combinación de valores sino que tenemos que pensar además, en los resultados esperados para cada combinación. ¡Ímproba tarea! Por otra parte, probablemente muchos de estos resultados sean iguales, o sea que los casos de prueba serían redundantes, no aportarían valor a las pruebas. O dicho de otra manera serían casos de prueba equivalentes, cuyos valores de entrada pertenecen a las mismas clases de equivalencia. Recordemos que el diseño de casos de prueba es un desafío para lograr simultáneamente: • Un número lo más reducido posible de casos • Un cubrimiento lo más amplio posible ¿Cómo procedemos entonces? Combinación por pares Esta técnica se basa en la conjetura de que muchos incidentes se producen cuando interactúan ciertos pares de valores posibles de dos variables independientes entre sí. La técnica Combinación por pares (all pairs) permite generar un conjunto de casos de prueba en el cual estén representados, al menos una vez, todos los pares de valores posibles de las variables identificadas. Los incidentes que podemos detectar con esta técnica son de tipo singular (single) o doble (double): Singular – Pueden detectarse incidentes porque una variable toma un cierto valor Doble – Pueden detectarse incidentes por la combinación de ciertos valores de 2 variables Si aplicáramos esta técnica al caso de las 10 variables con 10 valores posibles obtendríamos 177 casos de prueba. A continuación veremos cómo obtener manualmente combinaciones que contengan todos los pares de valores posibles de las variables identificadas. Luego veremos herramientas que asisten al diseñador para generar las combinaciones por pares. Ejemplo Supongamos que un producto de software maneja las siguientes variables: Género: Femenino, Masculino Nacionalidad: Uruguaya, Argentina, Otra Estado civil: Soltero, Casado, Otro Es muy importante destacar la independencia entre las variables. El género de una persona es totalmente independiente de su nacionalidad y de su estado civil. Calculemos todas las combinaciones aplicando el producto cartesiano de los valores posibles: 2*3*3 = 18 A continuación veremos todas las posibles combinaciones de estas variables. Ahora tratemos de generar todas las combinaciones por pares. Tomemos por ejemplo la variable Género. Si aplicamos la técnica de combinación por pares sus valores posibles se tienen que combinar con todas las Nacionalidades y Estados civiles, al menos una vez. Construyamos las tablas correspondientes y luego apliquemos un posible algoritmo, manualmente, para obtener el conjunto deseado. Tomamos un par inicial y a partir de él escribimos los valores de entrada para un posible caso de prueba y lo coloreamos con naranja en nuestras tablas: Femenino, Uruguaya, Soltero Luego tomamos otros pares que aún no hayamos visitado, y los coloreamos de azul, por ejemplo: Femenino, Argentina, Otro Y así seguimos tomando pares no visitados y combinándolos hasta que todos los pares estén considerados por lo menos una vez en el conjunto obtenido. Tomamos entonces y los coloreamos de gris: Femenino, Otra, Soltero ¡Uups, sí, tienen razón! El par Femenino, Soltero ya fue visitado y coloreado de naranja. Probemos entonces con: Femenino, Otra, Casado Ni Femenino, Otra, ni Femenino, Casado, ni Otra, Casado habían sido visitados. Representamos en una tabla las combinaciones que vamos obteniendo: Femenino ya lo combiné con todas las nacionalidades y todos los estados civiles. Prosigo con Masculino entonces y coloreo de marrón: Masculino, Uruguaya, Soltero. ¡Uups, sí, tienen razón! El par Uruguayo, Soltero ya fue visitado y coloreado de naranja. Probamos entonces: Masculino, Uruguaya, Casado y verifico que ninguno de los pares fue visitado aún. Proseguimos Proseguimos con: con: Masculino, Masculino, Argentina, Otra, Soltero Otro Hasta el Ahora tengo momento que tenemos ver qué las siguientes pares quedaron combinaciones: sin combinar. Todos los demás pares ya fueron visitados, o sea, que podemos tomar cualquier valor de la variable Género para las combinaciones faltantes y la representamos con el símbolo “~”. Elegimos la que consideremos que por alguna razón tiene más probabilidades de detectar un incidente. ¿Por qué quedaron al final pares sin visitar para algunas de las variables? Porque las variables no tienen el mismo número de valores posibles y las tablas correspondientes tienen largos diferentes. Contraejemplo Un sistema para consultas del estado de expedientes existentes implementa la funcionalidad de búsqueda de expedientes a través de un sitio web. El sistema requiere un número de expediente y despliega los estados por los que ha pasado y la resolución tomada. Se identificaron las siguientes variables y valores válidos para la funcionalidad de búsqueda: Origen expediente: Montevideo, otros departamentos Algún paso: Si, No Año: < 2000, >=2000 Estado: Iniciado, En trámite, Finalizado El sistema podría fallar, y no devolver los datos correspondientes, para expedientes ingresados en Montevideo antes del 2000, que tengan algún paso y que estén en estado en trámite. Sin embargo los casos de prueba generados con la técnica de todos los pares pueden no considerar esta combinación de los valores de 4 variables. Este incidente sólo podría haber sido detectado si hubiéramos combinado los valores “de a 4”, por lo menos. Quizás las variables no son tan independientes. O sea podríamos combinar los valores de las variables en triplas, cuádruplas, quíntuplas…, n_tuplas, y obtener un mayor cubrimiento de combinaciones de valores posibles. La gran diferencia es que existen varias herramientas para generar automáticamente las combinaciones por pares entre varias variables con varios valores posibles cada una, y relativamente pocas herramientas que generen combinaciones de n_tuplas o todas las combinaciones. Además, en estos casos los algoritmos utilizados pueden ser muy costosos en recursos (tiempo, recursos informáticos). Y resta el problema de agregar los resultados esperados… Por lo tanto, en la realidad, lo que recomendamos hacer es abordar primero la generación de combinaciones por pares y luego pensar qué otras combinaciones de 3, 4,…n valores posibles sería indispensable probar en ese contexto. En la presentación “Combinación por pares” podrán apreciar otros ejemplos, en uno de los cuales se plantea el tema de las restricciones. Resumen Luego de ver los ejemplos de la presentación podemos evaluar la técnica y resumir sus ventajas y limitaciones. Ventajas Si modelamos la realidad identificando un número importante de variables con varios valores posibles e independientes entre sí es recomendable comenzar el diseño generando las combinaciones por pares Existen muchas herramientas que asisten al diseñador para generar las combinaciones por pares Se garantiza así el cubrimiento de todos los pares de valores posibles No implica “trabajo extra” y es un buen punto de partida, porque siempre tenemos que identificar las variables involucradas y sus posibles valores. Limitaciones y riesgos Solamente se garantiza el cubrimiento de pares y podrían no detectarse incidentes que se producen por la interacción de un número mayor de valores posibles Podría no generarse alguna combinación importante o frecuentemente ejecutada Algunas variables aparentemente independientes en un primer momento, podrían sin embargo presentar valores posibles dependientes (como en el caso de los sistemas operativos y los navegadores del ejemplo) y pueden, por lo tanto, generarse combinaciones inválidas Pasos a seguir Identificar variables, dominios y valores posibles o Pueden nuevamente surgir dominios en los que sea necesario aplicar primero clases de equivalencia Generar las combinaciones por pares Analizar combinaciones inválidas Considerar combinaciones particulares Finalmente, veamos cómo podemos enmarcar la técnica de combinación por pares en la concepción general de las técnicas de diseño de casos de prueba que adoptamos: Modelo de la realidad o Variables independientes con varios valores posibles Estrategia de selección o Algoritmos para utilizar cada par de valores al menos una vez en una combinación de valores posibles Criterio de cubrimiento o Todos los pares de valores Teoría de errores o Los errores más típicos son de tipo singular (single) o doble (double) Herramientas Existen varias herramientas que generan casos de pruebas con esta técnica. Mencionamos algunas a modo de ejemplo: ALLPAIRS Test Case Generation Tool o http://tejasconsulting.com/opentestware/feature/allpairs.html Pict Classification Tree Editor CTE CombTestWeb o http://alarcosj.esi.uclm.es/CombTestWeb/ En particular esta última herramienta, desarrollada por el grupo Alarcos de la Escuela de Informática de la Universidad de Castilla-La Mancha, genera además de combinaciones por pares, otras combinaciones, como por ejemplo tomadas al azar, o todas las combinaciones posibles. Tiene también una opción Customizable pairwise (exponential cost), o sea, combinación por pares personalizada que permite restringir los valores de pares inválidos y ponderar los pares más frecuentes o más riesgosos para que se generen más combinaciones que los contengan.