trabajo final lisibonny beato

Upload: lisibonny-beato-castro

Post on 15-Jul-2015

31 views

Category:

Documents


0 download

TRANSCRIPT

Software Basado en Componentes

Trabajo FinalQuickCheck/Haskell

Lisibonny Beato

18 de febrero de 2010

QuickCheck/Haskell _____________________________________________________________________________

ndice generalIntroduccin .................................................................................................................................. 3 El lenguaje de programacin Haskell ............................................................................................ 4 Caractersticas principales y aplicaciones ................................................................................. 4 Programa de ejemplo en Haskell .............................................................................................. 4 QuickCheck para Haskell ............................................................................................................... 6 Qu es QuickCheck? ................................................................................................................ 6 Propiedades............................................................................................................................... 6 Propiedades condicionales.................................................................................................... 7 Propiedades cuantificadas .................................................................................................... 7 Propiedades triviales ............................................................................................................. 8 Combinadores especiales.......................................................................................................... 8 Combinador Classify .............................................................................................................. 8 Combinador Collect ............................................................................................................... 9 Generadores de casos de prueba personalizados............................................................... 10 Caso de estudio: Gestin de nombres de archivo....................................................................... 11 Desarrollando un generador de casos de prueba ................................................................... 11 Definiendo la propiedad a probar ........................................................................................... 11 Recolectando informacin de los casos de prueba................................................................. 12 Desarrollando generadores de casos de prueba alternativos ................................................ 13 Modificando funciones y probando nuevamente las propiedades ........................................ 15 Conclusiones ............................................................................................................................... 16 Bibliografa .................................................................................................................................. 17

_____________________________________________________________________________ Software Basado en Componentes 2

QuickCheck/Haskell _____________________________________________________________________________

IntroduccinA da de hoy la realizacin de pruebas sobre cdigo fuente es la tcnica ms utilizada para asegurar la calidad del software. Se calcula que ms de la mitad del esfuerzo empleado en el desarrollo de software se dedica a labores de testing. Es por esta razn que la investigacin para la automatizacin de esta tarea sea un rea muy activa en los ltimos aos. Est demostrado que los lenguajes de programacin funcionales estn mejor preparados para dicha automatizacin debido a la naturaleza puramente funcional de los mismos y a la carencia de efectos colaterales. Una de estas iniciativas de automatizacin de pruebas en lenguajes funcionales es QuickCheck, una herramienta originalmente desarrollada para el lenguaje de programacin Haskell y que ha sido implementada en otros lenguajes, tanto funcionales como imperativos. El objetivo de este trabajo es, precisamente, mostrar el funcionamiento de QuickCheck para Haskell y obtener conclusiones acerca de su desempeo, ventajas e inconvenientes todo ello derivado del uso de la herramienta en un caso de estudio concreto. Para ello se ha dividido el trabajo en las siguientes partes: La primera parte describe brevemente el lenguaje de programacin funcional Haskell y se muestran sus principales caractersticas y aplicaciones como base para hablar de la herramienta de pruebas QuickCheck. La segunda parte introduce el concepto de propiedad en QuickCheck y especficamente se tratan las propiedades condicionales, cuantificadas y triviales. Tambin se tratan algunas herramientas de QuickCheck relativas a la clasificacin y recoleccin de casos de pruebas, as como tambin a la construccin de generadores de casos de pruebas personalizados. En la tercera parte se desarrolla un caso de estudio que implementa una librera en Haskell para el manejo de nombres de archivo. Se busca probar distintas propiedades sobre dichas funciones, utilizando QuickCheck, y verificar el desempeo de las mismas con generadores de casos de prueba personalizados.

_____________________________________________________________________________ Software Basado en Componentes 3

QuickCheck/Haskell _____________________________________________________________________________

El lenguaje de programacin HaskellHaskell es un lenguaje de programacin puramente funcional sin efectos colaterales. Surgi en los aos 80's como respuesta a la necesidad de crear un lenguaje funcional que agrupara todas las caractersticas de los lenguajes que proliferaban en aquella poca.

Caractersticas principales y aplicacionesEs un lenguaje de muy alto nivel en donde muchos detalles son manejados de forma automtica. Es expresivo y conciso, por lo que el programador es capaz de lograr mucho con una pequea cantidad de cdigo. Se puede decir que Haskell le da mayor prioridad al tiempo del programador que al tiempo de procesamiento del cdigo, lo que lo hace un lenguaje de desempeo bajo en trminos de procesamiento. Una de las caractersticas ms importantes de Haskell es su extraordinaria capacidad para manejar datos complejos y para combinar componentes. Solo realiza clculos cuando el resultado es requerido, en otras palabras, utiliza tcnicas de evaluacin perezosa. Es un lenguaje fuertemente tipado, por lo que impone severas restricciones acerca de cmo realizar operaciones entre valores de distintos tipos de dato. Haskell es usado en aplicaciones de muy diversa naturaleza: compiladores, analizadores, validadores de teoremas, aplicaciones para el procesamiento de datos estructurados y otras aplicaciones de dominios especficos.

Programa de ejemplo en HaskellEl siguiente es un programa escrito en Haskell que implementa una funcin para calcular el factorial de un nmero. Contiene, adems, una funcin principal que pregunta al usuario cul es el factorial del nmero 5 y le notifica si la respuesta que ha dado es correcta o no.

module Main where factorial n = if n == 0 then 1 else n * factorial (n - 1) main = do putStrLn "Cul es el factorial de 5?" x quickCheck prop_TransTrans OK, passed 100 tests.

_____________________________________________________________________________ Software Basado en Componentes 6

QuickCheck/Haskell _____________________________________________________________________________ En este caso QuickCheck nos indica que de los cien casos de prueba generados, todos han pasado satisfactoriamente las pruebas. Sin embargo, si intentsemos probar que la aplicacin de la funcin reverse sobre una lista es igual a la lista origina, como se especifica en la siguiente propiedad: prop_TransId xs = reverse (xs) == xs where types = xs::[Int] Obtendramos la siguiente salida en Hugs:Main> quickCheck prop_TransId Falsifiable, after 5 tests: [-3,0,-2]

En este caso QuickCheck nos dice que el quinto caso de prueba no satisface la propiedad especificada. Nos muestra tambin los datos que se utilizaron en dicho caso de prueba. En las siguientes sub-secciones veremos tres tipos especiales de propiedades que se pueden utilizar en QuickCheck: Condicionales, cuantificadas y triviales.

Propiedades condicionales

Este tipo especial de propiedad permite especificar una condicin que los casos generados por QuickCheck deben cumplir en orden de ser utilizados como casos de prueba. Si la condicin no se cumple para un caso de prueba, este es descartado y se prueba con el siguiente. La sintaxis de una propiedad de este tipo es como se especifica a continuacin: ==> El siguiente ejemplo muestra una propiedad que busca probar si el mximo entre dos nmeros es siempre el segundo nmero cuando el primer nmero es menor o igual a este: prop_MaxMi x y = x max x y == y where types = (x::Int, y::Int)

Propiedades cuantificadas

Con este tipo de propiedad se puede especificar un generador de casos de prueba personalizado en vez de utilizar el generador por defecto que provee QuickCheck para el tipo de dato en cuestin. Con este tipo de propiedad es posible controlar la distribucin de los casos de prueba y, a diferencia del tipo anterior, no filtra datos por lo que el total de casos de prueba est disponible para ser utilizado. La sintaxis de una propiedad de este tipo es como se muestra a continuacin: forAll $ \ -> _____________________________________________________________________________ Software Basado en Componentes 7

QuickCheck/Haskell _____________________________________________________________________________ El siguiente ejemplo utiliza un generador de nmeros mayores que cien para ser utilizado en las pruebas de la propiedad del mximo entre dos nmeros descrita en la seccin anterior: prop_MaxMi x y = forAll mayorquecien $ \(x, y) -> max x y == y where types = (x::Int, y::Int)

Propiedades triviales

Con esta propiedad se pueden obtener estadsticas acerca de los casos triviales o casos en donde la condicin especificada ha sido verdadera. Esta propiedad devuelve la proporcin de estos casos con respecto al total de casos generados. La sintaxis de una propiedad de este tipo es como se muestra a continuacin: `trivial` El siguiente ejemplo muestra la cantidad de casos triviales dentro del conjunto de casos de prueba de una propiedad que busca que las listas generadas estn ordenadas en orden de ser usadas como casos de prueba: ordenadas xs = and (zipWith ( 2.

Combinador Collect

La recoleccin de valores utilizando este combinador es similar al anterior, con la diferencia de que en este caso se recolectan todos los datos generados y la distribucin de los mismos se reporta al final de las pruebas. La sintaxis de este combinador es como sigue: collect $ El siguiente ejemplo muestra el porcentaje de casos de prueba de acuerdo a todos los tamaos de las listas generadas: ordenadas xs = and (zipWith ( Property prop_nombresarchivo_correctos_classify naStr = classify (length ext == 0) "Sin extensin" $ classify (length ext > 0 && length ext < 5) "Extensin normal" $ classify (length ext >= 5) "Extensin larga" $ unirNA (dividirNA na) == na where na = unNA naStr (nombre,ext) = dividirNA na _____________________________________________________________________________ Software Basado en Componentes 12

QuickCheck/Haskell _____________________________________________________________________________ Ejecutando dicha propiedad en Hugs tenemos la siguiente salida:Main> quickCheck prop_nombresarchivo_correctos_classify OK, passed 100 tests. 70% Extensin larga. 22% Extensin normal. 8% Sin extensin.

Si revisamos detenidamente la informacin obtenida, podemos ver que no estamos trabajando con el conjunto completo de nombres de archivo vlidos, como por ejemplo LEEME, .emacs, archivo. o documento.txt.old.

Desarrollando generadores de casos de prueba alternativosPara corregir este problema podramos desarrollar un generador de casos de prueba alternativo sin instanciar la clase Arbitrary y utilizaremos oneof. nombresarchivo :: Gen String nombresarchivo = do nombre (String, String) dividirNA_nueva na = let na' = span (/= '.') . reverse $ na in case (length (fst na') == length na of True -> (na, "") False | length (fst na') == length na - 1 -> (na, "") | otherwise -> (reverse . drop 1 $ snd na' , ('.':) . reverse . fst $ na')

Con esta nueva funcin de divisin de nombres de archivos vamos a reescribir las propiedades prop_archivo_iguala_nombrearchivo y prop_nombresarchivo_correctos_nueva: prop_archivo_iguala_nombrearchivo_nueva :: Property prop_archivo_iguala_nombrearchivo_nueva = forAll NombrearchivosSinExt $ \na -> let (nombre,ext) = dividirNA_nueva na in nombre == na prop_nombresarchivo_correctos_nueva2:: Property prop_nombresarchivo_correctos_nueva2 = forAll nombresarchivo $ \na -> unirNA (dividirNA_nueva na) == na Ejecutando las propiedades en Hugs podemos ver que ahora todos los casos de prueba pasan las pruebas de ambas propiedades exitosamente:Main> quickCheck prop_nombresarchivo_correctos_nueva2 OK, passed 100 tests. Main> quickCheck prop_archivo_iguala_nombrearchivo_nueva OK, passed 100 tests.

_____________________________________________________________________________ Software Basado en Componentes 15

QuickCheck/Haskell _____________________________________________________________________________

ConclusionesDespus de trabajar con QuickCheck en el caso de estudio podra concluir que la visin de alto nivel de esta herramienta va muy acorde con la naturaleza funcional de Haskell, dado que para probar los programas no es necesario disear pruebas individuales y planear cuidadosamente los datos que dichas pruebas utilizarn, cosa que si es importante cuando se trata con lenguajes imperativos. Por esta misma razn una de las ventajas de trabajar con QuickCheck es la reduccin de los tiempos de validacin de los programas, que se consigue gracias a que los casos de prueba son generados de forma automtica. QuickCheck, adems, verifica los programas intentando encontrar ejemplos que no cumplen las especificaciones dadas (contra-ejemplos). A pesar de que esto no es una garanta de consistencia, ayuda a reducir dicho riesgo dentro de nuestro cdigo. Otro punto fuerte de esta herramienta es que ayuda en las tareas de documentacin de los programas, debido a que otros programadores que tengan que ver o trabajar con nuestro cdigo pueden saber exactamente qu propiedades hemos probado en nuestros programas, la naturaleza de los casos de prueba que hemos utilizado y los resultados que hemos obtenido en dichas pruebas. Sin embargo, hay que ser cuidadosos con la distribucin de los casos de prueba: si los datos de prueba que se utilizan no estn bien distribuidos las conclusiones que se obtienen pueden no ser correctas.

_____________________________________________________________________________ Software Basado en Componentes 16

QuickCheck/Haskell _____________________________________________________________________________

Bibliografa1. Sitio Web de Haskell, http://www.haskell.org/ 2. Sitio Web de QuickCheck, http://www.cs.chalmers.se/~rjmh/QuickCheck/ 3. Artculo de QuickCheck en Wikipedia, http://en.wikipedia.org/wiki/QuickCheck

_____________________________________________________________________________ Software Basado en Componentes 17