2010-11-20 15 views
6

Como parte de un proyecto universitario, tenemos que escribir un compilador para un lenguaje de juguete. Para hacer algunas pruebas para esto, estaba considerando la mejor manera de escribir algo así como pruebas unitarias. Como el compilador está escrito en haskell, Hunit y quickcheck están disponibles, pero quizás no del todo apropiados.Pruebas unitarias para una salida de compilador

¿Cómo podemos hacer cualquier tipo de prueba no manual? La única idea que he tenido es compilar efectivamente a Haskell también, ver cuál es el resultado, y usar un script de shell para comparar esto con el resultado del programa compilado: esto es bastante trabajo, y no es demasiado elegante tampoco.

La prueba de unidad es para ayudarnos, y no es parte del trabajo evaluado en sí.

+0

No necesita compilar a Haskell; también puede simplemente escribir una implementación de referencia simple de un intérprete. – sclv

Respuesta

4

Esto realmente depende de qué partes del compilador está escribiendo. Es bueno si puede mantener las fases distintas para ayudar a aislar los problemas, pero, en cualquier fase, e incluso en el nivel de integración, es perfectamente razonable contar con pruebas unitarias que constan de pares de código fuente y código compilado a mano. Puede comenzar con los programas legales más simples posibles y asegurarse de que su compilador muestre lo mismo que si compilara a mano.

A medida que aumenta la complejidad y la compilación manual se vuelve difícil de manejar, es útil para el compilador mantener algún tipo de registro de lo que ha hecho. Luego puede consultar este registro para determinar si se activaron o no las transformaciones u optimizaciones específicas para un programa fuente determinado.

Dependiendo de su idioma, puede considerar un generador de programas aleatorios a partir de una colección de fragmentos de programa (en la veta QuickCheck). Este generador puede probar la estabilidad de tu compilador y la capacidad de manejar entradas potencialmente imprevistas.

3

Las pruebas unitarias probarán una pieza pequeña de código, generalmente una clase o una función. El análisis léxico y semántico tendrá cada uno sus pruebas unitarias. El generador de Represión Intermedio también tendrá sus propias pruebas.

Una prueba de unidad cubre un caso de prueba simple: invoca la función de ser probado en un ambiente controlado y verifica (afirma) el resultado de la ejecución de la función. Una prueba de la unidad normalmente probar sólo un comportamiento y tiene la siguiente estructura, denominada AAA:

  • Organizar: crear el entorno de la función se llama en
  • Ley: invocar la función
  • Assert: verificar el resultado
0

Las pruebas se vuelven más difíciles una vez que la salida de su programa va a la consola (como la salida estándar). Luego debe recurrir a alguna herramienta externa, como grep o expect para verificar la salida.

Mantenga los valores de retorno de sus funciones en las estructuras de datos el mayor tiempo posible. Si la salida de su compilador es, por ejemplo, código de ensamblaje, construya una cadena en la memoria (o una lista de cadenas) y déjela salir en el último momento posible. De esta forma, puede probar el contenido de las cadenas de manera más directa y rápida.

0

Una de las opciones es la aproximación this guy is doing para probar compiladores reales: reúnase con la mayor cantidad de personas que pueda hablar y cada uno de ustedes compila y ejecuta el mismo conjunto de programas y luego compara los resultados. Asegúrese de agregar todos los casos de prueba que utilice a medida que más entradas lo hagan más efectivo. Un poco de diversión con la automatización y el control de fuente y puede hacer que sea bastante fácil de mantener.

Asegúrate de que lo aprueba primero el prof, pero como solo compartirás casos de prueba y resultados, no veo dónde tendrá mucho espacio para objetar.