|
| |
Estudio de frameworks para el desarrollo de pruebas de software. Pruebas de unidad
Resumen: La producción de software en nuestro país es una ciencia joven la cual se ha impulsado rápidamente gracias al desarrollo de las ciencias informáticas en las universidades de nuestro país y a entidades surgidas debido...
Publicación enviada por Irina Elena Argota Vega y Alain Bedoya Reyes
RESUMEN
La producción de software en nuestro país es una ciencia joven la cual se ha
impulsado rápidamente gracias al desarrollo de las ciencias informáticas en las
universidades de nuestro país y a entidades surgidas debido al Ministerio de la
Informática y de las Comunicaciones (MIC) con “el objetivo preciso de impulsar,
facilitar y ordenar el uso masivo de servicios y productos de las Tecnologías de
la Información, las Comunicaciones, la Electrónica y la Automatización para
satisfacer las expectativas de todas las esferas de la sociedad”.
Este desarrollo en la producción de software se ha estimulado con la fundación
de la Universidad de las Ciencias Informáticas (UCI), con lo cual se espera un
progreso acelerado de las Tecnologías de la Información y las Comunicaciones
(TIC).
El aseguramiento de la calidad se ha convertido en una necesidad de prioridad
para las organizaciones que desarrollan software porque en la medida que avanza
la tecnología, es más exigente la calidad del software requerida actualmente por
las empresas encargadas de medir la calidad, y para satisfacer estos
requerimientos de calidad uno de los métodos más utilizados por los
desarrolladores es el proceso de desarrollo de Pruebas de Software.
Hoy en día, se podría decir que las pruebas de software han llegado a ser más
fáciles y más difíciles al mismo tiempo. Las pruebas de software son más
difíciles por la gran cantidad de lenguajes de programación, sistemas operativos
y las plataformas de hardware en las que se encuentran envueltas. Las pruebas de
software son más fáciles, en algunos casos, por que los sistemas operativos y
software, son mucho más sofisticados y proveen intrínsicamente buenas rutinas de
pruebas, que pueden ser incorporadas en las aplicaciones, sin la necesidad que
el programador las desarrolle desde cero.(MYERS 2004)
Entre las Pruebas de Software que se le pueden realizar a un sistema determinado
están las Pruebas de Unidad. Sobre los frameworks que se pueden utilizar para el
desarrollo de las mismas, dentro del mundo del software libre, se centrará la
presente investigación.
Palabras claves: Pruebas de Software, Framework, Pruebas de unidad, calidad de
software.
INTRODUCCIÓN
Actualmente la prueba de software se utiliza en todos los desarrollos de la
industria, siendo inconcebible que un cliente reciba un sistema software que no
haya sido probado. Pese a su enorme impacto en el coste de desarrollo, es una de
las líneas de trabajo que muchos programadores aún consideran clasificable como
un arte y, por tanto, como difícil de conceptualizar.
En el mundo existen múltiples metodologías para el desarrollo de software, pero
sin duda alguna todas tienen implícito el proceso de desarrollo de pruebas, el
cual está centrado en el objetivo de encontrar defectos a un software; puede ser
por razones de depuración o de aceptación del mismo.
El objetivo general que se desea alcanzar para darle cumplimiento al presente
trabajo es: realizar un estudio de frameworks para el desarrollo de pruebas de
software.
De ahí que para el cumplimiento de este objetivo general se deriven los
siguientes objetivos específicos:
· Definición de conceptos involucrados con el tema de Pruebas de Software.
· Investigar sobre los pasos para la realización de pruebas de unidad.
· Investigar sobre los frameworks existentes que utilicen el lenguaje de
programación C++.
· Llegar a conclusiones del framwork escogido a partir de la experiencia
adquirida.
1. Conceptos generales.
1.1 Prueba de Software
La Prueba o Testeo de Software, es un procedimiento llevado a cabo para
identificar posibles fallos de implementación, calidad, o usabilidad de un
programa. Básicamente es una fase en el desarrollo de software cuyo objetivo es
probar las funcionalidades de la aplicación construida.
La prueba de software es un proceso que corre en paralelo al proceso de
desarrollo de software, y que se realiza por el convencimiento de que todo
sistema debe ser inspeccionado o probado con el objetivo de establecer si el
nivel de calidad requerido es alcanzado.
Es un elemento que a menudo se refiere como verificación y validación. En (PRESSMAN
2005) se plantea que “la verificación se refiere al conjunto de actividades que
aseguran que el software implementa correctamente una función específica. La
validación se refiere a un conjunto diferente de
actividades que aseguran que el software construido se ajusta a los requisitos
del cliente”.
1.2 Pruebas de Unidad
Es el proceso de verificación en la menor unidad del diseño del software: el
módulo, normalmente realizada por el propio personal de desarrollo en su
entorno. Usando la descripción del diseño del procedimiento como guía, se
prueban los caminos de control importantes, con el fin de descubrir errores
dentro del límite del módulo.
Antes de iniciar cualquier otra prueba es preciso probar el flujo de datos de la
interfaz del módulo. Si los datos no fluyen correctamente, todas las demás
pruebas no tienen sentido. (PRESSMAN 2005)
Lista de comprobaciones para la prueba de Interfaces.
1. ¿Es igual el número de parámetros de entrada al número de argumentos?
2. ¿Coinciden los atributos de los parámetros y los argumentos?
3. ¿Coinciden los sistemas de unidades de los parámetros y de los argumentos?
4. ¿Son iguales los números de los argumentos transmitidos a los módulos de
llamada que el número de parámetros?
5. ¿Son iguales los atributos de los argumentos transmitidos a los
módulos de llamada y los atributos de los parámetros?
6. ¿Son iguales los sistemas de unidades de los argumentos transmitidos a los
módulos de llamada y de los parámetros?
7. ¿Son correctos el número de los atributos y el orden de los argumentos de las
funciones incorporadas?
8. ¿Existen referencias a parámetros que no estén asociados con el punto de
entrada actual?
9. ¿Entran sólo argumentos alterados?
10. ¿Son consistentes las definiciones de variables globales entre los módulos?
11. ¿Se pasan las restricciones como argumentos?
La pruebas del camino básico y de bucles son técnicas muy efectivas para
descubrir una gran cantidad de errores en los caminos.
Este nivel de prueba se deben descubrir errores tales como:
l Comparaciones entre tipos de datos distintos.
l Operadores lógicos o procedencia incorrecta.
l Igualdad esperada cuando los errores de precisión la hacen poco probable.
l Las variables o comparaciones incorrectas.
l Terminaciones de bucles inapropiadas o inexistentes.
l Fallo de salida cuando se encuentra una iteración divergente.
l Bucles que manejan variables modificadas de forma inapropiada.
1.2.1 Procedimiento para la Prueba de Unidad. (PRESSMAN 2005)
Debido a que un módulo no es un programa independiente, se debe desarrollar,
para cada prueba de unidad, un software que controle y/o resguarde. En la
mayoría de las aplicaciones, un controlador no es más que un programa principal
que acepta los datos de la prueba, pasa estos datos al módulo (a ser probado) e
imprime los resultados importantes. Los resguardados sirven para remplazar
módulos que estás subordinados (llamados por) el componente que hay que probar.
Un resguardo o un subprograma simulado usa la interfaz del módulo subordinado,
lleva a cabo una mínima manipulación de datos, imprime una verificación de
entrada y devuelve control al módulo de prueba que lo invocó.
Los controladores y los resguardos son una sobrecarga de trabajo. Es decir,
ambos son software que debe desarrollarse (normalmente no se aplica un diseño
formal) pero que no se entrega con el producto de software final. Si los
controladores y resguardos son sencillos, el trabajo adicional es relativamente
pequeño. Desgraciadamente, muchos componentes no pueden tener una adecuada
prueba unitaria con un sencillo software adicional. En tales casos, la prueba
completa se pospone hasta que se llegue al paso de prueba de integración (donde
también se usan controladores o esguardos).
La prueba de unidad se simplifica cuando se diseña un módulo con un alto grado
de cohesión. Cuando un módulo sólo realiza una función, se reduce el número de
casos de prueba y los errores se pueden predecir y descubrir más fácilmente.
Ventajas de la utilización de este tipo de prueba.
Las ventajas de usar este tipo de pruebas son muchas, entre ellas se pueden
plantear:
l Los errores serán más fáciles de localizar.
l Los errores estarán más acotados, ya que se sabrá qué módulos no están pasando
las pruebas unitarias.
l Se reducen los errores ocurridos como consecuencia de la eliminación de otros
errores, ya que aplicando las pruebas unitarias se pueden ejecutar nuevamente
las pruebas y comprobar que el módulo funciona de la forma esperada.
l Con pruebas unitarias, la mayoría de los errores de programación se detectan
durante la propia etapa de programación, lo que tiene gran valor, ya que
mientras más tiempo permanezca un error en el sistema, más tiempo requerirá
eliminarlo y más repercusiones acarreará en otras secciones del programa.
l Las pruebas funcionales se hacen más sencillas, ya que solo se comprobarán la
correcta relación entre las distintas unidades.
l El programador escribe código de una forma más lógica, pues lo diseña mucho
más simple y accesible para poder realizarle las pruebas.
1.2.2 Guía de pasos para la realización de las Pruebas de Unidad.
1) Debe comenzar inmediatamente se vayan construyendo los módulos y serán
desarrolladas por las mismas personas que desarrollaron roles de programadores.
2) Deben ser aplicadas a todo el código.
3) Se recomienda utilizar alguna herramienta de prueba para la automatización de
las mismas.
4) Deben aplicarse métodos de caja negra para probar la funcionalidad de los
módulos (clases, procedimientos, funciones, métodos, objetos, o componentes).
5) Identificar las clases de equivalencia (de datos válidos y de datos no
válidos o erróneos).
6) Identificar casos de prueba a partir de clases de equivalencia.
7) Explorar las condiciones límites de un programa mediante la técnica de
análisis de valores límites.
8) Utilizar la técnica de conjetura de errores para determinar los errores que
más se repiten y en función de esta elaborar los casos de prueba.
9) Ejecutar los casos generados hasta el momento y analizar la cobertura
obtenida para determinar el cumplimiento de los objetivos de prueba trazados.
10) Los módulos que no estén pasando las pruebas deben ser informados al equipo
de desarrollo y una vez depurados estos errores deben ejecutarse nuevamente los
casos de prueba para verificar que la reparación no ha causado otros errores.
11) Delimitar los errores y sus posibles causas, de este modo el probador podrá
asegurarse de que no se repite el error en otras secciones del programa y podrá
asegurarse también de que los cambios no introducen un comportamiento no deseado
o errores adicionales.
12) Según los principios de las pruebas enunciados por Myers, se recomienda que
si se detectan muchos fallos en un módulo, lo mejor sería desecharlo, diseñarlo
y codificarlo nuevamente.
13) Los resultados obtenidos con la ejecución de las pruebas deben ser
documentados debidamente en el registro de defectos.
2. Comparación de Frameworks para la realización de las Pruebas de Unidad.
Un framework es una estructura de soporte auxiliar en la cual un proyecto de
software puede ser organizado y desarrollado. Típicamente, un framework puede
incluir soporte de programas, bibliotecas y un lenguaje script entre otros
softwares para ayudar a desarrollar y unir los diferentes componentes de un
proyecto.
Para la realización de pruebas de unidad, se investigaron frameworks que
utilizaran C++ como lenguaje para la programación.
2. Comparación de Frameworks para la realización de las Pruebas de Unidad.
2.1 Criterios para la comparación de los frameworks
1. Mínima cantidad de código a la hora de agregar nuevas pruebas. Si se
necesitan hacer muchas pruebas, mientras menos se tenga que teclear para agregar
una nueva mejor será, pues así se evita muchas líneas de código y la duplicación
de estas. El framework en el cual menos se tenga que implementar más eficiente
será a la hora realizar las pruebas en el tiempo establecido.
2. Facilidad para modificarse y ser portable. No debe tener ninguna dependencia
con las bibliotecas no estándar, y si es posible no debe basarse en
características exóticas de C++.
3. Accesorios de ayuda. Es mas fácil usar solamente una aserción por prueba, las
hace más fácil de entender y mantener, pero requiere el uso pesado de
accesorios. Un framework sin ellos se elimina inmediatamente.
4. Manejadores de excepciones y de recuperación. No es bueno que paren las
pruebas por cierto código que fue ejecutado, porque hubo un acceso a cierta
posición de memoria inválida o por una división por cero. El framework de prueba
debe reportar las excepciones y tanta información sobre ellas como sea posible.
Debe también ser posible correrlo otra vez y tener la ruptura de depuración en
el lugar en donde la excepción fue accionada.
5. Buena funcionalidad del ASSERT. De fallar una declaración, el ASSERT debe
imprimir el contenido de las variables que fueron comparadas. Debe también
proporcionar un buen sistema de ASSERT, el cual proporcione casi todas las
posibles comparaciones y los diferentes tipos de datos, así como comprobar si
las excepciones fueron o no fueron lanzadas, y sus tipos.
6. Apoya diversas salidas. Debe tener un formato que puedan entender y analizar
el IDEs que se esté utilizando, para que sea más fácil de navegar a cualquier
fallo en la prueba como si fueran errores de la sintaxis. Pero también debe
tener maneras de exhibir diversas salidas.
7. Grupos de accesorios:. De esto depende el buen funcionamiento de un
frameworks de prueba. Las pruebas deben formar parte de una suite o súper-clase
de prueba de la cual hereden las que implementan los probadores.
Teniendo como guía los criterios presentados a anteriormente se analizaron los
siguientes frameworks:
2.2 CppUnit
El CppUnit, es probablemente framework de unidad de prueba más utilizada en C++.
En un principio CppUnit fue bastante complicada de utilizar, ya sea con
funciones MFC (Windows) o trabajando GUI (Linux). CppUnit ya cuenta con gran
bibliografía y el perfeccionamiento de la misma hace que el trabajo con esta
unit se haya vuelto más factible.
1. Mínima cantidad de código a la hora de agregar nuevas pruebas: Es una de sus
principales ventajas ya que requiere trabajo aún para la prueba más simple.
2. Facilidad para modificarse y ser portable. Se ejecuta sobre Windows y Linux,
y la funcionalidad está bien modulada.
3. Accesorios de ayuda: Si se quiere que los objetos sean creados antes de cada
prueba, se necesita que sean los objetos sean asignados dinámicamente en la
función setup ().
4. Manejadores de excepciones y de recuperación: Utiliza el concepto de
protectores. CppUnit intenta captar e identificar las excepciones por defecto,
aunque se pueden crear excepciones propias para que sean combinadas con las ya
existentes.
5. Buena funcionalidad del ASSERT: Tiene un sistema de pocas declaraciones
acertadas, incluyendo la de comparación de números de tipo punto-flotante.
6. Apoya diversas salidas: Tiene bien definida la funcionalidad para las salidas
(Lo cual muestra los resultados de las pruebas) así como para los listeners (los
cuales obtienen notificaciones mientras las pruebas ocurren).
7. Grupos de accesorios: Si.
2.3 Boost.Test
Boot_Test no es exclusivamente un framework de unidades de prueba, sino que
tiene otras prestaciones. No está basado en la familia XUNIT. Boot_Test es una
librería con una gran potencialidad, tiene gran soporte para el manejo de
excepciones y las declaraciones avanzadas, además de otras funcionalidades
únicas como la ayuda para el chequeo de lazos infinitos.
1. Mínima cantidad de código a la hora de agregar nuevas pruebas: requiere un
mínimo de trabajo para adicionar nuevas pruebas, se acerca más al framework de
prueba ideal que el CppUnit.
2. Facilidad para modificarse y ser portable: Se obtienen marcas combinadas por
la misma razón que en el CppUnit. Esta librería permite portabilidad y un mejor
trabajo sobre Linux que la mayoría de los frameworks. Hacerles modificaciones a
la Boos.Test puede convertirse en algo complejo.
3. Accesorios de ayuda: Boot.Test evita la estructura de montaje/desmontaje de
las pruebas del NUNIT a favor de los constructores/destructores de C++. Una de
las grandes ventajas de lo descrito anteriormente es que no se necesita la
creación de accesorios de objetos dinámicos y en cambio se puede poner el
accesorio completo en la pila, o sea, para referirse a las variables hay que
hacerlo a través de nombres de objetos. Se haría mejor si el accesorio se
pudiera configurar en la pila a través de la macro BOOST_AUTO_UNIT_TEST.
4. Manejadores de excepciones y de recuperación: No solo se hace el manejo de
excepciones de manera correcta sino que imprime información sobre ellas, captura
las excepciones de Linux y tiene líneas de comandos que deshabilitan el manejo
de estas, permitiendo así capturar los problemas fácilmente.
5. Buena funcionalidad del ASSERT: Tiene declaraciones para cualquier tipo de
operación deseada, ya sea de igualdad, menor que, mayor que, entre otras. Tiene
ayuda para el chequeo de excepciones que se hayan lanzado. Las declaraciones
acertadas correctamente imprimen el contenido de las variables que están siendo
chequeadas.
6. Apoya diversas salidas: Probablemente lo tenga pero no es exactamente trivial
de cambiar.
7. Grupos de accesorios: Al crear el conjunto de ayudas se requiere una cantidad
X de declaraciones y modificaciones en el ejecutor de las pruebas.
2.4 Unit++.
El Unit++ se basa más en el uso del C++ para su implementación interna que
CppUnit. Esto no es muy recomendable, pues los expertos sugieren que la
vinculación del framework con el C++ solo sea a través de su utilización en la
ejecución de las pruebas y que la base del mismo sea un lenguaje que facilite su
uso, pues con C++ solo se logran dependencias externas y macros difíciles de
entender. Su documentación es pobre y carece de ejemplos que ilustren su
funcionamiento.
2.5 NanoCppUnit
Es un framework de prueba dirigido solamente a las plataformas Windows. El
código de fuente no se estructura muy bien, está lleno de macros de poco
entendimiento, haciendo difícil agregarle nuevas características como tipos de
la salida definidas por el usuario. Tiene un empaquetado tremendo del framework,
lo cual dificulta el trabajo con él. Escasa bibliografía en internet sobre este
framework.
2.6 CxxTest
Cxxtest utiliza el lenguaje Perl para generar código C++. Analiza el código de
las pruebas implementadas por el usuario y genera a un corredor de prueba en C++
que se ejecuta directamente desde las pruebas del usuario. Por su flexibilidad
es posible hacer pruebas rigurosas con código sencillo. Su único requerimiento
es instalar Perl y que este se ejecute correctamente.
1. Minima cantidad de código a la hora de agregar nuevas pruebas: Es muy bueno.
Es mejor que los frameworks mencionados ateriormente por su sencillez y
fortaleza. Permite crear pruebas sin la necesitad de declarar una clase
contenedora.
2. Facilidad para modificarse y ser portable. CxxTest requiere el sistema más
simple de características de lenguaje. No necesita librerías externas. También
se distribuye simplemente como sistema de archivos de cabecera, por lo que no
hay necesidad de compilar en una biblioteca separada o algo similar.
Funcionalmente es como un pozo separado del código de fuente original, así que
la realización de modificaciones es bastante directa.
3. Accesorios de ayuda. Crear los accesorios es bastante directo y apenas
requiere la herencia de una clase, pudiendo crear todas las funciones que se
necesiten.
4. Manejadores de excepciones y de recuperación buenos. Captura todas las
excepciones e imprime la información sobre ellas, de cualquier tipo de error,
aunque no captura excepciones del sistema con Linux. Se puede volver a efectuar
fácilmente las pruebas. También brinda un paquete de macro el cual permite la
captura de excepciones por el usuario siempre que lo necesite.
5. Buena funcionalidad del ASSERT. Implementa una suite de prueba completa, con
funciones assert fáciles de entender, incluyendo las de manejo de excepciones,
la comprobación de predicados y las relaciones arbitrarias. Incluso se pueden
imprimir warnings, los cuales pueden ser usados para diferenciar dos partes del
código llamado en una misma prueba o se pueden imprimir mensajes hechos por el
usuario.
6. Soporte a diferentes salidas. Da soporte a diversas salidas, pasándole un
parámetro que indique cual es el tipo de salida que el usuario quiere que
ejecute el proceso del Perl.
7. Un buen soporte de Suite. Si, todas las pruebas forman parte de una suite.
3. Framework escogido a partir de la experiencia.
En el proceso de escoger un framework para realizar las pruebas de unidad,
primero se tuvo en cuanta los aspectos antes mencionados. En segundo lugar, con
motivo a los requerimientos del ambiente de trabajo: plataforma GNU/Linux. Y la
plataforma de software Eclipse (plataforma utilizada para desarrollar entornos
de desarrollo integrados) en la cual se implementaron las clases que se desean
probar, se escogió el Cxxtest, el cual se integra bien al Eclipse, siendo de
fácil instalación y uso.
Con algunas clases con método de entradas y salidas se probó la macro
TS_ASSERT_EQUALS, posibilitando respuestas esperadas declaradas con anterioridad
en el diseño de las pruebas de unidad.
CONCLUSIONES
l Cada módulo que se desarrolle puede tener una batería de pruebas de unidad que
comprueben que funciona correctamente a lo largo del tiempo. Esto combinado con
un proceso de integración continua permite conocer el grado de funcionamiento
del proyecto completo.
l CxxTest, framework sencillo de utilizar, tiene una gran suite de pruebas y
mucha documentación en internet. Se puede utilizar en ambiente GNU/Linux. Su
único inconveniente es que necesita de Perl para que funcione, pero esto se
logra de forma sencilla y es, además, su principal potencialidad.
BIBLIOGRAFÍA
1. Games from Within. http://www.gamesfromwithin.com/articles
2. IVAR JACOBSON, G. B., JAMES RUMBAUGH. Capítulo 11: PRUEBA. en: El proceso
unificado de desarrollo de software. La Habana, Félix Varela, 2004. 1: 435.p.
3. MYERS, G. J. The Art of Software Testing. Hoboken, New Jersey., John Wiley &
Sons, Inc., 2004.
4. PRESSMAN, R. S. Capítulo 17: Técnicas de Prueba del Software. en: Ingeniería
del Software. Quinta Edición. La Habana, Félix Varela, 2005. Parte 1: 601.p.
5. Wikipedia, Enciclopedia Libre, http://es.wikipedia.org/wiki/
Datos del Autor
Nombre y Apellidos: Irina Elena Argota Vega
Categoria: Ingeniero en Ciencias Informáticas.
Año de Graduación: 2007
Profesión: Profesor de la Universidad de Ciencias Informáticas
Correo electrónico: iargota@uci.cu
Lugar de Procedencia: Santiago de Cuba, Cuba.
Compartir 
Publicación enviada por Irina Elena Argota Vega y Alain Bedoya Reyes
Contactar mailto:iargota@uci.cu
Código ISPN de la Publicación EkpyupElyukduVBIfY
Publicado Monday 24 de March de 2008
Ultimas Publicaciones en ilustrados.com
ilustrados.com nace con el fin difundir el conocimiento publicando trabajos de investigación, monografias, tesis, presentaciones powerpoint y afines. Publicar trabajos en ilustrados.com ha alcanzado prestigio y reconocimiento internacional siendo cada vez más el número de académicos, empresas, investigadores, científicos que consultan las publicaciones de nuestro portal.
|