RACCIS, 4(1), 13-20, 2014 Revista Antioqueña de las Ciencias Computacionales y la Ingeniería de Software ISSN: 2248-7441 www.fundacioniai.org/raccis raccis@fundacioniai.org Analysis to design test cases Análisis al diseño de casos de prueba Isabella Locarti1, Francesco Unguillo2 KOAN SAS. locartii(AT)koansoftware.com1, unguillof(AT)koansoftware.com2 INFORMACIÓN DEL ARTÍCULO Tipo Reflexión Historia Recibido: 02-02-2014 Correcciones: 12-06-2014 Aceptado: 16-06-2014 Keywords Design, quality, scenarios, test cases, test plan. Palabras clave Casos de prueba, calidad, diseño, escenarios, plan de pruebas. ABSTRACT Test the software is a necessary question in the process to achieve reliability, safety and quality of products, but most testers not aware of the importance of this activity. This article makes a reflection about this topic, and are described some myths and realities of the design and implement test cases. Parts of the concept that software testing should be viewed and applied as a parallel phase the entire product life cycle, and not leave it to the end as an imposition before delivery. Furthermore, is described the essence of the test cases design, while the challenge of this process are discussed. The objective is to present points of view based on experience everyday of this activity within the software engineering view. RESUMEN Probar el software es una cuestión necesaria en el proceso de alcanzar fiabilidad, seguridad y calidad de los productos, pero la mayoría de probadores no con consientes de la importancia de esta actividad. En este artículo se hace una reflexión acerca del tema, y se describen algunos mitos y realidades del diseño e implementación de casos de prueba. Se parte del concepto de que la prueba del software se debe visualizar y aplicar como una fase paralela a todo el ciclo de vida del producto, y no dejarlo para el final como una imposición antes de la entrega. Además, se describe la esencia del diseño de casos de prueba, a la vez que se analizan los desafíos de este proceso. El objetivo es presentar puntos de vista basados en la experiencia del día a día de esta actividad al interior de la Ingeniería de Software. © 2014 IAI. All rights reserved. 1. Introducción Antes de liberar un producto software, los ingenieros de pruebas deben diseñar y aplicar un conjunto de casos de prueba para verificar la fiabilidad del sistema. Pero en la comunidad este proceso se rodea de una serie de mitos y realidades que, muchas veces, no pasan de ser precisamente eso. Los principales mitos que se encuentran están relacionados con la inutilidad de los casos de prueba, la dificultad, la incompatibilidad entre los tipos de negocios, los perfiles de los probadores, y los procesos de desarrollo. Por desgracia, la realidad es que todo lo relacionado con los casos de prueba y la trazabilidad de los requisitos es visto simplemente como una sesión obligatoria, impuesta por un proceso formal de entrega, al que no se le da la importancia que realmente merece y tiene. Esto conduce a la ineficiencia, la ignorancia, y a la improvisación de pruebas sobre la marcha. En este artículo se presenta un análisis a estos mitos y realidades, y se describen procesos que pueden ser útiles como guías para diseñar casos de prueba eficientes y eficaces. un proceso estructurado para el diseño efectivo de casos de prueba. 2. Recomendaciones iniciales A continuación se describen algunas recomendaciones con el objetivo de ayudarles a los probadores a organizar 2.2 Deben ser comprobables Si es así, entonces se puede continuar con el proceso, sino, se debe replantear. 2.1 Cuándo pensar en los casos de prueba Los casos de prueba son más que algunas frases utilizadas para probar algunos flujos. Son la forma de demostrar el nivel de confianza en el producto que se entrega, porque miden la cobertura de los requisitos y su situación en cada momento del proceso de desarrollo, por ejemplo, si han sido cubiertos con suficientes casos de prueba, o si en algún momento el estado de ejecución de las pruebas es el deseado o planeado. Con esta responsabilidad, los casos de prueba necesitan un poco de ayuda a fin de poder demostrar la correctitud del producto en todo momento. Por tal razón, se deben diseñar desde la primera etapa de la primera fase del ciclo de vida del sistema, es decir, desde los primeros contactos con el producto que necesita el cliente, no cuando está terminado [1]. Esto significa que se deben relacionar inmediatamente que se recopilan las primeras piezas de información o necesidades de los clientes o usuarios. 13 2.3 Determinar si son funcionalidades críticas para el producto o para el negocio Si lo son, es necesario definir qué tipo de conjunto de pruebas se necesitará, cómo priorizarlas, y cuál sería la posibilidad de cambiar esa prioridad en términos del esfuerzo necesario para revisar los casos de prueba, para ejecutarlos, para realizarle seguimiento al estado de ejecución, y después, tal vez, volver a la prioridad inicial. 2.4 Integrarlos al documento de requisitos Luego que se recibe el modelo de casos de uso, el primer instinto de los probadores es estructurar los casos de prueba con base en los flujos funcionales conducidos por los actores, con los mejores escenarios y flujos alternativos, y, muy probablemente, utilizando un estilo de diseño independiente, y con un amplio número de pasos, lo que significa que cada caso de prueba se puede ejecutar de forma individual, y no depende de otros casos de prueba. Esto no está mal, pero todavía se deben tener en cuenta algunos aspectos: Las funcionalidades críticas, que no son tan importantes para el cliente, se requieren para correr otros escenarios, por lo que se deben tratar por separado, marcándolas con prioridad mayor que los mejores escenarios. Cada flujo funcional ejecutado por un actor tiene necesariamente capas medias que se necesitan para trabajar. Esto significa que se deben considerar sus pruebas como una suite de casos de prueba especial, con otro estilo de diseño, o escribir un estilo más detallado. Esto significa que definitivamente hay que tener en cuenta algunas técnicas para seleccionar los casos de prueba más representativos, por lo menos algunas particiones de equivalencia y sus valores límite. Tener sólo flujos end-to-end en los casos de prueba puede significar un alto grado de redundancia para los mismos, y un alto riesgo de bloquear toda la ejecución si uno de los pasos iniciales comunes no está funcionando. Si estos flujos se dividen en componentes funcionales podrían funcionar mejor. Planear pruebas de regresión, porque de esta manera es más fácil ejecutar los casos de prueba de forma independiente, no en cascada. Se puede pensar o necesitar automatizar algunas partes de los flujos, aunque para algunos no es posible hacerlo. Esto sin duda significa un estilo de escritura detallado, a veces usando un enfoque en cascada. Teniendo en cuenta la estructura inicial de los flujos end-to-end, con seguridad se acabará escribiendo otro caso de prueba para la automatización, es decir, otra pieza de trabajo que contiene la misma información de otros casos de prueba, lo que resulta una vez más en redundancia. ¿Y qué de los requisitos no-funcionales? Muy probablemente no están incluidos en el modelo de casos de uso inicial, por lo que es necesario asegurar que se tendrá una estructura de casos de prueba para ellos. 2.5 El proceso de desarrollo y el manejo del tiempo En un proceso iterativo y ágil esto no es una excepción, porque se trata de echar un vistazo a los requisitos y ver cómo se entregarán las funcionalidades, si es posible volver a utilizar algunos de los primeros casos de prueba creados, o si se puede crear una suite de regresión desde el principio y mejorarla mientras se desarrolla el producto. El tiempo es un elemento crucial en el desarrollo de productos software, por lo que si se tiene menos del necesario lo conveniente es considerar el agrupamiento de los casos de prueba en suites funcionales impulsadas por los componentes críticos, considerar tanto el producto como los riesgos del proyecto, utilizar un estilo de escritura de alto nivel y flujos end-to-end en cascada, y fabricar componentes críticos independientes. Suponiendo que para cuando se recibe el primer conjunto de requisitos de negocio ya se ha hecho todo lo mejor posible, es el momento de saber más acerca de ellos, buscar una comprensión diferente de la que se tenía en la primera vista, y empezar a diseñar y escribir los casos de prueba necesarios. Este es un buen momento para ver qué herramientas se deben utilizar, y evaluar su compatibilidad con los requisitos de prueba en términos de la estructura de la prueba. Básicamente, desde el punto de vista del diseño de casos de prueba existen algunas cosas a tener en cuenta al momento de elegir una herramienta de gestión de pruebas: Debe tener una estructura claramente definida para suites de prueba, casos de prueba y scripts de prueba. Debe permitir casi cualquier tipo de estructura de prueba que se pueda necesitar en algún momento, una organización en sprints/iteraciones, u otras fases de prueba, como una organización jerárquica con muchas capas configurables. Debe ofrecer la posibilidad de agrupar los casos de prueba de formas diferentes a suites de prueba, por ejemplo, etiquetas o palabras clave, de manera que se puedan utilizar para organizar un efectivo ciclo de ejecución de pruebas ad hoc cuando sea necesario. Debe ofrecer la posibilidad de almacenar varias versiones de casos de prueba, y de actualizar los que ya se han asignado para ejecución. Debe tener otros atributos configurables que puedan servir para los propósitos del probador. Debe permitir una delimitación clara de las precondiciones o pasos iniciales que se deben tomar. Esto sucede al momento en que se reciben los requisitos del negocio, pero ¿qué pasa cuando se reciben las especificaciones técnicas, y cuando la ejecución de las pruebas recibe luz verde y se deben aplicar rápidamente? En estos momentos el diseño de casos de prueba pasa a 14 un segundo plano, pero debería ser una preocupación, porque de lo contrario será más difícil hacerle seguimiento a la ejecución de los necesarios para probar los requisitos del negocio. Esta es la principal diferencia entre pruebas comprensibles de requisitos de negocio, frente a las técnicas bajo estrés no comprensibles y en condiciones de tiempo ajustado. A pesar de esto los probadores podrían terminar la ejecución de algunos casos de prueba técnicos, y con seguridad que al menos alguien analizó esas especificaciones, las fraccionó, y les dio prioridad, y que alguien más ejecutará por lo menos una vez todos los escenarios. Haciendo hincapié en que el diseño de casos de prueba no sólo implica escribir casos de prueba, una detección temprana de la estructura de las pruebas requeridas, con una idea de cómo se verán y organizarán los casos de prueba, del esfuerzo necesario para la preparación de la prueba, y de las técnicas de diseño que se utilizarán para seleccionar las pruebas más representativas, ayudará a crear una línea base para el proceso. Además, sería más fácil diseñar casos de prueba: Eficaces: con una mayor probabilidad de detectar errores debido al análisis inicial de los requisitos. No-redundantes: gracias a una correcta identificación de los primeros pasos que se deben seguir, la organización de la suite de pruebas, y los estilos de diseño de los casos de prueba. Con un nivel de detalle adecuado e impulsado por las necesidades identificadas y el tiempo asignado. Trazables: debido a una correlación temprana entre los requisitos y los casos de prueba, por lo que es más fácil identificar las áreas afectadas cuando las necesidades cambian, o cuando algunas de las suites de prueba no funcionan por un tiempo y están afectando al producto. Esto parece no ser más que un toque suave que hace la diferencia, pero lo más importante es dejar el mito atrás, aceptar la realidad y hacer una verdadera diferencia al considerar todos los aspectos requeridos tan pronto como sea posible en el proceso. 3. Desafíos del diseño de casos de prueba Un alto número de casos de prueba se diseñan con poco o ningún esfuerzo, pero diseñar buenos casos de prueba puede ser complejo y desafiante, y a menudo las personas no responsables de escribirlos y ejecutarlos olvidan proporcionar los recursos para diseñar buenas pruebas; sin contar la comprensión de la información que se requiere para obtener los informes suficientes que permitan medir la eficacia de los esfuerzos de prueba. También está la organización, el equipo de desarrollo, el equipo de prueba, los procesos, y las herramientas, que pueden definir, e incluso a veces aplicar, las pruebas que se desean. Por eso, no es ninguna sorpresa, al buscar en los foros de discusión, que diversas personas buscan soluciones de talla única para todo. En Internet y en los libros hay información más que suficiente que explica la forma de analizar requisitos, aplicar técnicas de diseño de pruebas, e implementarlas en la práctica, pero no todos son ayudas verdaderas. Para hacerse a una idea de qué es un buen caso de prueba, se recomienda consultar el trabajo de investigación de Cem Kaner [2], porque el objetivo del presente artículo no es explicar cómo aplicar las técnicas de prueba, sino más bien compartir la información como una guía introductoria sobre los factores a considerar y que permiten diseñar buenas pruebas. El contenido se basa en experiencias para resolver los desafíos de un equipo de pruebas, y se asume que los lectores tienen alguna experiencia en pruebas formales, y que tienen comprensión de las técnicas de diseño. El primer desafío al que se enfrentan los probadores es que los impactos del diseño de buenas pruebas hace a todos conscientes de los principios de la prueba, y la Fundación ISTQB [3] destaca siete de ellos: 1. Las pruebas muestran la presencia de defectos, no su ausencia. Se deben diseñar más pruebas que muestren defectos, porque el camino feliz puede que funcione, a menos que, por supuesto, se cuestione la calidad del código que se analiza. 2. En diversas situaciones probar todo es imposible. Por lo que se recomienda usar el análisis de riesgos y priorizar el enfoque del esfuerzo de prueba. Al aceptar el hecho de que no hay una prueba para cada combinación y permutación se bajarán los niveles de estrés y las expectativas. Algunas cosas se pueden pasar por alto, pero si se requieren 20 casos de prueba, lo mejor es diseñar 100, y de ellos elegir los 20 mejores. 3. Iniciar las actividades de prueba lo antes posible en el ciclo de vida de desarrollo. Dejar de lado la creencia de que las pruebas son sólo para Verificar y Validar la funcionalidad del producto, una vez que es ejecutable. Diseñar pruebas desde la primera etapa de la primera fase del ciclo de vida puede tener un alto retorno de la inversión, en comparación con hacerlo en las fases posteriores. 4. Los defectos tienden a agruparse. Por lo que se recomienda diseñar nuevas pruebas después de ejecutar las pruebas, y, cuando se tenga tiempo, revisar algunos casos de prueba de la colección que fue excluida del alcance de aplicación inicial, y que se refieran a los componentes en los que se detectaron defectos. 5. En algún momento un sistema se puede volver inmune a las pruebas que se repiten muchas veces. Una vez más, se recomienda no dejar de diseñar nuevas pruebas después que las previstas encontraron defectos, y revisar el conjunto de pruebas que se excluyeron inicialmente, o utilizar más técnicas de prueba para ampliar el tipo de defectos detectados. 15 6. Las pruebas se diseñan bajo la influencia del contexto del sistema que está siendo desarrollado, y de la formalidad del dominio del negocio. Pero no todas las personas construye puentes, por lo que las pruebas se deben adaptar a las necesidades específicas del plan. 7. En ocasiones, se diseña una extensa cantidad de pruebas de acuerdo con el código, pero más tarde se reconoce que el código no resuelve las necesidades y expectativas de los usuarios. Por eso, cuando no existen las especificaciones, lo recomendable es considerar el diseño de las pruebas de acuerdo con la forma en que el usuario espera que el sistema funcione, y cómo va a satisfacer su necesidad. Por regla general no se debe confiar en el código como fuente de especificación. El segundo desafío es identificar qué, por qué y cómo las cosas tienen que ser probadas. Esto llega a ser muy difícil, y a veces político, cuando se trabaja en equipo o con personas que no entienden el propósito y los objetivos de las pruebas. El ciclo de vida del desarrollo y la madurez de los actores y el equipo pueden ser los principales obstáculos para ser creativo al diseñar buenas pruebas, e identificar qué probar es como hacer las preguntas correctas en el análisis de requisitos. El estándar ISO/IEC 25010:2011 [4] puede ser un punto de partida en la dirección correcta, e incluir estas características en las preguntas es una forma efectiva de obtener información y aclarar las especificaciones, especialmente cuando se trabaja con equipos ágiles (a veces frágiles) porque presentan una oportunidad para definir los detalles de un requisito más allá de lo que pensaba que podría ser el propietario original. Debido a que en ocasiones no se tiene acceso a expertos que ayuden a identificar aspectos específicos comprobables, lo recomendable es tratar de anticiparse a los problemas, en términos de las necesidades y experiencias que se pueden producir utilizando las siguientes características de calidad: Funcionalidad Fiabilidad Usabilidad Eficiencia Mantenibilidad Portabilidad Estas características de alto nivel tienen subcaracterísticas, como precisión, rendimiento, capacidad de cambio, instalabilidad, y otras más, que se deben seleccionar de acuerdo con el calendario, el presupuesto y los recursos disponibles. Una característica que no se menciona lo suficiente en el desarrollo de software es la capacidad de prueba, y un alto número de productos software están diseñados de tal manera que pueden necesitar mucho tiempo, son propenso a errores, y son difíciles de probar. Lo ideal es considerar la facilidad de la prueba en la fase de diseño, para permitir que se diseñen mejores pruebas desde el principio. El tercer desafío es lograr que el contenido de las pruebas sea claro y medible. Esto probablemente no hace parte del diseño de las pruebas, ya que se espera que lo que hay que medir se defina en las actividades de planificación de pruebas y en su proceso de control. Las pruebas son como un faro para el equipo, porque lo deben guiar para que pueda evitar los obstáculos. Curiosamente, esta es la última cosa que se tiene en cuenta, pero en algún momento se tendrá que proporcionar información como: Prueba de esfuerzo Mejoramiento del enfoque de prueba Probar algo para alguien Mejorar la cobertura y las habilidades Un buen comienzo para ver qué información se requiere en un caso de prueba es leer el estándar IEEE 829 [5]. Desde ahí se pueden excluir los elementos que se consideren irrelevantes a largo plazo, añadir algunos según sean necesarios, e identificar qué informes se requieren, y luego buscar la mejor herramienta que los genere tan pronto como se necesiten. Desafortunadamente, las pruebas tienden a ser muy dependientes de las herramientas para procesar grandes cantidades de información, pero ésta también podría tener un impacto en la formalidad de la prueba, por lo que se requieren ciertos procesos para mantener la información. Otro asunto importante es revisar frecuentemente las pruebas, de la misma forma que se revisa el código, porque esto establece un proceso para la mejora continua. 4. La esencia del diseño de casos de prueba Es una realidad que, sin importar qué tan bien se estructuren e implementen los planes de pruebas y de prevención, los productos software siempre tienen defectos. Esto es evidente, porque los desarrolladores no pueden prevenir/eliminar todos los errores durante el ciclo de desarrollo. Pero también es una realidad que el software debe ser probado a fondo antes de entregarlo a los usuarios finales [6], por lo tanto, es responsabilidad de los probadores diseñar pruebas que: 1) revelen defectos, y 2) puedan ser utilizadas para evaluar el desempeño del software, la facilidad de uso, la fiabilidad, entre otras características, y, para lograr estos objetivos, los probadores deben seleccionar y/o formular un número finito de casos de prueba, a menudo a partir de un dominio de ejecución muy grande. Por desgracia, la prueba completa generalmente no se lleva a cabo ni se realiza dentro del alcance, el presupuesto y las limitaciones de tiempo del proyecto. Es importante destacar que a menudo los probadores sufren la presión de la administración, y de las partes interesadas, cuando las pruebas tienden a perder su control y no se llevan a cabo en la forma prevista, en parte porque las expectativas cada vez son menos realistas. Así que, el probador debe planificar con eficacia la prueba, formular un conjunto de casos de prueba, seleccionar y ejecutar los adecuados, y supervisar el proceso para asegurar que los recursos y el tiempo asignados se utilicen eficazmente. Pero, formular esto es sin duda una tarea formidable, y para llevarlo a cabo necesitan educación y formación adecuada, así como la capacidad para obtener el apoyo de gestión. 16 En este proceso, generalmente los probadores se adhieren a dos enfoques diferentes para las pruebas: 1) utilizando todas las posibles entradas y mediante un método convencional pueden tratar de probar principalmente un módulo o componente, y luego ensayar con todos los posibles caminos del software. Además de aplicar este enfoque, inculcan lentamente el atributo de razonar todo lo relacionado con el producto, lo que finalmente les permitirá detectar la mayor cantidad de defectos posible. Pero un probador formado y educado sabe que esto no es un objetivo realista, ni económicamente viable o factible. 2) Seleccionan las entradas de prueba al azar, con la esperanza de que revelen defectos críticos. Pero los especialistas en pruebas opinan que este tipo de entradas tienen un pobre historial de desempeño, en cuanto a la evaluación de los atributos de calidad del sistema. Por lo tanto, este es un debate de nunca acabar y una pregunta sin respuesta desde el punto de vista de las pruebas. Sin importar cuál de estos métodos se aplique, siempre se cree que el objetivo del probador en definitiva es comprender la funcionalidad, el dominio de entradas y salidas, y el entorno de uso para las pruebas [7]. Del mismo modo, para ciertos tipos de pruebas, también tiene que entender en detalle cómo se construye el código. Además, necesita hacer uso de su conocimiento acerca de los tipos de defectos que se inyectan habitualmente durante el desarrollo o el mantenimiento del software. Con toda esta información debe, inteligentemente, seleccionar un subconjunto de entradas, así como las combinaciones de las mismas, que cree que tienen la mayor posibilidad de revelar defectos dentro de las condiciones y limitaciones impuestas en las pruebas. Sin embargo, este proceso necesita tiempo y esfuerzo, por lo que el probador que quiere maximizar y/u optimizar el uso del tiempo y los recursos sabe y aprecia el hecho de que sólo se puede lograr cuando se han desarrollado casos de prueba eficaces para las pruebas funcionales. Por casos de prueba eficaces se entienden aquellos que tienen una buena posibilidad de revelar un defecto. Si el objetivo es desarrollar un proceso de pruebas de alta calidad, la capacidad de desarrollar este tipo de casos de prueba es muy importante para una organización, a su vez, le trae muchas consecuencias positivas. Si los casos de prueba son eficaces se tiene: Una mayor probabilidad de detectar defectos Un uso más eficiente de los recursos de la organización Una mayor probabilidad de reutilización de la prueba Un cumplimiento más adecuado para las pruebas, los calendarios del proyecto y los presupuestos, y una alta posibilidad de entregar un producto software de mayor calidad. 4.1 Técnicas para diseñar casos de prueba Después de describir las diversas ventajas de los casos de prueba eficaces, es importante presentar una consideración cuidadosa a los enfoques que un probador debe utilizar para diseñarlos. En este caso, es necesario ver y/o inspeccionar el software como un producto de ingeniería, y, teniendo en cuenta esta percepción, hay dos estrategias de prueba básicas que se pueden utilizar: 1) funcional, a veces denominada de caja negra o de especificación, y 2) estructural, llamada de caja blanca o caja de cristal. En la primera estrategia, el probador considera al software bajo prueba como una caja negra, y no tiene conocimiento de su estructura interna, es decir, de cómo funciona, sólo tiene conocimiento de lo que hace. El tamaño del producto a probar puede variar desde un módulo sencillo, un componente de alguna función, o un objeto clúster, hasta un subsistema o un sistema completo. Además, la descripción del comportamiento subyacente, o la funcionalidad, se puede proporcionar mediante una especificación formal, un diagrama de entrada/proceso/salida, o un conjunto de pre y post condiciones bien definido. Otra fuente de información que vale la pena mencionar es el documento de especificación de requisitos, en el que generalmente se describe la funcionalidad del software, y sus entradas y salidas esperadas. Con toda esta información, el probador selecciona los valores de entrada, ejecuta las pruebas, y luego determina si los productos obtenidos están en línea con los previstos en la especificación. Debido a que las pruebas funcionales sólo tienen en cuenta el comportamiento del software y su funcionalidad, este enfoque es especialmente útil, y muy útil, para revelar errores en los requisitos y la especificación. La segunda estrategia se centra en la estructura interna del software bajo prueba, por lo tanto, para diseñar los casos de prueba, el probador debe primero tener conocimiento de esa estructura, y, para lograrlo, debe tener a su disposición el código o el seudo-código como una representación adecuada, de tal forma que los pueda utilizar para la referencia y comprensión. Una vez que ha logrado la visión necesaria de la estructura, selecciona los casos de prueba convenientes para ejercitar elementos estructurales internos específicos, con el objetivo de determinar si están funcionando correctamente o no. Por ejemplo, los casos de prueba se diseñan a menudo para ejercitar todas las declaraciones o las ramificaciones verdaderas/falsas que se producen en un módulo o función miembro, pero, debido a que el diseño, la ejecución, y el análisis de los resultados de las pruebas estructurales toma tiempo, esta estrategia se limita y aplica generalmente sólo a pequeñas piezas software, como módulos o funciones miembro. Aunque las estrategias de prueba estructural son especialmente útiles para revelar errores de diseño y control basados en código, los lógicos y de secuencia, los de inicialización, y los de flujo de datos, desde el punto de vista del probador, para lograr el objetivo de proporcionarles a los usuarios software con pocos errores y de alta calidad, se deben aplicar ambas estrategias para el diseño de casos de prueba. Además, tanto las funcionales como las estructurales le sirven de apoyo para seleccionar un número finito de casos de prueba, y, del mismo modo, ambos enfoques se complementan entre sí, porque cada uno puede ser útil para revelar ciertos 17 tipos de errores. Es importante destacar que, con un conjunto de casos de prueba diseñados utilizando ambas estrategias, el probador aumenta las probabilidades de revelar muchos tipos diferentes de defectos en el software, y también tendrá un conjunto efectivo de casos de prueba reutilizables para las pruebas de regresión, y para probar nuevas versiones del software. En la Tabla 1 se describe un resumen de ambas estrategias de prueba. Tabla 1. Estrategias funcionales vs estructurales Estrategia Visión del probador Fuentes de conocimiento Funcional Documento de requisitos Documento de especificación Conocimiento del dominio Estructural Documento de diseño de alto nivel Documento de diseño detallado Grafos de control de flujo Sin embargo, existen factores que se deben considerar antes del diseño [6], como: El riesgo asociado con la prueba Tipos de errores esperados El conocimiento y la experiencia del probador El nivel de la prueba y el grupo de actividades que tienen que ser agrupadas y administradas Las herramientas que se utilizarán para ejecutar los casos de prueba Técnicas Partición de clase equivalente Análisis de valores límite Pruebas de estados de transición Grafos causa-efecto Adivinación de errores… Pruebas de estado Pruebas ramificadas Pruebas de caminos Pruebas de flujo de datos Pruebas de mutación Prueba de bucles… El tipo de aplicación, el software, y el dominio del problema Los requisitos del cliente… Además de estos factores, existen otras cuestiones que juegan un papel crucial, y que se deben resolver para realizar la elección de la técnica más adecuada para el diseño de casos de prueba, tal como se muestra en la Tabla 2. Tabla 2. Cuestiones a resolver antes de diseñar casos de prueba 1 2 3 4 5 6 7 8 9 10 Interrogante Si el proceso de la prueba tiene que ir junto con el modelo en V, o si se trata de un diseño basado en pruebas Si hay algunas especificaciones de requisitos poco claras Si la aplicación es grande, o abarca varias aplicaciones o subsistemas interconectados que se deben probar en paralelo Si las pruebas son rentables Si se necesitan pruebas de bajo nivel para evaluar el trabajo o el comportamiento interno del sistema Para determinar la cobertura de la prueba Para determinar el logro de la eficiencia de la prueba Para optimizar el esfuerzo de la prueba mediante el diseño de casos de prueba ejecutados con recursos limitados Si se consiguen fácilmente las herramientas de apoyo para formular y/o ejecutar los casos de prueba Si es posible lograr la comprensión general de la aplicación durante la fase de pruebas Las técnicas para diseñar casos de prueba pueden ser: Basadas en la experiencia. El conocimiento de las personas, y sus habilidades y experiencia, conforman la base y son de vital importancia para la formulación de las condiciones de prueba y los casos de prueba. Sin duda, la experiencia de las personas, desde los frentes técnicos y de negocios, es necesaria y esencial, porque le brinda diferentes perspectivas al análisis de la prueba y al proceso de diseño. Además, gracias a la experiencia previa en el trabajo con sistemas similares, pueden tener una idea y/o conocimiento profundo de lo que podría salir mal, lo que es muy útil para las pruebas. Por lo tanto, las técnicas basadas en la experiencia van de la mano con las basadas en la especificación y las basadas en la estructura, y también se utilizan cuando no existe una especificación, o cuando es inadecuada u obsoleta. Puede ser el único tipo de técnica utilizada para diseñar casos destinados a probar sistemas de bajo riesgo, pero este enfoque puede ser particularmente útil en situaciones extremadamente críticas en tiempo, y, de hecho, es Técnica Funcional Funcional Funcional Funcional Estructural Estructural Estructural Estructural Estructural Estructural uno de los factores que conduce a las pruebas exploratorias. Aleatorias. Generalmente, cualquier módulo de software o sistema tiene un dominio de entrada desde el que se seleccionan los datos de entrada para la prueba, y se utiliza para formular y/o ejecutar los casos de prueba diseñados. Ahora bien, cuando un probador adopta el enfoque de selección aleatoria de los valores de entrada desde el dominio de entrada de requisitos, prepara los casos de prueba, y los ejecuta para probar la aplicación, está aplicando el enfoque aleatorio. Por ejemplo, si el dominio de entrada válido para un módulo es todos los números enteros positivos entre 1 y 100, utilizando este enfoque el probador selecciona valores dentro de ese dominio, por ejemplo 15, 27 y 33. Pero, el uso de estas técnicas deja algunas preguntas que permanecen abiertas: ¿Los valores de los casos de prueba son suficientes para demostrar que el módulo o el sistema cumplen con su especificación? 18 ¿Existen valores de entrada adicionales, distintos de los seleccionados, que sean más propensos a revelar errores? ¿Debe usarse cualquier valor válido por fuera del dominio como entrada de prueba para la ejecución de los casos de prueba? Es decir, ¿los datos de la prueba incluyen valores decimales, valores negativos, o valores enteros superiores a 100? Estas cuestiones se pueden abordar fácilmente con enfoques más estructurados para el diseño de pruebas funcionales, aunque el uso de entradas de prueba aleatorias puede ahorrar algo de tiempo y esfuerzo, que otros métodos de selección si requieren [7]. Pero, de acuerdo con diversos especialistas en pruebas, la selección de las entradas al azar tiene muy pocas posibilidades de producir un conjunto efectivo de datos de prueba para ejecutar casos de prueba, por lo que la eficacia relativa de estas técnicas frente a enfoques más estructurados para generar entradas de prueba siempre será tema de introspección y/o investigación. 4.2 Componentes de un caso de prueba En primer lugar, un caso de prueba está diseñado y pensado para indicar qué se hace en la prueba, por lo tanto, es muy importante darle al probador consideraciones cuidadosas para el desarrollo de los casos, de forma que se le defina y/o proporcione una descripción completa del ítem que se debe validar para asegurar que el sistema está funcionando según lo previsto, y que también debe reflejar la confianza de que se construye con la máxima calidad. Entonces, independientemente de la técnica/estrategia de diseño que se implemente durante el desarrollo de los casos de prueba, el probador debe asegurarse de cubrir y documentar lo siguiente: Resumen. Debe reflejar el tema real, y la categoría y las características de las funciones, de forma que el probador pueda organizar fácilmente los casos de prueba en grupos lógicos y ordenarlos en consecuencia. Esta sección podría tener detalles relativos al esfuerzo de ejecución sobre la base horasprobador, unidades de trabajo, y prioridad. A menudo se refiere como la fuerza del caso de prueba. Diseño. Esta sección refleja el diseño general del caso de prueba, y podría incluir alguna descripción de alto nivel. Revisión Formal. Contiene detalles acerca de la lista que el equipo debe revisar o aprobar en el caso de prueba, y también define el proceso de aprobación. Esta sección se utiliza principalmente para instituir los pasos de revisión formal para asegurar que los procesos de negocio cumplen con las normas. Además, podría incluir detalles relativos al dueño del caso de prueba, los elementos de trabajo, las notificaciones, y el resumen de resultados. Requisitos. Esta sección está destinada a asociar los requisitos con un caso de prueba en particular, cuando se añaden al plan de pruebas. Así, una vez que se ha establecido esta asociación, el probador puede proceder a crear informes de cobertura, para entender y determinar qué porcentaje de los requisitos cubren los casos de prueba. Es importante destacar que, mediante el mantenimiento de esta asociación, es posible configurar y comprobar la trazabilidad a lo largo del proyecto. Pre-condiciones. Describe los elementos que forman el pre-requisito, o que deben ocurrir antes de que el probador realmente puede empezar a correr/ejecutar los casos de prueba. Post-condiciones. Describen lo que debe ocurrir después que se complete la ejecución de los casos de prueba. Típicamente es la generación de los reconocimientos necesarios, el envío de notificaciones de correo electrónico, entre otros. Resultados esperados. En esta sección se detalla la lista de resultados que se deben alcanzar antes de que el probador considere que ha tenido éxito la realización de la prueba. Es posible que contenga un documento/archivo o imagen del código resultante. Scripts de prueba. Describen los scripts de prueba que están asociados con un caso de prueba en particular. En general, hay varios tipos de scripts de prueba, como los manuales, las palabras clave habilitadas, y los automatizados, y cada uno contiene las instrucciones para la aplicación de un caso de prueba. Durante la ejecución, los manuales se procesan sentencia a sentencia, a diferencia de los automatizados que se ejecutan utilizando una herramienta. Registros de ejecución de prueba. Generalmente, contienen información detallada para los casos de prueba y de los resultados de alto nivel generados en la ejecución. También proporcionan detalles relativos a los entornos de hardware y software necesarios para la ejecución de la prueba, por ejemplo, si un caso de prueba pasa cuando se ejecuta en dos sistemas operativos diferentes, dos plataformas de hardware diferentes, o utilizando tres navegadores diferentes, entonces el probador podría crear un registro de ejecución de la prueba para cada una de estas combinaciones. Así mismo, contienen el resultado global que se asocia con la ejecución del caso de prueba, un registro detallado de la ejecución de la prueba, y una historia detallada de todos los resultados de la ejecución. Adjuntos. Esta sección suele contener todos los documentos y archivos que apoyan el caso de prueba Lista de evaluación de riesgos. Contiene una lista de los riesgos asociados con un caso de prueba en particular. 19 Cuando todas estas secciones se relacionan en un caso de prueba, y éste se ejecuta, entonces es buena señal de que se han cumplido los criterios relativos a la consecución de cobertura completa de la prueba, de la eficiencia, de la seguridad, entre otras. 5. Conclusiones Un caso de prueba es un conjunto de condiciones o variables con las que un probador determina si un sistema bajo prueba cumple los requisitos o funciona correctamente. El proceso de desarrollo de casos de prueba también puede ayudar a detectar problemas en los requisitos o en el diseño de una aplicación. En la medida de lo posible, los casos de prueba se deben escribir de tal manera que prueben una sola cosa a la vez, de tal manera que no se superpongan. La recomendación general es estructurarlos lo más atómico que sea posible, de esta forma se puede garantizar que cubren todos los escenarios positivos y negativos. Para lograrlo, el lenguaje debe ser sencillo y fácil de entender, utilizar voz activa (Haz esto, haz aquello), y hacer uso de nombres exactos y consistentes (de formularios, campos, etc.). Las características de un buen caso de prueba: 1) Preciso: exige el propósito; 2) Económico: no hay pasos o palabras innecesarios; 3) Trazabilidad: capaz de rastrear requisitos; 4) Repetible: puede ser utilizado para realizar la prueba una y otra vez, y 5) Reutilizable: se puede reutilizar si es necesario. En resumen, los acasos de prueba deben ser lo más simples posible, con un objetivo determinado y con unos logros específicos; para escribirlos se puede recurrir a las herramientas disponibles, y, al automatizarlos, buscar la mayor cobertura, porque de lo contrario se perderá el esfuerzo de esta actividad. Referencias [1] Serna, M.E. & Arango, I.F. (2011). Software Testing: More than a Stage in the Life Cycle. Revista de Ingeniería 35, pp. 34-40. [2] Kaner, C. (2003). What is a good test case? In STAR East, Orlando, FL, USA. [3] ISTQB (2011). Foundation Level in Software Testing Syllabus 2011. Online [Dec. 2013]. [4] ISO/IEC (2011). 25010:2011: Systems and software engineering - Systems and software Quality Requirements and Evaluation (SQuaRE) - System and software quality models. [5] IEEE (2008). 829:2008 IEEE Standard for Software and System Test Documentation. [6] Binder, R. (1999). Testing Object-Oriented Systems: Models, Patterns, and Tools. Addison-Wesley. [7] Marick, B. (1995). The Craft of Software Testing. Prentice Hall. 20