<?xml version="1.0" encoding="ISO-8859-1"?><article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<front>
<journal-meta>
<journal-id>0121-4993</journal-id>
<journal-title><![CDATA[Revista de Ingeniería]]></journal-title>
<abbrev-journal-title><![CDATA[rev.ing.]]></abbrev-journal-title>
<issn>0121-4993</issn>
<publisher>
<publisher-name><![CDATA[Universidad de los Andes.]]></publisher-name>
</publisher>
</journal-meta>
<article-meta>
<article-id>S0121-49932011000300006</article-id>
<title-group>
<article-title xml:lang="es"><![CDATA[Prueba del software: más que una fase en el ciclo de vida]]></article-title>
<article-title xml:lang="en"><![CDATA[Software testing: more than a stage in the life cycle]]></article-title>
</title-group>
<contrib-group>
<contrib contrib-type="author">
<name>
<surname><![CDATA[Serna M]]></surname>
<given-names><![CDATA[Edgar]]></given-names>
</name>
<xref ref-type="aff" rid="A01"/>
</contrib>
<contrib contrib-type="author">
<name>
<surname><![CDATA[Arango I]]></surname>
<given-names><![CDATA[Fernando]]></given-names>
</name>
<xref ref-type="aff" rid="A02"/>
</contrib>
</contrib-group>
<aff id="A01">
<institution><![CDATA[,Universidad de San Buenaventura  ]]></institution>
<addr-line><![CDATA[Medellín ]]></addr-line>
</aff>
<aff id="A02">
<institution><![CDATA[,. Universidad Nacional de Colombia sede Medellín  ]]></institution>
<addr-line><![CDATA[ ]]></addr-line>
</aff>
<pub-date pub-type="pub">
<day>30</day>
<month>12</month>
<year>2011</year>
</pub-date>
<pub-date pub-type="epub">
<day>30</day>
<month>12</month>
<year>2011</year>
</pub-date>
<numero>35</numero>
<fpage>34</fpage>
<lpage>40</lpage>
<copyright-statement/>
<copyright-year/>
<self-uri xlink:href="http://www.scielo.org.co/scielo.php?script=sci_arttext&amp;pid=S0121-49932011000300006&amp;lng=en&amp;nrm=iso"></self-uri><self-uri xlink:href="http://www.scielo.org.co/scielo.php?script=sci_abstract&amp;pid=S0121-49932011000300006&amp;lng=en&amp;nrm=iso"></self-uri><self-uri xlink:href="http://www.scielo.org.co/scielo.php?script=sci_pdf&amp;pid=S0121-49932011000300006&amp;lng=en&amp;nrm=iso"></self-uri><abstract abstract-type="short" xml:lang="es"><p><![CDATA[La prueba de software es probablemente la parte menos comprendida del ciclo de vida del desarrollo de software. En este trabajo, mediante una propuesta metodológica de cuatro fases, se muestra por qué es difícil detectar y eliminar errores, por qué es complejo el proceso de realizar pruebas y por qué es necesario prestarle más atención]]></p></abstract>
<abstract abstract-type="short" xml:lang="en"><p><![CDATA[Software testing probably is the least understood part of the software testing life cycle. In this work, by means of a methodological proposal of four stages, is showed why is complex the process of carrying out the testing software, why is necessary to pay it more attention and why is so difficult to detect and delete the mistakes]]></p></abstract>
<kwd-group>
<kwd lng="es"><![CDATA[Caminos de ejecución]]></kwd>
<kwd lng="es"><![CDATA[capacidad de prueba]]></kwd>
<kwd lng="es"><![CDATA[escenario de prueba]]></kwd>
<kwd lng="es"><![CDATA[flujo de datos]]></kwd>
<kwd lng="es"><![CDATA[prueba del software]]></kwd>
<kwd lng="es"><![CDATA[verificación]]></kwd>
<kwd lng="en"><![CDATA[Data flow]]></kwd>
<kwd lng="en"><![CDATA[execution paths]]></kwd>
<kwd lng="en"><![CDATA[software testing]]></kwd>
<kwd lng="en"><![CDATA[testability]]></kwd>
<kwd lng="en"><![CDATA[test scenario]]></kwd>
<kwd lng="en"><![CDATA[verification]]></kwd>
</kwd-group>
</article-meta>
</front><body><![CDATA[  <font face="verdana" size="2">     <p align="center"><font face="Verdana" size="3"><b>Prueba del software: m&aacute;s que una fase en el ciclo de vida</b></font></p>     <p align="center"><font face="Verdana" size="2">Software testing: more than a stage in the life cycle</font></p>     <p><b>Edgar Serna M.</b><sup>(1)</sup>, <b>Fernando Arango I.</b><sup>(2)</sup></p>     <p>(1) M.Sc. Universidad de San Buenaventura Medell&iacute;n. Correo:<a href="mailto:edgar.serna@usbmed.edu.co">edgar.serna@usbmed.edu.co</a></p>     <p>(2) PhD. Universidad Nacional de Colombia sede Medell&iacute;n. Correo: <a href="mailto:farango@unal.edu.co">farango@unal.edu.co</a></p>     <p> Recibido: 31 de agosto de 2010, modificado 18 de enero de 2012, aprobado 18 de enero de 2012.</p><hr />     <p><b>Resumen</b></p>     <p> La prueba de software es probablemente la parte menos comprendida del ciclo de vida del desarrollo de software. En este trabajo, mediante una propuesta metodol&oacute;gica de cuatro fases, se muestra por qu&eacute; es dif&iacute;cil detectar y eliminar errores, por qu&eacute; es complejo el proceso de realizar pruebas y por qu&eacute; es necesario prestarle m&aacute;s atenci&oacute;n.</p>     <p><b>Palabras claves</b></p>     ]]></body>
<body><![CDATA[<p> Caminos de ejecuci&oacute;n, capacidad de prueba, escenario de prueba, flujo de datos, prueba del software, verificaci&oacute;n.</p>     <p><b>Abstract</b></p>     <p> Software testing probably is the least understood part of the software testing life cycle. In this work, by means of a methodological proposal of four stages, is showed why is complex the process of carrying out the testing software, why is necessary to pay it more attention and why is so difficult to detect and delete the mistakes.</p>     <p><b>Key words</b></p>     <p> Data flow, execution paths, software testing, testability, test scenario, verification.</p> <hr>     <p><font face="verdana" size="3"><b> Introducci&oacute;n</b></font></p>     <p> Toda empresa que desarrolla software prueba sus productos pero, aun as&iacute;, antes de entregarlos siempre contienen anomal&iacute;as residuales de diversa gravedad. A veces, es dif&iacute;cil imaginar c&oacute;mo es que los probadores no detectan algunos errores evidentes. En muchas empresas, los probadores est&aacute;n mal preparados para ejecutar la dif&iacute;cil tarea de ensayar los productos software, cada vez m&aacute;s complejos. Los resultados en muchas encuestas informales, hechas a los asistentes a seminarios, sugieren que algunos de los que realizan pruebas, como profesi&oacute;n o como un complemento al desarrollo, tienen un adecuado entrenamiento en pruebas o tienen acceso a buenos libros de pruebas de software.</p>     <p> James Whittaker &#91;1&#93; brinda algunas luces acerca de por qu&eacute; el proceso de probar el software actual es tan retador e identifica varios enfoques concretos que todos los probadores deber&iacute;an ser capaces de aplicar f&aacute;cilmente: el probador eficiente tiene a su disposici&oacute;n un amplio conjunto de t&eacute;cnicas de prueba, entiende c&oacute;mo se utilizar&aacute; el producto en su entorno operativo, tiene buen olfato para encontrar errores sutiles y tiene a la mano una bolsa de trucos que sabe utilizar. Los m&eacute;todos que se describen en este trabajo pueden ayudar a los probadores para dar una respuesta sensata a la cuesti&oacute;n de lo que realmente quieren expresar cuando dicen: "estamos ejecutando pruebas a un sistema software".</p>     <p> Los desarrolladores conocen la frustraci&oacute;n cuando se reciben reportes de errores de parte de los usuarios. Cuando esto sucede inevitablemente se preguntan: &iquest;c&oacute;mo escaparon esos errores a las pruebas? Sin duda que invirtieron incontables horas en el examen cuidadoso de cientos o miles de variables y sentencias de c&oacute;digo, as&iacute; que &iquest;c&oacute;mo puede un error eludir esta vigilancia? La respuesta requiere, en primer lugar, una mirada m&aacute;s atenta a las pruebas de software en el contexto de desarrollo y, en segundo lugar, es necesario comprender el papel que juegan los probadores y los desarrolladores en dicho contexto dos funciones parecidas pero muy diferentes.</p>     <p> Suponiendo que las anomal&iacute;as que reportan los usuarios realmente son errores, la respuesta a la anterior pregunta podr&iacute;a ser cualquiera de las siguientes:</p> <ul type = "square">     ]]></body>
<body><![CDATA[<li>El usuario ejecuta un c&oacute;digo no probado. Por falta de tiempo, no es raro que los desarrolladores liberen c&oacute;digo sin probar, en el que los usuarios pueden encontrar anomal&iacute;as.     <li>El orden en que se ejecutan las declaraciones en el ambiente de uso difiere del que se utiliz&oacute; durante la prueba. Este orden puede determinar si el software funciona bien o no.     <li>El usuario aplica una combinaci&oacute;n de valores de entrada no probados. Las posibles combinaciones de valores de entrada, que miles de usuarios pueden hacer a trav&eacute;s de una interfaz de software, simplemente son demasiado numerosas para que los probadores las apliquen todas y, como deben tomar decisiones dif&iacute;ciles acerca de qu&eacute; valores de entrada probar, a veces toman las equivocadas.     <li>El entorno operativo del usuario nunca se prob&oacute;. Es posible que los probadores tengan conocimiento de dicho entorno, pero no cuenten con el tiempo suficiente para probarlo. Tal vez no replicaron la combinaci&oacute;n de hardware, perif&eacute;ricos, sistemas operativos y aplicaciones del entorno del usuario en el laboratorio de pruebas. Por ejemplo, aunque es poco probable que las empresas que escriben software de red creen redes de miles de nodos en su laboratorio de pruebas, los usuarios s&iacute; lo pueden hacer y, de hecho, lo hacen en sus entornos reales.     </ul>     <p> Desde una visi&oacute;n general del problema y del proceso de las pruebas del software, este art&iacute;culo investiga y describe los problemas que enfrentan los probadores e identifica las cuestiones t&eacute;cnicas que cualquier soluci&oacute;n de prueba debe abordar. Adem&aacute;s, estudia las clases de soluciones que actualmente se utilizan en la pr&aacute;ctica.</p>     <p><font face="verdana" size="3"><b>PROBADORES Y PROCESOS DE PRUEBA</b></font></p>     <p> Los probadores de software deben considerar lo siguiente al planificar y ejecutar las pruebas: el software y su funci&oacute;n de c&aacute;lculo, las entradas y c&oacute;mo se pueden combinar y el entorno en el que el software eventualmente funcionar&aacute;. Este dif&iacute;cil proceso requiere tiempo, sofisticaci&oacute;n t&eacute;cnica y una adecuada planificaci&oacute;n. Los probadores no s&oacute;lo deben tener buenas habilidades de desarrollo -a menudo las pruebas requieren una gran cantidad de c&oacute;digo- sino tambi&eacute;n conocimientos en lenguajes formales, teor&iacute;a de grafos, l&oacute;gica computacional y algoritmia. De hecho, los probadores creativos aplican muchas disciplinas, relacionadas con la inform&aacute;tica, al problema de las pruebas, a menudo con resultados impresionantes.</p>     <p> Incluso el software m&aacute;s simple presenta obst&aacute;culos por lo que, para tener una visi&oacute;n m&aacute;s clara acerca de algunas de las dificultades inherentes a las pruebas de software, es necesario acercarse a ellas a trav&eacute;s de la aplicaci&oacute;n de cuatro fases:</p> <ol>     <li>Modelar el entorno del software.     ]]></body>
<body><![CDATA[<li>Seleccionar escenarios de prueba.     <li>Ejecutar y evaluar los escenarios.     <li>Medir el progreso de las prueba.     </ol>     <p> Estas fases le ofrecen a los probadores una estructura en la que pueden agrupar los problemas relacionados y que deben resolver antes de pasar a la siguiente fase.</p>     <p>FASE 1: Modelar el Entorno del Software</p>     <p> La tarea del probador es simular la interacci&oacute;n entre el software y su entorno, para lo que debe identificar y simular las interfaces que utiliza el sistema, y enumerar las entradas que pueden circular por cada una de ellas. &Eacute;ste podr&iacute;a ser el asunto m&aacute;s importante que enfrentan y, teniendo en cuenta los diversos formatos de archivo, los protocolos de comunicaci&oacute;n y las terceras partes disponibles -interfaces de programaci&oacute;n de las aplicaciones- puede ser muy complicado. Las interfaces m&aacute;s comunes son:</p> <ul type = "square">     <li>Las interfaces humanas, incluyen todos los m&eacute;todos comunes con los que las personas se comunican con el software. La m&aacute;s destacada es la interfaz gr&aacute;fica de usuario <i>-Graphical User Interface GUI-</i>, pero todav&iacute;a se utilizan antiguos dise&ntilde;os como la interfaz de l&iacute;nea de comandos y la basada en men&uacute;s. Los posibles mecanismos de entrada que se deben considerar son los clics del rat&oacute;n, pulsaciones de teclado y entradas desde otros dispositivos. Los probadores deciden entonces c&oacute;mo organizar estos datos para comprender c&oacute;mo ensamblarlos en una prueba efectiva.     <li>Las interfaces de software, llamadas APIs <i>-Application Programming Interfaces-</i>, indican c&oacute;mo utiliza el software al sistema operativo, la base de datos o la librer&iacute;a, en tiempo de ejecuci&oacute;n. Los servicios que estas aplicaciones ofrecen se modelan como entradas de prueba, pero el desaf&iacute;o para los probadores es comprobar, no s&oacute;lo las probables, sino tambi&eacute;n las inesperadas. Por ejemplo, todos los desarrolladores esperan que el sistema operativo guarde los archivos por ellos, pero olvidan que el sistema operativo les puede informar que el medio de almacenamiento est&aacute; lleno por lo que, incluso, los mensajes de error deben probarse.     <li>Las interfaces del sistema de archivos, existen siempre que el software lea o escriba datos en archivos externos. Los desarrolladores deben escribir l&iacute;neas de c&oacute;digo de comprobaci&oacute;n de errores para determinar si el archivo contiene datos y formato adecuados. Por lo tanto, los probadores deben construir o generar archivos con contenido, que a la vez sea legal e ilegal, y archivos que contengan texto y formatos variados.     ]]></body>
<body><![CDATA[<li>Las interfaces de comunicaci&oacute;n, permiten el acceso directo a los dispositivos f&iacute;sicos como los controladores de dispositivos y otros sistemas embebidos y requieren un protocolo de comunicaci&oacute;n espec&iacute;fico. Para examinarlas, los probadores deben ser capaces de generar protocolos v&aacute;lidos e inv&aacute;lidos; adem&aacute;s de poder ensamblar muchas y diferentes combinaciones de comandos y datos, para aplicarlos a la interfaz bajo prueba, en el formato del paquete apropiado.     </ul>     <p> Luego, los probadores deben comprender las interacciones de usuario que est&aacute;n fuera del control del software bajo prueba, ya que las consecuencias pueden ser graves si el software no est&aacute; preparado. Ejemplos de situaciones que los probadores deben abordar son:</p> <ul type="square">     <li>Usando el sistema operativo un usuario elimina un archivo que otro usuario ten&iacute;a abierto, &iquest;qu&eacute; pasar&aacute; la pr&oacute;xima vez que el software intente accesar ese archivo?     <li>Un dispositivo se reinicia en medio de un proceso de comunicaci&oacute;n, &iquest;podr&aacute; el software darse cuenta de esto y reaccionar adecuadamente, o simplemente lo dejar&aacute; pasar?     <li>Dos sistemas compiten por duplicar servicios desde la API, &iquest;podr&aacute; la API atender correctamente ambos servicios?     </ul>     <p> Cada entorno &uacute;nico de aplicaci&oacute;n puede resultar en un n&uacute;mero significativo de interacciones de usuario que se debe probar.</p>     <p><b>Para tener en cuenta</b></p>     <p> Cuando una interfaz presenta problemas de tama&ntilde;o o de complejidad infinitos, los probadores se enfrentan a dos dificultades: 1) seleccionar cuidadosamente los valores para cualquier variable de entrada, y 2) decidir cu&aacute;l ser&aacute; la secuencia de las entradas. En la selecci&oacute;n de valores, deben determinar el de las variables individuales y asignar las combinaciones adecuadas cuando el programa acepta m&uacute;ltiples variables como entrada.</p>     ]]></body>
<body><![CDATA[<p> Frecuentemente utilizan la t&eacute;cnica <i>Boundary Value Partitioning</i> &#91;2&#93; para seleccionar valores individuales para las variables, en o alrededor de sus fronteras. Por ejemplo, probar los valores m&aacute;ximo, m&iacute;nimo y cero para un entero con signo es una prueba com&uacute;n, lo mismo que los valores que rodean cada una de estas particiones -por ejemplo, 1 y -1 que rodean la frontera cero-. Los valores entre las fronteras se tratan como el mismo n&uacute;mero: utilizar 16 &oacute; 16.000 no hace ninguna diferencia para el software bajo prueba.</p>     <p> Una cuesti&oacute;n m&aacute;s compleja es elegir los valores para m&uacute;ltiples variables procesadas simult&aacute;neamente, que potencialmente podr&iacute;an afectar a otras, y para lo que debe considerarse el producto que resulta de la combinaci&oacute;n de valores completo. Por ejemplo, para dos n&uacute;meros enteros: considerar ambos positivos, ambos negativos, uno positivo y uno cero, y as&iacute; sucesivamente &#91;3&#93;. Al decidir c&oacute;mo ser&aacute; la secuencia de entrada, los probadores tienen un problema de generaci&oacute;n de secuencia, por lo que deben tratar cada entrada f&iacute;sica y cada evento abstracto como s&iacute;mbolos en el alfabeto de un lenguaje formal y definir un modelo de ese lenguaje, que les permita visualizar el posible conjunto de pruebas e indagar c&oacute;mo se ajusta cada una a la prueba general. El modelo m&aacute;s com&uacute;n es un grafo o diagrama de estados, aunque existen muchas variaciones: otros modelos populares incluyen expresiones regulares y gramaticales, herramientas de la teor&iacute;a de lenguajes; menos utilizados son los modelos estoc&aacute;sticos de procesos y los algoritmos gen&eacute;ticos. Pero, en general, el modelo es una representaci&oacute;n que describe c&oacute;mo se combinan las entradas, y los s&iacute;mbolos de los eventos, para formar palabras y oraciones sint&aacute;cticamente v&aacute;lidas.</p>     <p> Esas oraciones son secuencias de entrada que se pueden aplicar al software bajo prueba. Un ejemplo de esto es, considerar la entrada <i>Filemenu.Open</i>, que involucra una caja de dialogo para seleccionar archivos; <i>Filename</i>, que representa la selecci&oacute;n -tal vez con clics del mouse- de un archivo existente, y <i>ClickOpen</i> y <i>ClickCancel</i>, que representan el bot&oacute;n accionado. La secuencia <i>Filemenu.Open Filename ClickOpen</i> es correcta, como muchas otras, pero la secuencia <i>ClickCancel Filemenu.Open</i> es incorrecta, ya que el bot&oacute;n de cancelaci&oacute;n no se puede presionar hasta que la caja de di&aacute;logo se haya invocado. Un modelo en lenguaje formal puede hacer una distinci&oacute;n entre las secuencias a aplicar.</p>     <p> Podemos representar el uso correcto de la caja de di&aacute;logo para seleccionar archivos, por ejemplo, en un editor de texto, con la expresi&oacute;n: <i>Filemenu.Open filename</i>* (<i>ClickOpen</i>|<i>ClickCancel</i>, en la que el asterisco representa el operador de clausura de Kleene &#91;4&#93; y demuestra que la acci&oacute;n <i>filename</i> puede ocurrir cero o m&aacute;s veces. Esta expresi&oacute;n indica que la primera entrada recibida es <i>Filemenu.Open</i>, seguida de cero o m&aacute;s selecciones de un <i>filename</i> -una combinaci&oacute;n de clics del rat&oacute;n y entradas de teclado- y que, a continuaci&oacute;n, se presiona el bot&oacute;n <i>Open</i> o <i>Cancel</i>. Este sencillo modelo representa todas las combinaciones de entrada que pueden suceder y si tienen sentido o no. Para completarlo, tendr&iacute;amos que representar secuencias para las interfaces de usuario y del sistema operativo. Adem&aacute;s, necesitar&iacute;amos una descripci&oacute;n de los archivos legales y corruptos para investigar a fondo la interacci&oacute;n del sistema de archivos, tarea que requiere usar ampliamente la l&oacute;gica, la descomposici&oacute;n y la abstracci&oacute;n.</p>     <p>FASE 2: Seleccionar Escenarios de Prueba</p>     <p> Muchos modelos de dominio y particiones de variables representan un n&uacute;mero infinito de escenarios de prueba, cada uno de los cuales cuesta tiempo y dinero. S&oacute;lo un subconjunto de ellos se puede aplicar en cualquier programa de desarrollo de software realista, as&iacute; que &iquest;c&oacute;mo hace un probador inteligente para seleccionar ese subconjunto? &iquest;17 es mejor valor de entrada que 34? &iquest;cu&aacute;ntas veces se debe seleccionar un <i>filename</i> antes de pulsar el bot&oacute;n <i>Open</i>? Estas cuestiones, que tienen muchas respuestas, actualmente se investigan activamente. Los probadores, sin embargo, prefieren una respuesta que se refiera a la cobertura de c&oacute;digo fuente o a su dominio de entrada y se orientan por: la cobertura de las declaraciones de c&oacute;digo -ejecutar cada l&iacute;nea de c&oacute;digo fuente por lo menos una vez-, o la cobertura de entradas -aplicar cada evento generado externamente-. Estos son los criterios m&iacute;nimos que utilizan para juzgar la completitud de su trabajo, por lo tanto, el conjunto de casos de prueba que muchos eligen es el que cumpla con sus metas de cobertura.</p>     <p> Pero si el c&oacute;digo y la cobertura de entrada son suficientes, los productos entregados deber&iacute;an tener muy pocos errores. En cuanto al c&oacute;digo, no son las declaraciones individuales las que interesan a los probadores, sino los caminos de ejecuci&oacute;n: secuencias de declaraciones de c&oacute;digo que representan un camino de ejecuci&oacute;n del software pero, desafortunadamente, existe un n&uacute;mero infinito de caminos. En cuanto al dominio de entrada, no les interesan las individuales, sino las secuencias de entrada que, en su conjunto, representan escenarios a los que el software debe responder, pero tambi&eacute;n existe un n&uacute;mero infinito de ellas.</p>     <p> Las pruebas se organizan desde dichos conjuntos infinitos hasta lograr, lo mejor posible, los criterios adecuados de datos de prueba; que se utilizan adecuada y econ&oacute;micamente para  representar cualquiera de esos conjuntos. <i>"Mejor"</i> y <i>"adecuadamente"</i> son subjetivos: los probadores t&iacute;picamente buscan el conjunto que garantizar&aacute; encontrar la mayor&iacute;a de los errores. Muchos usuarios y profesionales de aseguramiento de la calidad del software est&aacute;n interesados en que los probadores eval&uacute;en los escenarios de uso t&iacute;picos -cosas que ocurren con mayor frecuencia en el uso del producto-. Probar esos escenarios puede asegurar que el software funciona de acuerdo con lo especificado, y que se han detectado los errores m&aacute;s frecuentes.</p>     <p> Para citar un caso, consideremos nuevamente el ejemplo del editor de texto: para probar el uso t&iacute;pico, nos centraremos en la edici&oacute;n y el formato, puesto que es lo que la mayor&iacute;a de usuarios reales hace; no obstante, para encontrar errores, un lugar con mayor probabilidad son las caracter&iacute;sticas m&aacute;s dif&iacute;ciles de c&oacute;digo, como el dibujo de figuras y la edici&oacute;n de tablas.</p>     <p><b>Criterios de prueba de los caminos de ejecuci&oacute;n</b></p>     ]]></body>
<body><![CDATA[<p> Los criterios adecuados para datos de prueba se concentran en la cobertura de caminos de ejecuci&oacute;n o en la cobertura de secuencias de entrada, pero rara vez en ambos. El criterio de selecci&oacute;n de caminos de ejecuci&oacute;n m&aacute;s com&uacute;n es el de aquellos que cubran las estructuras de control. Por ejemplo: 1) Seleccionar un conjunto de casos de prueba que garantice que cada sentencia se ejecute al menos una vez y 2) Seleccionar un conjunto de casos de prueba que garantice que cada estructura de control <i>If, Case, While,...</i> se eval&uacute;e en cada uno de sus posibles caminos de ejecuci&oacute;n.</p>     <p> Sin embargo, el flujo de control es s&oacute;lo un aspecto del c&oacute;digo fuente. Actualmente, &iquest;Qu&eacute; software mueve datos de un lugar a otro? La familia de flujo de datos del criterio adecuado para datos de prueba describe la cobertura de estos datos &#91;5&#93;, como el seleccionar un conjunto de casos de prueba que garantice que cada estructura de datos se inicialice y que posteriormente se utilice.</p>     <p> Por &uacute;ltimo, es interesante la siembra de errores &#91;2&#93;, aunque tiene m&aacute;s atenci&oacute;n de los investigadores que de los probadores. En este m&eacute;todo, los errores se a&ntilde;aden intencionadamente en el c&oacute;digo fuente, y se dise&ntilde;an escenarios de prueba para encontrarlos. Lo ideal ser&iacute;a que al encontrar &eacute;stos, tambi&eacute;n se encontraran errores reales. Por lo tanto, es posible un criterio como el siguiente: seleccionar un conjunto de casos de prueba que exponga cada uno de los errores sembrados.</p>     <p><b>Criterios de prueba del dominio de entrada</b></p>     <p> El criterio para el rango de cobertura del dominio abarca desde la cobertura de una interfaz sencilla hasta la medici&oacute;n estad&iacute;stica m&aacute;s compleja:</p> <ul type="square">     <li>Elegir un conjunto de casos de prueba que contenga cada entrada f&iacute;sica.     <li>Seleccionar un conjunto de casos de prueba que garantice que cada interfaz de control -ventanas, men&uacute;s, botones, etc.- se recorra.     </ul>     <p> El criterio de discriminaci&oacute;n requiere una selecci&oacute;n aleatoria de secuencias de entrada hasta que, estad&iacute;sticamente, representen todo el dominio infinito de las entradas.</p> <ul type="square">     <li>Seleccionar un conjunto de casos de prueba que tenga las mismas propiedades estad&iacute;sticas que el dominio de entrada completo.     ]]></body>
<body><![CDATA[<li>Escoger un conjunto de rutas que puedan ser ejecutadas por un usuario t&iacute;pico.     </ul>     <p> Para resumir, los investigadores de pruebas estudian algoritmos para seleccionar conjuntos de prueba m&iacute;nimos que cumplan los criterios para caminos de ejecuci&oacute;n y dominios de entrada. La mayor&iacute;a de ellos est&aacute; de acuerdo en que es prudente utilizar varios criterios cuando se toman decisiones importantes para cada versi&oacute;n del producto. Los experimentos para comparar criterios adecuados para datos de prueba son necesarios, as&iacute; como los nuevos criterios. No obstante, por ahora, los probadores deben estar conscientes de qu&eacute; criterios integrar en su metodolog&iacute;a y comprender las limitaciones inherentes de esos criterios cuando reportan resultados.</p>     <p>FASE 3: Ejecutar y Evaluar los Escenarios</p>     <p> Una vez identificado el conjunto de casos de prueba adecuado, los probadores los convierten a formatos ejecutables, a menudo c&oacute;digo, de modo que los escenarios de prueba resultantes simulen la acci&oacute;n de un usuario t&iacute;pico. Debido a que los escenarios de prueba se ejecutan manualmente constituye un trabajo intensivo y, por tanto, propenso a errores, por lo que los probadores deben tratar de automatizarlos tanto como sea posible. En muchos entornos es posible aplicar autom&aacute;ticamente las entradas a trav&eacute;s del c&oacute;digo que simula la acci&oacute;n de los usuarios, y existen herramientas que ayudan a este objetivo. Pero la automatizaci&oacute;n completa requiere la simulaci&oacute;n de cada fuente de entrada, y del destino de la salida de todo el entorno operacional. A menudo, los probadores incluyen c&oacute;digo para recoger datos en el entorno simulado, como ganchos o seguros de prueba, con los que recogen informaci&oacute;n acerca de las variables internas, las propiedades del objeto, y otros. De esta forma, ayuda a identificar anomal&iacute;as y a aislar errores. Estos ganchos se eliminan cuando el software se entrega.</p>     <p> La evaluaci&oacute;n de escenarios, la segunda parte de esta fase, es f&aacute;cil de fijar pero dif&iacute;cil de ejecutar -es mucho menos automatizada-. La evaluaci&oacute;n implica la comparaci&oacute;n de las salidas reales del software, resultado de la ejecuci&oacute;n de los escenarios de prueba, con las salidas esperadas, tal y como est&aacute;n documentadas en la especificaci&oacute;n, que se supone correcta, ya que las desviaciones son errores. En la pr&aacute;ctica, esta comparaci&oacute;n es dif&iacute;cil de lograr. Te&oacute;ricamente, la comparaci&oacute;n -para determinar la equivalencia- de dos funciones arbitrarias computables, es irresoluble. Volviendo al ejemplo del editor de texto: si la salida se supone que es <i>"resaltar una palabra mal escrita"</i> &iquest;c&oacute;mo se puede determinar que se ha detectado cada instancia de faltas ortogr&aacute;ficas? Tal dificultad es la raz&oacute;n por la que la comparaci&oacute;n de la salida real versus la esperada, se realiza generalmente por un or&aacute;culo humano: un probador que monitorea visualmente la pantalla de salida y cuidadosamente analiza los datos que aparecen.</p>     <p><b>Dos enfoques para evaluar las pruebas</b></p>     <p> Al tratar con el problema de la evaluaci&oacute;n de la prueba los investigadores aplican dos enfoques: la formalizaci&oacute;n y el c&oacute;digo de prueba embebido.</p> <ul type="square">     <li>La formalizaci&oacute;n consiste en <i>"formalizar"</i> el proceso de escritura de las especificaciones, y la forma como, desde ellas, se derivan el dise&ntilde;o y el c&oacute;digo &#91;6&#93;. Tanto el desarrollo orientado por objetos, como el estructurado, tienen mecanismos para expresar formalmente las especificaciones, de forma que se simplifique la tarea de comparar el comportamiento real y el esperado. La industria generalmente le ha rehuido a los m&eacute;todos formales; no obstante, una buena especificaci&oacute;n, aunque informal, sigue siendo de gran ayuda. Sin una especificaci&oacute;n, posiblemente los probadores pueden encontrar s&oacute;lo los errores m&aacute;s obvios. Por otra parte, la ausencia de una especificaci&oacute;n redundar&iacute;a en una p&eacute;rdida significativa de tiempo cuando se  reporten anomal&iacute;as, no especificadas, como errores.     <li>Esencialmente existen dos tipos de c&oacute;digo de prueba embebido: 1) el m&aacute;s simple es el c&oacute;digo de prueba que expone algunos objetos de datos internos, o estados, de tal forma que un or&aacute;culo externo pueda juzgar su correctitud m&aacute;s f&aacute;cilmente. Al implementarse dicha funcionalidad es invisible para los usuarios. Los probadores pueden tener acceso a resultados del c&oacute;digo de prueba a trav&eacute;s, por ejemplo, de una prueba al API o a un depurador. 2) Un tipo m&aacute;s complejo de c&oacute;digo embebido tiene caracter&iacute;sticas de programa de auto-prueba &#91;7&#93;: a veces se trata de soluciones de codificaci&oacute;n m&uacute;ltiple para el problema, para chequear o escribir rutinas inversas que deshacen cada operaci&oacute;n. Si se realiza una operaci&oacute;n y luego se deshace, el estado del software resultante debe ser equivalente a su estado pre-operacional. En esta situaci&oacute;n el or&aacute;culo no es perfecto: podr&iacute;a haber un error, en ambas operaciones, en el que cada error enmascara a otro.     ]]></body>
<body><![CDATA[</ul>     <p><b>Pruebas de regresi&oacute;n</b></p>     <p> Despu&eacute;s que los probadores presentan con &eacute;xito los errores encontrados, generalmente los desarrolladores crean una nueva versi&oacute;n del software, en la que, supuestamente esos errores se han eliminado. La prueba progresa a trav&eacute;s de versiones posteriores del software hasta una que se selecciona para entregar. La pregunta es, &iquest;cu&aacute;ntas re-pruebas, llamadas pruebas de regresi&oacute;n, se necesitan en la versi&oacute;n n cuando se re-utilizan las pruebas ejecutadas sobre la versi&oacute;n <i>n-1</i>?</p>     <p> Cualquier selecci&oacute;n puede: a) arreglar s&oacute;lo el problema que fue reportado,  b) fallar al arreglar el problema reportado, c) arreglar el problema reportado pero interrumpir un proceso que antes trabajaba, o d) fallar al arreglar el problema reportado e interrumpir un proceso funcional. Teniendo en cuenta estas posibilidades, ser&iacute;a prudente volver a ejecutar todas las pruebas de la versi&oacute;n <i>n-1</i> en la versi&oacute;n n antes de probar nuevamente, aunque esta pr&aacute;ctica generalmente tiene un costo elevado &#91;8&#93;. Por otra parte, las nuevas versiones del software a menudo vienen con caracter&iacute;sticas y funcionalidades nuevas, adem&aacute;s de los errores corregidos, as&iacute; que las pruebas de regresi&oacute;n le quitar&iacute;an tiempo a las pruebas del c&oacute;digo nuevo. Para ahorrar recursos, los probadores deben trabajar en estrecha colaboraci&oacute;n con los desarrolladores para establecer prioridades, y reducir al m&iacute;nimo las pruebas de regresi&oacute;n.</p>     <p> Otro inconveniente de estas pruebas es que pueden, temporalmente, modificar el criterio adecuado para datos de prueba seleccionado en la fase anterior. Cuando se realizan pruebas de regresi&oacute;n, los probadores s&oacute;lo pretenden demostrar la ausencia de errores y forzar su aplicaci&oacute;n a que exhiba un comportamiento espec&iacute;fico. El resultado es que el criterio adecuado para datos de prueba, que hasta ahora gu&iacute;a la selecci&oacute;n de los casos de prueba, es ignorado. Por lo que, en su lugar, los probadores deben asegurarse de que el c&oacute;digo se haya corregido adecuadamente.</p>     <p><b>Asuntos relacionados</b></p>     <p> Los desarrolladores deber&iacute;an, idealmente, escribir c&oacute;digo teniendo en su mente las pruebas: si el c&oacute;digo va a ser dif&iacute;cil de verificar y validar, entonces se deber&iacute;a reescribir, de tal forma que pueda verificarse y validarse adecuadamente. Del mismo modo, una metodolog&iacute;a de prueba deber&iacute;a juzgarse de acuerdo con su contribuci&oacute;n a la automatizaci&oacute;n y al or&aacute;culo de la soluci&oacute;n de los problemas. Muchas metodolog&iacute;as propuestas ofrecen poca orientaci&oacute;n en cualquier de estas &aacute;reas. Otra preocupaci&oacute;n para los probadores, mientras ejecutan pruebas de verificaci&oacute;n o validaci&oacute;n, es c&oacute;mo coordinar con los desarrolladores las actividades de depuraci&oacute;n. Dado que los errores los identifican los probadores, pero los diagnostican los desarrolladores, puede suceder: 1) que su reproducci&oacute;n fracase y 2) que el escenario de prueba se ejecute nuevamente.</p>     <p> Que fracase la reproducci&oacute;n no es tan simple como parece, por lo que la respuesta obvia ser&iacute;a, por supuesto, volver a ejecutar la prueba fracasada y observar nuevamente el comportamiento de los resultados, aunque volver a efectuar una prueba no garantiza que se reproduzcan las mismas condiciones originales. Re-ejecutar un escenario requiere conocer con exactitud el estado del sistema operativo y cualquier software que lo acompa&ntilde;e -tal es el caso de las aplicaciones cliente-servidor que requieren la reproducci&oacute;n de las condiciones del entorno tanto en el cliente como en el servidor-. Adem&aacute;s, conocer el estado de automatizaci&oacute;n de la prueba, los dispositivos perif&eacute;ricos y cualquiera otra aplicaci&oacute;n de segundo plano, que se ejecute localmente o trav&eacute;s de la red y que podr&iacute;a afectar a la aplicaci&oacute;n bajo prueba. No es de extra&ntilde;ar que una de las frases que com&uacute;nmente se escucha en los laboratorios de prueba es: "Bueno, se comporta de forma diferente antes de..."</p>     <p>FASE 4: Medir el Progreso de las Pruebas</p>     <p> Supongamos que cualquier d&iacute;a, el jefe de un probador viene y le pregunta: "&iquest;Cu&aacute;l es el estado de sus pruebas?" Los probadores escuchan a menudo esta pregunta, pero no est&aacute;n bien preparados para responderla. La raz&oacute;n es que en la pr&aacute;ctica, medir las pruebas consiste en contar cosas: el n&uacute;mero de entradas aplicadas, el porcentaje de c&oacute;digo cubierto, el n&uacute;mero de veces que se ha invocado la aplicaci&oacute;n, el n&uacute;mero de veces que se ha terminado la aplicaci&oacute;n con &eacute;xito, el n&uacute;mero de errores encontrados y as&iacute; sucesivamente. La interpretaci&oacute;n de estas <i>"cuentas"</i> es dif&iacute;cil: &iquest;encontrar un mont&oacute;n de errores es buena o mala noticia? La respuesta podr&iacute;a ser: un alto n&uacute;mero de errores, que significa que la prueba se ejecut&oacute; completamente y que persisten muy pocos errores; o que simplemente que el software tiene un mont&oacute;n de errores y que, a pesar de que muchos fueron encontrados, muchos otros permanecen ocultos.</p>     ]]></body>
<body><![CDATA[<p> Los valores de estos conteos pueden dar muy pocas luces acerca de los avances de las pruebas, y muchos probadores alteran estos datos para dar respuesta a las preguntas, con lo que determinan la completitud estructural y funcional de lo que han hecho. Por ejemplo, para comprobar la completitud estructural los probadores pueden hacerse estas preguntas:</p> <ul type="square">     <li>&iquest;He probado para errores de programaci&oacute;n com&uacute;n? &#91;9&#93;     <li>&iquest;He ejercitado todo el c&oacute;digo fuente? &#91;2&#93;     <li>&iquest;He forzado a todos los datos internos a ser inicializados y utilizados? &#91;5&#93;     <li>&iquest;He encontrado todos los errores sembrados? &#91;2&#93;     </ul> Y para probar la completitud funcional: <ul type="square">     <li>&iquest;He tenido en cuenta todas las formas en las que el software puede fallar y he seleccionado casos de prueba que las muestren y casos que no lo hagan? &#91;9&#93;     <li>&iquest;He aplicado todas las posibles entradas? &#91;2&#93;     <li>&iquest;Tengo el dominio de los estados del software completamente explorado? &#91;1&#93;     <li>&iquest;He ejecutado todos los escenarios que espero que un usuario ejecute? &#91;10&#93;     ]]></body>
<body><![CDATA[</ul>     <p> Estas preguntas -fundamentalmente el criterio adecuado para datos de prueba- son &uacute;tiles para los probadores, empero, determinar cu&aacute;ndo detener las pruebas o cu&aacute;ndo est&aacute; listo un producto para su liberaci&oacute;n, es m&aacute;s complejo. Se necesitan medidas cuantitativas de la cantidad de errores que queden en el software, y de la probabilidad de que cualquiera de ellos sea descubierto por el usuario. Si los probadores pudieran lograr esta medida, sabr&iacute;an cuando parar las pruebas y ser&iacute;a posible que se acercaran cuantitativamente al problema de forma estructural y funcional.</p>     <p><b>Capacidad de prueba</b></p>     <p> Desde un punto de vista estructural, Jeffrey Voas &#91;11&#93; propuso la capacidad de prueba como una manera para determinar la complejidad de la aplicaci&oacute;n de una prueba: "la idea de que el n&uacute;mero de l&iacute;neas de c&oacute;digo determine la dificultad de la prueba es obsoleta, la cuesti&oacute;n es mucho m&aacute;s complicada, y es donde entra en juego la capacidad de prueba". Si un producto software tiene alta capacidad de prueba: 1) ser&aacute; m&aacute;s f&aacute;cil de probar y, por consiguiente, m&aacute;s f&aacute;cil de encontrar sus errores y 2) ser&aacute; posible monitorear las pruebas, por lo que los errores y las probabilidades de que se queden otros sin descubrir, disminuyen. Una baja capacidad de prueba requerir&aacute; muchas m&aacute;s pruebas para llegar a estas mismas conclusiones, y es de esperar que sea m&aacute;s dif&iacute;cil encontrar errores. La capacidad de prueba es un concepto convincente pero que apenas comienza a popularizarse, y todav&iacute;a no se han publicado suficientes datos acerca de su capacidad predictiva.</p>     <p><b>Modelos de fiabilidad</b></p>     <p> &iquest;Cu&aacute;nto durar&aacute; el software en ejecuci&oacute;n antes de que falle? &iquest;Cu&aacute;nto costar&aacute; el mantenimiento del software? Sin duda, es mejor encontrar respuestas a estas preguntas mientras todav&iacute;a se tenga el software en el laboratorio de pruebas. Desde un punto de vista funcional, los modelos de fiabilidad &#91;10&#93; -modelos matem&aacute;ticos de escenarios de prueba y datos de errores- est&aacute;n bien establecidos. Estos modelos pretenden predecir c&oacute;mo se comportar&aacute; el software en su entorno funcional, con base en c&oacute;mo se comport&oacute; durante las pruebas. Para lograr esto, la mayor&iacute;a de ellos requieren la especificaci&oacute;n de un perfil operativo: una descripci&oacute;n de c&oacute;mo se espera que los usuarios apliquen las entradas.</p>     <p> Para calcular la probabilidad de una falla, estos modelos hacen algunas suposiciones acerca de la distribuci&oacute;n de probabilidades subyacentes que regulan las ocurrencias de las anomal&iacute;as. Tanto los investigadores como los probadores expresan escepticismo acerca de que se puedan  ensamblar adecuadamente estos perfiles. Por otra parte, las hip&oacute;tesis hechas por los modelos de fiabilidad a&uacute;n no verifican te&oacute;rica o experimentalmente, salvo en dominios de aplicaci&oacute;n espec&iacute;ficos. Sin embargo, estudios de caso exitosos demuestran que estos modelos pueden ser cre&iacute;bles.</p>     <p><font face="verdana" size="3"><b>CONCLUSIONES Y TRABAJO FUTURO</b></font></p> <ul type="square">     <li>Las compa&ntilde;&iacute;as de software se enfrentan con serios desaf&iacute;os en la prueba de sus productos, cada vez m&aacute;s grandes, debido a que el software es cada vez m&aacute;s complejo.      <li>Lo primero y m&aacute;s importante que hay que hacer es reconocer la naturaleza compleja de las pruebas y tomarlas en serio: contratar a las personas m&aacute;s inteligentes que se pueda encontrar, ayudarlas a conseguir y/o brindarles las herramientas y el entrenamiento que requieran para aprender su oficio y escucharlos cuando hablan acerca de la calidad del software. Ignorarlos podr&iacute;a ser el error m&aacute;s costoso que nunca se haya cometido.      ]]></body>
<body><![CDATA[<li>Los investigadores en pruebas se enfrentan igualmente a estos desaf&iacute;os. Las compa&ntilde;&iacute;as de software est&aacute;n ansiosas por financiar buenas ideas de investigaci&oacute;n, pero la demanda fuerte es por m&aacute;s pr&aacute;ctica experimental y menos trabajo acad&eacute;mico. El tiempo para concatenar la investigaci&oacute;n acad&eacute;mica con los productos industriales es ahora.     <li>Las cuatro fases que estructuran la metodolog&iacute;a propuesta no se deben considerar como definitivas y &uacute;nicas, porque este es un campo en constante desarrollo e investigaci&oacute;n en el que est&aacute;n involucrados muchos investigadores y empresas.     </ul> <hr>     <p><font face="verdana" size="3"><b>REFERENCIAS BIBLIOGR&Aacute;FICAS</b></font></p>     <!-- ref --><p>&#91;1&#93; J. A. Whittaker & M. G. Thomason. "A Markov Chain Model for Statistical Software Testing". <i>IEEE Transactions on Software Engineering</i>, IEEE Trans. Software Eng., Vol. 20, No. 10, Oct. 1994, pp. 812-824.    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&#160;<a href="javascript:void(0);" onclick="javascript: window.open('/scielo.php?script=sci_nlinks&ref=000117&pid=S0121-4993201100030000600001&lng=','','width=640,height=500,resizable=yes,scrollbars=1,menubar=yes,');">Links</a>&#160;]<!-- end-ref --></p>     <!-- ref --><p>&#91;2&#93; G. J. Myers. <i>The Art of Software Testing</i>. New York: John Wiley & Sons, 1976, pp. 59-65.    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&#160;<a href="javascript:void(0);" onclick="javascript: window.open('/scielo.php?script=sci_nlinks&ref=000119&pid=S0121-4993201100030000600002&lng=','','width=640,height=500,resizable=yes,scrollbars=1,menubar=yes,');">Links</a>&#160;]<!-- end-ref --></p>     <!-- ref --><p>&#91;3&#93; T. J. Ostrand & M. J. Balcer. "The Category-Partition Technique for Specifying and Generating Functional Tests". <i>Communications of the ACM</i>. Comm. ACM, Vol. 31, No. 6, June 1988, pp. 676-686.    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&#160;<a href="javascript:void(0);" onclick="javascript: window.open('/scielo.php?script=sci_nlinks&ref=000121&pid=S0121-4993201100030000600003&lng=','','width=640,height=500,resizable=yes,scrollbars=1,menubar=yes,');">Links</a>&#160;]<!-- end-ref --></p>     ]]></body>
<body><![CDATA[<!-- ref --><p>&#91;4&#93; Kozen, D. "On Hoare Logic, Kleene Algebra and Types". <i>Studies in Epistemology, Logic, Methodology and Philosophy of Science</i>, Vol. 315, Aug. 2002, pp. 119-133.    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&#160;<a href="javascript:void(0);" onclick="javascript: window.open('/scielo.php?script=sci_nlinks&ref=000123&pid=S0121-4993201100030000600004&lng=','','width=640,height=500,resizable=yes,scrollbars=1,menubar=yes,');">Links</a>&#160;]<!-- end-ref --></p>     <!-- ref --><p>&#91;5&#93; S. Rapps & E. J. Weyuker. "Selecting Software Test Data Using Dataflow Information". <i>IEEE Transactions on Software Engineering</i>. IEEE Trans. Software Eng., Vol. 11, No. 4, Apr. 1985, pp. 367-375.    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&#160;<a href="javascript:void(0);" onclick="javascript: window.open('/scielo.php?script=sci_nlinks&ref=000125&pid=S0121-4993201100030000600005&lng=','','width=640,height=500,resizable=yes,scrollbars=1,menubar=yes,');">Links</a>&#160;]<!-- end-ref --></p>     <!-- ref --><p>&#91;6&#93; D. K. Peters & D. L. Parnas. "Using Test Oracles Generated from Program Documentation". <i>IEEE Transactions on Software Engineering</i>. IEEE Trans. Software Eng., Vol. 24, No. 3, Mar. 1998, pp. 161-173.    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&#160;<a href="javascript:void(0);" onclick="javascript: window.open('/scielo.php?script=sci_nlinks&ref=000127&pid=S0121-4993201100030000600006&lng=','','width=640,height=500,resizable=yes,scrollbars=1,menubar=yes,');">Links</a>&#160;]<!-- end-ref --></p>     <!-- ref --><p>&#91;7&#93; D. Knuth. "Literate Programming". <i>The Computer Journal</i>. The Comp. Jour., Vol. 27, No. 2, May 1984, pp. 97-111.    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&#160;<a href="javascript:void(0);" onclick="javascript: window.open('/scielo.php?script=sci_nlinks&ref=000129&pid=S0121-4993201100030000600007&lng=','','width=640,height=500,resizable=yes,scrollbars=1,menubar=yes,');">Links</a>&#160;]<!-- end-ref --></p>     <!-- ref --><p>&#91;8&#93; G. Rothermel & M. J. Harrold. "A Safe, Efficient Algorithm for Regression Test Selection". <i>In Proceedings of the Conference on Software Maintenance ICSM '93</i>. Montreal, Canada, Sept. 1993, pp. 358-367.    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&#160;<a href="javascript:void(0);" onclick="javascript: window.open('/scielo.php?script=sci_nlinks&ref=000131&pid=S0121-4993201100030000600008&lng=','','width=640,height=500,resizable=yes,scrollbars=1,menubar=yes,');">Links</a>&#160;]<!-- end-ref --></p>     ]]></body>
<body><![CDATA[<!-- ref --><p>&#91;9&#93; J. B. Goodenough & S. L. Gerhart. "Toward a Theory of Test Data Selection". <i>IEEE Transactions on Software Engineering</i>. IEEE Trans. Software Eng., Vol. 2, No. 2, June 1975, pp. 156-173.    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&#160;<a href="javascript:void(0);" onclick="javascript: window.open('/scielo.php?script=sci_nlinks&ref=000133&pid=S0121-4993201100030000600009&lng=','','width=640,height=500,resizable=yes,scrollbars=1,menubar=yes,');">Links</a>&#160;]<!-- end-ref --></p>     <!-- ref --><p>&#91;10&#93; J. D. Musa. "Software Reliability Engineered Testing". <i>Computer</i>, Vol. 29, No. 11, Nov. 1996, pp. 61-68.    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&#160;<a href="javascript:void(0);" onclick="javascript: window.open('/scielo.php?script=sci_nlinks&ref=000135&pid=S0121-4993201100030000600010&lng=','','width=640,height=500,resizable=yes,scrollbars=1,menubar=yes,');">Links</a>&#160;]<!-- end-ref --> </p>     <!-- ref --><p>&#91;11&#93; J. M. Voas. "PIE: A Dynamic Failure-Based Technique". <i>IEEE Transactions on Software Engineering</i>. IEEE Trans. Software Eng., Vol. 18, No. 8, Aug. 1992, pp. 717-727.    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&#160;<a href="javascript:void(0);" onclick="javascript: window.open('/scielo.php?script=sci_nlinks&ref=000137&pid=S0121-4993201100030000600011&lng=','','width=640,height=500,resizable=yes,scrollbars=1,menubar=yes,');">Links</a>&#160;]<!-- end-ref --></p> <hr> </font>      ]]></body><back>
<ref-list>
<ref id="B1">
<label>1</label><nlm-citation citation-type="">
<person-group person-group-type="author">
<name>
<surname><![CDATA[Whittaker]]></surname>
<given-names><![CDATA[J. A]]></given-names>
</name>
<name>
<surname><![CDATA[Thomason]]></surname>
<given-names><![CDATA[M. G]]></given-names>
</name>
</person-group>
<article-title xml:lang="en"><![CDATA[A Markov Chain Model for Statistical Software Testing]]></article-title>
<source><![CDATA[]]></source>
<year>Oct.</year>
<month> 1</month>
<day>99</day>
<volume>20</volume>
<numero>10</numero>
<issue>10</issue>
<page-range>812-824</page-range></nlm-citation>
</ref>
<ref id="B2">
<label>2</label><nlm-citation citation-type="book">
<person-group person-group-type="author">
<name>
<surname><![CDATA[Myers]]></surname>
<given-names><![CDATA[G. J]]></given-names>
</name>
</person-group>
<source><![CDATA[The Art of Software Testing]]></source>
<year>1976</year>
<page-range>59-65</page-range><publisher-name><![CDATA[New York: John Wiley & Sons]]></publisher-name>
</nlm-citation>
</ref>
<ref id="B3">
<label>3</label><nlm-citation citation-type="">
<person-group person-group-type="author">
<name>
<surname><![CDATA[Ostrand]]></surname>
<given-names><![CDATA[T. J]]></given-names>
</name>
<name>
<surname><![CDATA[Balcer]]></surname>
<given-names><![CDATA[M. J]]></given-names>
</name>
</person-group>
<article-title xml:lang="en"><![CDATA[The Category-Partition Technique for Specifying and Generating Functional Tests]]></article-title>
<source><![CDATA[]]></source>
<year>June</year>
<month> 1</month>
<day>98</day>
<volume>31</volume>
<numero>6</numero>
<issue>6</issue>
<page-range>676-686</page-range></nlm-citation>
</ref>
<ref id="B4">
<label>4</label><nlm-citation citation-type="">
<person-group person-group-type="author">
<name>
<surname><![CDATA[Kozen]]></surname>
<given-names><![CDATA[D]]></given-names>
</name>
</person-group>
<article-title xml:lang="en"><![CDATA[On Hoare Logic, Kleene Algebra and Types]]></article-title>
<source><![CDATA[]]></source>
<year>Aug.</year>
<month> 2</month>
<day>00</day>
<volume>315</volume>
<page-range>119-133</page-range></nlm-citation>
</ref>
<ref id="B5">
<label>5</label><nlm-citation citation-type="">
<person-group person-group-type="author">
<name>
<surname><![CDATA[Rapps]]></surname>
<given-names><![CDATA[S]]></given-names>
</name>
<name>
<surname><![CDATA[Weyuker]]></surname>
<given-names><![CDATA[E. J]]></given-names>
</name>
</person-group>
<article-title xml:lang="en"><![CDATA[Selecting Software Test Data Using Dataflow Information]]></article-title>
<source><![CDATA[]]></source>
<year>Apr.</year>
<month> 1</month>
<day>98</day>
<volume>11</volume>
<numero>4</numero>
<issue>4</issue>
<page-range>367-375</page-range></nlm-citation>
</ref>
<ref id="B6">
<label>6</label><nlm-citation citation-type="">
<person-group person-group-type="author">
<name>
<surname><![CDATA[Peters]]></surname>
<given-names><![CDATA[D. K]]></given-names>
</name>
<name>
<surname><![CDATA[Parnas]]></surname>
<given-names><![CDATA[D. L]]></given-names>
</name>
</person-group>
<article-title xml:lang="en"><![CDATA[Using Test Oracles Generated from Program Documentation]]></article-title>
<source><![CDATA[]]></source>
<year>Mar.</year>
<month> 1</month>
<day>99</day>
<volume>24</volume>
<numero>3</numero>
<issue>3</issue>
<page-range>161-173</page-range></nlm-citation>
</ref>
<ref id="B7">
<label>7</label><nlm-citation citation-type="">
<person-group person-group-type="author">
<name>
<surname><![CDATA[Knuth]]></surname>
<given-names><![CDATA[D]]></given-names>
</name>
</person-group>
<article-title xml:lang="en"><![CDATA[Literate Programming]]></article-title>
<source><![CDATA[]]></source>
<year>May </year>
<month>19</month>
<day>84</day>
<volume>27</volume>
<numero>2</numero>
<issue>2</issue>
<page-range>97-111</page-range></nlm-citation>
</ref>
<ref id="B8">
<label>8</label><nlm-citation citation-type="">
<person-group person-group-type="author">
<name>
<surname><![CDATA[Rothermel]]></surname>
<given-names><![CDATA[G]]></given-names>
</name>
<name>
<surname><![CDATA[Harrold]]></surname>
<given-names><![CDATA[M. J]]></given-names>
</name>
</person-group>
<source><![CDATA[A Safe, Efficient Algorithm for Regression Test Selection]]></source>
<year>Sept</year>
<month>. </month>
<day>19</day>
<page-range>358-367</page-range><publisher-loc><![CDATA[Montreal ]]></publisher-loc>
</nlm-citation>
</ref>
<ref id="B9">
<label>9</label><nlm-citation citation-type="">
<person-group person-group-type="author">
<name>
<surname><![CDATA[Goodenough]]></surname>
<given-names><![CDATA[J. B]]></given-names>
</name>
<name>
<surname><![CDATA[Gerhart]]></surname>
<given-names><![CDATA[S. L]]></given-names>
</name>
</person-group>
<article-title xml:lang="en"><![CDATA[Toward a Theory of Test Data Selection]]></article-title>
<source><![CDATA[]]></source>
<year>June</year>
<month> 1</month>
<day>97</day>
<volume>2</volume>
<numero>2</numero>
<issue>2</issue>
<page-range>156-173</page-range></nlm-citation>
</ref>
<ref id="B10">
<label>10</label><nlm-citation citation-type="">
<person-group person-group-type="author">
<name>
<surname><![CDATA[Musa]]></surname>
<given-names><![CDATA[J. D]]></given-names>
</name>
</person-group>
<article-title xml:lang="en"><![CDATA[Software Reliability Engineered Testing]]></article-title>
<source><![CDATA[]]></source>
<year>Nov.</year>
<month> 1</month>
<day>99</day>
<volume>29</volume>
<numero>11</numero>
<issue>11</issue>
<page-range>61-68</page-range></nlm-citation>
</ref>
<ref id="B11">
<label>11</label><nlm-citation citation-type="">
<person-group person-group-type="author">
<name>
<surname><![CDATA[Voas]]></surname>
<given-names><![CDATA[J. M]]></given-names>
</name>
</person-group>
<article-title xml:lang="en"><![CDATA[PIE: A Dynamic Failure-Based Technique]]></article-title>
<source><![CDATA[]]></source>
<year>Aug.</year>
<month> 1</month>
<day>99</day>
<volume>18</volume>
<numero>8</numero>
<issue>8</issue>
<page-range>717-727</page-range></nlm-citation>
</ref>
</ref-list>
</back>
</article>
