giovedì 20 ottobre 2011

Un modo semplice per testare basato su Eclipse editori


Dopo due release della versione open source di protobuf-dt -Google e dieci quelle interne, la complessità del codice crescere fino a un punto che i test più completa è necessario.Anche se le pratiche in questo post può essere usato per testare i diversi aspetti di un editor di Eclipse, ci concentreremo sui test scoping .
Verificare che funzioni correttamente scoping prevede:
  1. Definizione e l'analisi di protocollo di buffer-contenuto da utilizzare per i test
  2. Trovare un elemento specifico nel file analizzato
  3. Verificare che scoping restituisce tutti gli elementi possibili che possono corrispondere l'elemento trovato al punto # 2
Un ulteriore requisito è di rendere i test il più leggero possibile (ad esempio non hanno bisogno di creare un'istanza di un Eclipse completo per l'esecuzione di test).

1. Definizione e l'analisi di protocollo buffer contenuti da utilizzare

Il mio primo tentativo è stato quello di mettere tutto il codice di buffer protocollo in un StringBuilder e poi passò a mio XtextRule per ottenere un ritorno AST, come segue:
01.@ Regola pubblico XtextRule xtext = createWith (integrationTestSetup ());
02. 
03.@ test pubblico vuoto should_provide_Property_fields_for_custom_field_option () {
. 04StringBuilder proto = nuovo StringBuilder ();
05.proto.append ( "com.google.proto pacchetto;" )
06.. append ( "import 'google / protobuf / descriptor.proto';" )
07.. append ( "" )
08.. append ( "google.protobuf.FieldOptions estendere {" )
. 09. append ( "codice int32 opzionale = 1000;" )
10.append (. "info opzionale int32 = 1001;" )
11.. append ( "}" )
12.. append ( "" )
13.. append ( "Persona messaggio {" )
14.append. ( "optional boolean attivo = 1 [(codice) = 68];" )
15.. append ( "}" );
16.Protobuf root = xtext.parseText (proto);
17./ / test implementazione
18.}
Inutile dire che la scrittura e il mantenimento di questo è un vero e proprio PITA. Per rendere più leggibile devo aggiungere ulteriore spazio per ogni linea in modo che il tutto sembra quadrati. Inoltre, copia / incolla del codice dall'editor di buffer di protocollo richiede anche l'aggiunta di aggiungere e citazioni di ogni linea, oltre la formattazione.Oltre a questo, rende il metodo di prova troppo lungo.
Un approccio alternativo è stato quello di avere. Proto file nel file system. Non ero contento di questo approccio, poiché nessuno la lettura del codice sarà bisogno di andare a due cifre per capire che cosa sta facendo il test.
Infine, ho trovato un approccio migliore: specificare il testo del buffer protocollo come un commento!
Non sono venuto fuori con questa idea me stesso, sto semplicemente prendendo in prestito da CDT . Dopo l'implementazione di un approccio più semplice, ma simile, il mio test è la seguente:
01./ / com.google.proto pacchetto;
. 02/ / import 'google / protobuf / descriptor.proto';
03./ / 
04./ / estendere google.protobuf.FieldOptions {
05./ / codice facoltativo int32 = 1000;
06./ / info opzionale int32 = 1001;
07./ /}
08./ / 
09.Persona / / {messaggio
10./ / opzionale booleano attivo = 1 [(codice) = 68];
11./ /}
12.@ test pubblico vuoto should_provide_Property_fields_for_custom_field_option () {
13.Protobuf root = xtext.root ();
14./ / test implementazione
15.}
Questo è un grande miglioramento! Prima di tutto, il metodo di prova finisce per essere più breve e più facile da leggere.In secondo luogo, è facile da digitare qualcosa nell'editor di buffer di protocollo, copiarlo e incollarlo sopra un metodo di prova. Poi devo solo per evidenziarlo e premere Ctrl + / avere il testo convertito in un commento.
In questo nuovo scenario, il mio XtextRule abitudine fa il seguente:
  1. estrae il commento di ogni metodo di prova e crea un nome metodo> commento mappatura
  2. analizza il commento di un metodo di prova e crea un AST poco prima di eseguire il metodo di prova, non prima
  3. mantiene un riferimento al nodo radice della AST, per essere utilizzato dal metodo di prova si
Sembra buono, ma per quanto riguarda importazione file. Proto?
Durante il test di scoping, è assolutamente necessario verificare che i tipi importati sono comprese correttamente.
All'inizio ho avuto. Proto file da importare nel file system e memorizzati in Git, che è brutto per la ragione che ho citato prima.
Per rendere le cose migliori, ho preso in prestito un'altra idea da CDT:. Specificare il nome del file di testo e del proto file da importare nei commenti, XtextRule creerà il file nel file system appena prima di eseguire un metodo di prova.
Ecco un esempio:
01./ / / / Crea un file custom-options.proto
02./ /
03./ / com.google.proto pacchetto;
04./ /
05./ / import "google / protobuf / descriptor.proto";
06./ /
07./ / estendere google.protobuf.FileOptions {
08./ / codice facoltativo int32 = 1000;
09./ / info opzionale int32 = 1002;
10./ /} 
11. 
12./ / com.google.proto pacchetto;
13./ / 
14./ / import 'su misura options.proto';
15./ /
. 16/ / opzione (code) = 68;
17.@ test pubblico vuoto should_provide_imported_Property_fields_for_custom_option () {
18./ / test implementazione
19.}
Nell'esempio di sopra abbiamo due commenti per un metodo di prova. Il primo racconta la mia XtextRule per creare un file chiamato "custom-options.proto" prima di eseguire il metodo di prova. Il secondo commento sarà quello analizzato e di cui AST saranno conservati dal XtextRule (proprio come nell'esempio precedente).
Pulito, non è vero? :)

2. Trovare un elemento specifico nel file analizzato

Questo passaggio è necessario per garantire che scoping restituisce tutti i tipi possibili che un riferimento, può essere oggetto indicando.
In questo esempio:
01./ / com.google.proto pacchetto;
. 02/ / import 'google / protobuf / descriptor.proto';
03./ / 
04./ / estendere google.protobuf.FieldOptions {
05./ / codice facoltativo int32 = 1000;
06./ / info opzionale int32 = 1001;
07./ /}
08./ / 
09.Persona / / {messaggio
10./ / opzionale booleano attivo = 1 [(info) = 68];
11./ /}
12.@ test pubblico vuoto should_provide_Property_fields_for_custom_field_option () {
13.}
il mio test sta andando a verificare che scoping restituisce il codice di campo opzioni e informazioni come fiammiferi potenziali (codice). Per farlo, ho bisogno di trovare l'elemento giusto che AST (codice) rappresenta.
Diciamo che desidera cercare le informazioni personalizzati opzione di campo. Il mio approccio originale richiederebbe il seguente:
  1. Trova tutti gli elementi della AST di CustomFieldOption tipo
  2. Se qualche risultato viene restituito da # 1, trovare colui il cui nome è "info"
Ecco un esempio:
1.radice Protobuf = xtext.root ();
2./ / staticamente importati da CustomFieldOptionFinder
3.opzione CustomFieldOption = findCustomFieldOption (nome ( "info" ), in (root));
Questa soluzione di per sé non è male, e funziona! Purtroppo richiede un cercatore di specializzazione per tipo in AST.Per un linguaggio relativamente semplice come buffer protocollo, che richiederebbe più di 10 cercatori, che è troppo codice da mantenere solo per il test.
Inserisci CDT con un approccio migliore, che richiede solo un mirino per tutti i tipi in AST. Questo cercatore cerca elementi in questo modo:
  1. Trova il primo elemento corrispondente del testo
  2. Verificare che l'elemento trovato è del tipo specificato e ha il nome specificato
Per esempio:
1.opzione CustomFieldOption = xtext.find ( "info" ")" , CustomFieldOption. classe );
Per trovare l'usanza opzione "info" questo cercatore sarà:
  1. concatena le stringhe passate come argomenti e trovare il primo elemento che corrisponde al testo "info)"
  2. verificare che l'elemento trovato è un CustomFieldOption e ha nome "info" (l'argomento String solo la prima)
Come potete vedere, questo approccio è l'esatto contrario della mia quello originale.
Dal momento che un solo finder è necessario, posso avere il mio XtextRule crearlo e passare la radice della AST ad esso. In questo modo, non devo passare per il cercatore ogni volta che esegue una ricerca.

3. Verifica che scoping restituisce il tipo corretto

Questo è in realtà DSL-specifici. La mia unica raccomandazione è qui, se si sta usando JUnit, scrivere il matchers Hamcrest proprio per mantenere il codice di prova breve e leggibile, e senza duplicazione.

Mettere tutto insieme

Ecco come uno dei miei test per protobuf-dt assomiglia a:
01.Persona / / {messaggio
02./ / Tipo Tipo opzionale = 1 [ctype = STRING];
03./ /}
04.@ test pubblico vuoto should_provide_Property_fields_for_native_field_option () {
05./ / Abbiamo una versione di overload di "trovare" che richiede un solo <code> String </ code>,
06./ / da utilizzare quando il testo da trovare e il nome di partita sono la stessa cosa.
07.opzione NativeFieldOption = xtext.find ( "ctype" , NativeFieldOption. classe );
08.portata IScope = provider.scope_PropertyRef_property (option.getProperty (), di riferimento);
09.Collection <property> fieldOptions = descrittore () optionsOfType (CAMPO).;
10.assertThat (descriptionsIn (scope), containAll (fieldOptions));
11.}
Non esitate a fare clic su questi link per trovare il codice di:
  • XtextRule
  • ModelFinder
  • o semplicemente ottenere il codice sorgente del progetto
Le risposte sono sempre i benvenuti! :)

Messaggi futuro

Ci sono un paio di cose utili che ho fatto con xtext che mi piacerebbe blog circa nel prossimo futuro:
  • Aggiungendo il controllo ortografico per i commenti e stringhe
  • Apertura di file di fuori di un workspace di Eclipse
  • Rendere il lavoro xtext con nomi di file, invece di estensioni di file
Ora è una questione di trovare il tempo ed energia!

Nessun commento:

Posta un commento

Nota. Solo i membri di questo blog possono postare un commento.