Domanda

Sto cercando uno strumento che può prendere un test di unità, come

IPerson p = new Person();
p.Name = "Sklivvz";
Assert.AreEqual("Sklivvz", p.Name);

e generare automaticamente il corrispondente stub di classe e interfaccia

interface IPerson         // inferred from IPerson p = new Person();
{
    string Name 
    { 
        get;              // inferred from Assert.AreEqual("Sklivvz", p.Name);
        set;              // inferred from p.Name = "Sklivvz";
    }
}

class Person: IPerson     // inferred from IPerson p = new Person();
{
    private string name;  // inferred from p.Name = "Sklivvz";

    public string Name    // inferred from p.Name = "Sklivvz";
    {
        get
        {
            return name;  // inferred from Assert.AreEqual("Sklivvz", p.Name);
        }
        set
        {
            name = value; // inferred from p.Name = "Sklivvz";
        }
    }

    public Person()       // inferred from IPerson p = new Person();
    {
    }
}

So ReSharper e Visual Studio fare alcuni di questi, ma ho bisogno di uno strumento completo -- riga di comando o quant'altro-che automaticamente deduce che cosa deve essere fatto.Se non c'è nessuna tale strumento, come si fa a scrivere (per es.estendendo ReSharper, da zero, utilizzando le librerie di cui)?

È stato utile?

Soluzione

Ciò che tu sembri bisogno di un parser per il tuo linguaggio (Java), ed un nome e tipo di sistema di risoluzione.("Tabella dei simboli builder").

Dopo l'analisi del testo di origine, un compilatore di solito ha un nome resolver, che tenta di registrare la definizione dei nomi e dei loro corrispondenti tipi, e un tipo di controllo che verifica che ogni espressione ha un tipo valido.

Normalmente il nome/tipo resolver si lamenta quando non riesce a trovare una definizione.Che cosa si vuole fare è quello di trovare il "undefined" cosa sta causando il problema, e di dedurre un tipo per esso.

Per

 IPerson p = new Person();

il nome del resolver sa che la "Persona" e "IPerson" non sono definiti.Se fosse

 Foo  p =  new Bar();

non ci sarebbe alcun indizio che si voleva un'interfaccia, solo che Pippo è un po ' astratto padre di Bar (ad esempio, una classe o un'interfaccia).Così la decisione che deve essere conosciuto per lo strumento ("ogni volta che si trova ad un costrutto, si supponga di Foo è un'interfaccia ...").Si potrebbe utilizzare un metodo euristico:IFoo e Pippo significa IFoo dovrebbe essere un'interfaccia, e da qualche parte qualcuno deve definire Pippo come una classe di realizzazione di tale interfaccia.Una volta che il strumento ha preso questa decisione, è necessario aggiornare il suo simbolo tabelle in modo che si può passare ad altre dichiarazioni:

Per

 p.Name = "Sklivvz";

dato che p deve essere un'Interfaccia (dal precedente inferenza), quindi il Nome deve essere un membro di campo, e sembra che il suo tipo è la Stringa dall'assegnazione.

Con l'istruzione:

 Assert.AreEqual("Sklivvz", p.Name);

i nomi e i tipi di risolvere senza ulteriore problema.

Il contenuto del IFoo e Pippo entità è una sorta di fino a voi;non è necessario utilizzare get e set, ma questo è gusto personale.

Questo non funziona così bene quando si dispone di più soggetti nella stessa dichiarazione:

 x = p.a + p.b ;

Sappiamo che a e b sono probabilmente i campi, ma non si può indovinare che cosa tipo numerico se, infatti, numerico, o se sono stringhe (questo è legale per le stringhe in Java, non so su C#).Per il C++ non si sa nemmeno cosa sia il "+" significa;potrebbe essere un operatore nella Barra di classe.Quindi quello che dovete fare è raccogliere vincoli, ad esempio, "è un qualche indefinito numero o una stringa", etc.e come lo strumento raccoglie le prove, si restringe l'insieme dei possibili vincoli.(Questo funziona come quelle di word problemi:"Joe ha sette figli.Jeff è più alto di Sam.Harry non può nascondere dietro a Sam....chi è Jeff gemello?" in cui è necessario raccogliere le prove e rimuovere l'impossibilità).Si anche preoccupare caso in cui si finisce con una contraddizione.

Si potrebbe escludere p.un+p.b caso, ma poi non è possibile scrivere la vostra unità di test con l'impunità.Ci sono standard di vincolo solutori là fuori, se si desidera che l'impunità.(Un concetto).

OK, abbiamo le idee, ora, questo può essere fatto in modo pratico?

La prima parte di questo richiede un parser e un pieghevole nome e tipo di sistema di risoluzione.Avete bisogno di un constraint solver o almeno un "valore definito i flussi di valore non definito l'operazione" (banale constraint solver).

Il nostro DMS Software Reengineering Toolkit con la sua Java Front End probabilmente potrebbe fare questo.DMS è uno strumento generatore di strumento, per le persone che vogliono costruire strumenti di controllo di processo lingue in modi arbitrari.(Si pensi a "computing con frammenti di programma piuttosto che numeri").

DMS generale scopo l'analisi di macchine, e può costruire un albero per qualsiasi front-end è dato (ad esempio, Java, e non c'è un C# front-end).Il motivo per cui ho scelto di Java è che il nostro Java front-end ha tutto quello di cui nome e tipo di risoluzione macchinari, e viene fornito in forma di codice sorgente, in modo da può essere piegato.Se si è bloccata la banale constraint solver, probabilmente si potrebbe piegare il Java name resolver per capire i tipi.DMS vi permetterà di montare alberi che corrispondono ai frammenti di codice, e si uniscono a loro, in quelli più grandi;come strumento di raccolta dati per la tabella dei simboli, si potrebbe costruire il primitivo alberi.

Da qualche parte, si deve decidere che avete fatto.Quante unità di test lo strumento che hanno a che vedere prima si conosce l'intera interfaccia?(Immagino che si mangia tutti quelli che ti offrono?).Una volta completato, si assembla frammenti per i vari membri e costruire un AST per un'interfaccia;DMS possibile utilizzare la sua prettyprinter per la conversione che AST indietro nel codice sorgente come hai mostrato.

Io suggerisco di Java, poiché il nostro Java front-end ha nome e tipo di risoluzione.Il nostro C# front-end non.Si tratta di una "semplice" questione di ambizione;qualcuno deve scrivere, ma un bel po ' di lavoro (o almeno lo è stato per Java e non riesco a immaginare di C# è molto diverso).

Ma l'idea funziona bene in linea di principio, utilizzando DMS.

Si potrebbe fare questo con alcune altre infrastrutture che ha dato accesso a un parser e un pieghevole nome e tipo di sistema di risoluzione.Che potrebbe non essere così facile da ottenere per C#;Ho il sospetto che MS può dare un parser, e l'accesso a un nome e tipo di risoluzione, ma non sono in alcun modo per cambiare la situazione.Forse il Mono è la risposta?

Hai ancora bisogno di un era di generare frammenti di codice e il loro assemblaggio.Si potrebbe provare a fare questo con la stringa di hacking;la mia (lunga) esperienza con incollaggio programma di bit è che se la fai con le stringhe, infine, fare un pasticcio di esso.Vuoi davvero pezzi che rappresentano frammenti di codice di tipo noto, che possono essere combinati in modi che la grammatica consente;DMS fa che, pertanto, nessun pasticcio.

Altri suggerimenti

La sua incredibile come nessuno abbia davvero dato qualcosa verso ciò che si chiede.

Non so la risposta, ma io vi darò i miei pensieri su di esso.

Se dovessi tentare di scrivere qualcosa di simile me mi piacerebbe vedere su un resharper plugin.Il motivo per cui dico che è perché, come lei ha affermato, resharper può fare, ma in singoli passaggi.Quindi mi sento di scrivere qualcosa che è andato riga per riga e applicare appropriati resharper metodi di creazione concatenati.

Ora non ho nemmeno sapere come fare questo, come non ho mai costruito nulla per resharper, ma è quello che vorrei provare a fare.Si rende il senso logico che si poteva fare.

E se decidi di scrivere codice, si PREGA di inviare, come ho potuto scoprire che utile, essendo in grado di generare l'intero scheletro di un passo.Molto utile.

Se avete intenzione di scrivere una propria implementazione avrei sicuramente consigliamo di dare un'occhiata al NVelocity (C#) o Velocità (Java) modello di motori.

Ho usato questi in un generatore di codice prima e hanno trovato che rendono il lavoro molto più facile.

È fattibile, almeno in teoria.Quello che vorrei fare è usare qualcosa come csparser per analizzare i test di unità (non è possibile compilarlo, purtroppo) e poi prendere da lì.L'unico problema che posso vedere è che quello che stai facendo è sbagliato in termini di metodologia - rende più senso per generare unità di test per le classi di entità (anzi, Visual Studio fa proprio questo) che farlo in un altro modo.

Penso che una vera soluzione a questo problema sarebbe molto specializzata parser.Dal momento che non è così facile da fare, ho un idea più conveniente.Purtroppo, è necessario cambiare il modo di scrivere i test (cioè, solo la creazione dell'oggetto):

dynamic p = someFactory.Create("MyNamespace.Person");
p.Name = "Sklivvz";
Assert.AreEqual("Sklivvz", p.Name);

Una fabbrica oggetto potrebbe essere utilizzato.Se è possibile trovare il nome oggetto, creare e ritorno (questa è la normale esecuzione del test).Se non la trova, si creerà una registrazione proxy (un DynamicObject) in grado di registrare tutte le chiamate e alla fine (forse abbattere) potrebbe emettere file di classe (magari basato su alcuni modelli) che riflettono ciò che ha "visto" di essere chiamato.

Alcuni svantaggi che vedo:

  • È necessario eseguire il codice in "due" modalità, che è fastidioso.
  • In ordine per il proxy per "vedere" e di registrare le chiamate, devono essere eseguite;in modo che il codice in un catch blocco, per esempio, deve eseguire.
  • Devi cambiare il modo in cui creare il vostro oggetto in prova.
  • È necessario utilizzare dynamic;si perde in fase di compilazione di sicurezza in sedute successive e si ha un calo di prestazioni.

L'unico vantaggio che vedo è che è molto più economico per creare rispetto specializzata parser.

Mi piace CodeRush da DevExpress.Essi hanno un enorme personalizzabile motore di template.E la migliore per me c'è nessun finestre di Dialogo.Essi hanno anche funzionalità per la creazione di interfacce e metodi e classi di interfaccia che non esiste.

Prova a guardare la Pex , Un progetto di microsoft sul test di unità , che è ancora in fase di ricerca

research.microsoft.com/en-us/projects/Pex/

Io credo che quello che cerchi è un fuzzing tool kit (https://en.wikipedia.org/wiki/Fuzz_testing).

Al duro non l'ho mai usato, si potrebbe dare Randoop.NET possibilità di generare il test di unità' http://randoop.codeplex.com/

Visual Studio viene fornito con alcune caratteristiche che possono essere utili per voi qui:

Generare Stub Del Metodo.Quando si scrive una chiamata a un metodo che non esiste, avrai un po ' di smart tag il nome del metodo che è possibile utilizzare per generare un metodo stub sulla base dei parametri si sta passando.

Se hai una tastiera persona (io), poi a destra dopo aver digitato la parentesi di chiusura, si può fare:

  • Ctrl-. (per aprire lo smart tag)
  • INSERIRE (per generare stub)
  • F12 (vai a definizione, per raggiungere il nuovo metodo)

Gli smart tag viene visualizzato solo se l'IDE pensa che non c'è un metodo che corrisponde.Se si desidera generare quando lo smart tag non è, si può andare per Modifica->Intellisense->Generare Stub Del Metodo.

Frammenti di.Piccoli modelli di codice che lo rende facile generare bit di codice comune.Alcuni sono semplici (provare "se[TAB][TAB]).Alcuni sono complessi ('switch' generare casi per un enum).Si può anche scrivere il proprio.Per il tuo caso, cerca di "classe" e "prop".

Vedi anche "Come cambiare “Metodo Generate Stub” per lanciare NotImplementedException in VS?"per informazioni frammenti in un contesto di GMS.

autoprops.Ricordate che la proprietà può essere molto più semplice:

public string Name { get; set; }

creare una classe.In Esplora soluzioni, RClick sul nome del progetto o in una sottocartella, selezionare Aggiungi->Classe.Digitare il nome della nuova classe.Hit INSERIRE.Si otterrà una dichiarazione di classe nel diritto dello spazio dei nomi, etc.

Implementare l'interfaccia.Quando si desidera che una classe implementa un'interfaccia, scrivere il nome dell'interfaccia da parte, attivare la smart tag e selezionare l'opzione per generare stub per i membri di interfaccia.

Questi non sono abbastanza 100% automatico soluzione che si sta cercando, ma penso che sia una buona attenuazione.

Trovo che ogni volta che ho bisogno di una generazione di codice strumento come questo, io sono probabilmente la scrittura di codice che potrebbe essere reso un po ' più generico e quindi ho solo bisogno di scrivere una volta.Nel tuo esempio, quelli di getter e setter, non sembrano essere l'aggiunta di qualsiasi valore per il codice, infatti, è in realtà solo affermare che il getter/setter meccanismo in C# funziona.

Dovrebbe astenersi dallo scrivere (o anche utilizzando tale strumento prima di capire che le motivazioni per la scrittura di questi tipi di test sono.

BTW, si potrebbe desiderare di avere uno sguardo a NBehave?

Io uso Rhino Prende in giro per questo, quando ho solo bisogno di un semplice stub.

http://www.ayende.com/wiki/Rhino+Mocks+-+Stubs.ashx

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top