miércoles, 21 de septiembre de 2016

Automatic Software Repair

Automatic Software Repair es un área de investigación del desarrollo de software que comenzó a utilizarse alrededor del año 2000. Es una técnica que tiene como función arreglar bugs de forma automática; es decir sin intervención humana.

Para poder comprender de qué se trata, tenemos que partir de los conceptos fundamentales utilizados en esta rama de la investigación de software: 

En primer lugar, cabe destacar que todo programa en ejecución tiene comportamientos esperados y no esperados, pero también hay un sujeto implícito que es el que observa que estos comportamientos sean de esa manera. El mismo puede ser un QA (un humano) o también puede ser una especificación (conjunto de comportamientos esperados explícitos, ya sea los formulados en una batería de test, o los implícitos, como ser un programa que no puede “crashear” bajo ningún input). 

Otro concepto importante y muy ligado a las especificaciones, es el de oráculos. Cuando hablamos de ellos, nos referimos a “artefactos” que nos indican si una ejecución es correcta o no. Como vemos, los dos términos se asemejan entre sí, ya que hablan de comportamientos esperados; entonces, ¿dónde radica la diferencia? En que la especificación suele contener información no funcional (tipos de input, rangos de entrada) mientras que los oráculos tienen instancias concretas de validación. De esta manera, dentro de Automatic Software Repair tenemos dos oráculos: los de bug y los de regresión. Los de Bug nos indican que existe un error y que hay que empezar nuestro proceso de reparación, mientras que los de regresión nos indican que tras este proceso introdujimos algún error. 

Una de las claves de Automatic Software Repair, es que para realizar un proceso de reparación automática, debe realizarse en una clase de bugs. Este conjunto de errores puede ser de acuerdo a su causa raíz, a sus síntomas o a su reparación. 

Luego, se deberían preparar buenos oráculos, tanto de bug como de regresión, para continuar con la ejecución de algoritmos de reparación que completen el proceso. Estos algoritmos, nos indican adonde tenemos que probar nuestras reparaciones automáticas, y se pueden clasificar en dos grandes “familias”. 

La primera de ellas es la reparación en tiempo real, que se basa en el cambio de estado del programa para lograr un comportamiento adecuado. No se refiere a cambiar el código, sino a la configuración o el input del mismo. 

El oráculo de bug más frecuentemente utilizado en esta reparación es un “crash” o una invariante en el sistema. Para reparar estos estados hay algunos estudios basados en la redundancia, que indican que en un programa hay “varias maneras de hacer lo mismo”. 

Así es como hay estudios para escapar de loops infinitos, para modificar un input por uno esperado dentro del rango, o para darle al programa un objeto default para no “crashear” ante un Null Pointer Exception. 

La otra familia es la generación automática de parches, en donde, a diferencia de la reparación en tiempo real, se cambia el código del programa para repararlo automáticamente. 

En la mayoría de estos estudios, el oráculo de bug es un test case que falla, mientras que un oráculo de regresión es la batería de test asociada a la aplicación que hay que probar. 

En este tipo de reparaciones, llamadas behavior (comportamientos), uno de los estudios más conocidos se basa en “algoritmos de mutación”. Para estos, la solución está en el código: si quitás una línea de código, quizá solucionas un bug; si añadís una, podrías llegar a solucionar un error y, si modificas una línea, también podrías solucionar un bug. ¿Pero cómo se llega a esta conclusión? Con algoritmos que seleccionan y encuentran soluciones, denominados parches.

A pesar de que ya existen gran cantidad de respuestas, dentro de esta rama de investigación, aún quedan algunas preguntas por responder: ¿qué pasa cuando la solución que da el programa no es la correcta? o ¿qué ocurre cuando no se encuentran algoritmos que puedan solucionar el programa? Y esto plantea un nuevo desafío: que un programa pueda reparar un bug, subir un commit y que las personas puedan aprobarlo o no. 

Autor:
Gustavo Lamy Cobarrubia
QA & Testing Specialist