¿Cómo usar BDD para probar un compilador unitario?

8

Mi equipo está escribiendo un compilador para un lenguaje específico de dominio (DSL) que se integrará en un IDE. En este momento, estamos enfocados en la fase de análisis del compilador. Estamos no utilizando cualquier analizador-generadores existentes (tales como antlr) porque necesitamos rendimiento en tiempo real y altamente detallado / advertencia / información de los mensajes de error. Tenemos

  1. clases, cada una de las cuales representa un nodo en el árbol de sintaxis concreta para el lenguaje, así como
  2. clases que actúan como anotaciones para cada nodo (es decir, para errores e información adicional), así como
  3. clases internas que construyen y manipulan el árbol de sintaxis concreto (es decir, lexer, parser, caché para cadenas, visitantes de sintaxis).

Estamos tratando de decidir una estrategia general para organizar nuestras pruebas. Nuestra empresa está impulsando el desarrollo basado en el comportamiento (BDD) y el diseño basado en el dominio (DDD). Aunque estamos creando un DSL para el dominio de nuestra empresa, el dominio del compilador es un lenguaje de programación.

Todavía estamos en el proceso de compilar el compilador y ya tenemos algunas pruebas. Nuestro objetivo es tener una cobertura del estado de cuenta del 100%.

Actualmente tenemos pruebas en las que ingresamos el código fuente al generador de árbol de sintaxis, y luego ejecutamos una verificación en cada propiedad de cada nodo del árbol de sintaxis resultante para asegurarnos de que la información esperada (número de línea, error (s) relevante, hijo) / tokens principales, ancho del token, tipo de token, etc.). Ahora, dado que cada nodo es su propia clase, y ciertas anotaciones y errores asociados a un nodo son clases separadas, esta prueba termina haciendo referencia a muchas clases.

Actualmente tenemos pruebas para ciertas clases, como el lexer en el que podemos aislar la entrada (una cadena) y la salida (una lista de tokens) de otras clases (por ejemplo, las clases para los nodos del árbol de sintaxis). Estas pruebas son más granulares.

Ahora, las pruebas en el párrafo inmediatamente anterior se pueden poner en correspondencia con la clase bajo prueba (por ejemplo, lexer, caché de cadenas). Sin embargo, las pruebas del segundo párrafo anterior realmente prueban toda la fase de análisis del compilador; es decir, cada prueba puede tener más de 300 aserciones para el árbol de sintaxis, dado el código fuente de entrada. Las pruebas son para el comportamiento de la fase de análisis.

¿Es esta una estrategia de prueba adecuada? Si no, ¿qué deberíamos estar haciendo de manera diferente? ¿Qué estrategia de organización debemos usar para nuestras pruebas?

cm007
fuente

Respuestas:

5
  > Is this an appropriate testing strategy?

No , porque su subdominio es un DSL (un tipo de lenguaje de programación) y su compilador es parte de un detalle de implementación para el caso de uso que permite automatizar acciones / flujos de trabajo en este dominio usando el DSL.

Dado que no sé cómo sus miradas DSL como que se supone que tiene conceptos como loop, condition, statement, variableutilizando el ejemplo

 for(int i=1;i =< 10;i++) {subtask();}

Usando un lenguaje similar a bdd-gherkin podrías escribir algo como

as a automation user
i want to have a for loop with startvalue, endvalue, loopincrement
so that i can repeat subtasks several times.

given startvalue=1
and endvalue = 10
and loopinclrement = 1
when i execute for(int i=%startvalue%;i =< %endvalue %;i+=%loopinclrement%)
then the subtask should have been executet 10 times.

Esto es bastante trabajo para demostrar que su compilador funciona como se esperaba.

  > If not, what should we be doing differently? 
  > What organization strategy should we use for our tests?

Crearía un gran depósito de ejemplos para entrada con salida correspondiente.

La prueba automatizada iteraría a través de los ejemplos y verificaría que la salida del compilador coincida con la salida esperada.

Ejemplo: si su dsl de factura / pedido se compila en Java, una entrada de repositorio se vería así:

 example: loop over orderentries
 dsl-source: foreach orderitem in orders do calculateTaxes(orderitem)
 expected errormessage: none
 expected java output: for(OrderItemType orderitem : orders) 
                          {calculateTaxes(orderitem);}

 example: loop with syntax errors
 dsl-source: foreach orderitem in orders 
 expected errormessage: missing "do"-keyword in line 1
 expected java output: none

Entonces, en lugar de escribir una gran cantidad de código para adaptarse a bdd, simplemente tiene que agregar ejemplos de valores de entrada / salida codificados.

k3b
fuente