Wie verwende ich BDD, um einen Compiler zu testen?

8

Mein Team schreibt einen Compiler für eine domänenspezifische Sprache (DSL), die in eine IDE integriert wird. Im Moment konzentrieren wir uns auf die Analysephase des Compilers. Wir sind nicht mit allen vorhandenen Parser-Generatoren (wie ANTLR) , weil wir Echtzeit - Leistung benötigen und sehr detaillierte Fehlern / Warnung / Meldung Informationen. Wir haben

  1. Klassen, von denen jede einen Knoten im konkreten Syntaxbaum für die Sprache darstellt, sowie
  2. Klassen, die als Anmerkungen für jeden Knoten dienen (dh für Fehler und zusätzliche Informationen), sowie
  3. interne Klassen, die den konkreten Syntaxbaum erstellen und bearbeiten (dh Lexer, Parser, Cache für Zeichenfolgen, Syntaxbesucher).

Wir versuchen, eine Gesamtstrategie für die Organisation unserer Tests festzulegen. Unser Unternehmen treibt die verhaltensgesteuerte Entwicklung (BDD) und das domänengesteuerte Design (DDD) voran. Obwohl wir ein DSL für die Domäne unseres Unternehmens erstellen, ist die Domäne des Compilers eine Programmiersprache.

Wir sind noch dabei, den Compiler zu erstellen und haben bereits einige Tests. Wir streben eine 100% ige Abdeckung der Kontoauszüge an.

Wir haben derzeit Tests, bei denen wir Quellcode in den Syntaxbaum-Builder eingeben und dann eine Überprüfung für jede Eigenschaft jedes Knotens des resultierenden Syntaxbaums ausführen, um sicherzustellen, dass die erwarteten Informationen (Zeilennummer, relevante Fehler, untergeordnetes Element) vorliegen / übergeordnete Token, Breite des Tokens, Art des Tokens usw.). Da jeder Knoten eine eigene Klasse ist und bestimmte Anmerkungen und Fehler, die an einen Knoten angehängt sind, separate Klassen sind, verweist dieser Test auf viele Klassen.

Wir haben derzeit Tests für bestimmte Klassen wie den Lexer, in dem wir die Eingabe (eine Zeichenfolge) und die Ausgabe (eine Liste von Token) von anderen Klassen (z. B. den Klassen für die Knoten des Syntaxbaums) isolieren können. Diese Tests sind detaillierter.

Jetzt können die Tests im obigen Absatz in Übereinstimmung mit der zu testenden Klasse (z. B. Lexer, String-Cache) gestellt werden. Die Tests aus dem obigen zweiten Absatz testen jedoch wirklich die gesamte Analysephase des Compilers. Das heißt, jeder Test kann angesichts des eingegebenen Quellcodes weit über 300 Zusicherungen für den Syntaxbaum enthalten. Die Tests beziehen sich auf das Verhalten der Analysephase.

Ist dies eine geeignete Teststrategie? Wenn nicht, was sollen wir anders machen? Welche Organisationsstrategie sollten wir für unsere Tests verwenden?

cm007
quelle

Antworten:

5
  > Is this an appropriate testing strategy?

Nein , da Ihre Subdomain eine DSL (eine Art Programmiersprache) ist und Ihr Compiler Teil eines Implementierungsdetails für den Anwendungsfall ist, mit dem Aktionen / Workflows in dieser Domäne mithilfe von DSL automatisiert werden können.

Da ich weiß nicht , wie Ihr DSL sieht aus wie ich annehmen , dass Sie Begriffe wie loop, condition, statement, variabledas Beispiel mit

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

Mit einer bdd-gherkin-ähnlichen Sprache könnte man so etwas schreiben

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.

Dies ist eine Menge Arbeit, um zu beweisen, dass Ihr Compiler wie erwartet funktioniert.

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

Ich würde ein großes Repository mit Beispielen für die Eingabe mit entsprechender Ausgabe erstellen.

Der automatisierte Test würde die Beispiele durchlaufen und überprüfen, ob die Compilerausgabe mit der erwarteten Ausgabe übereinstimmt.

Beispiel: Wenn Ihre rechnungs- / auftragsbezogene DSL-Datei in Java kompiliert wird, sieht ein Repository-Eintrag folgendermaßen aus:

 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

Anstatt viel Code für bdd zu schreiben, müssen Sie lediglich Beispiele für fest codierte Eingabe- / Ausgabewerte hinzufügen.

k3b
quelle