Come strutturare i test unitari per un'app GUI usando C # e NUnit


16

Mi è stato chiesto di fare un piccolo progetto laterale per fornire una semplice applicazione a uno dei nostri clienti. Normalmente lavorerei sul codice di back-end in cui ho capito tutti i miei bisogni di test, e non ho ancora avuto il dubbio piacere di scrivere test per la GUI, quindi non è chiaro per me come dovrei impostare il codice di test e gli strumenti per un EXE.

Il mio primo istinto era quello di includere semplicemente i test con il codice dell'applicazione, tuttavia ciò avrebbe richiesto di fornire una serie di dipendenze specifiche per i test, che mi è stato chiesto di non spedire specificamente al cliente. Inoltre, non sono in grado di spremere denaro per uno strumento di test appositamente costruito, quindi ho bisogno di usare gli strumenti che ho a portata di mano ( StoryQ , RhinoMocks e NUnit), che in realtà dovrebbe essere più che sufficiente per testare il comportamento di una semplice app GUI. Per quanto posso vedere, questo mi lascia cercando di trovare un buon equilibrio tra il mantenimento del design davvero semplice o l'ingegnerizzazione intenzionale per motivi di test. Sembra che sto costruendo l'app con la logica aziendale in una libreria separata e testando la libreria come farei di solito, o trovando qualche altro meccanismo per consentirmi all'eseguibile senza rompere moduli aggiuntivi che il design dell'applicazione non davvero bisogno.

Modifica: si
noti che questa domanda riguarda come strutturare la relazione tra NUnit e il mio eseguibile - al contrario di una DLL - e non su come separare la presentazione e la logica aziendale.
/Modificare

Quindi la mia domanda è:

  1. Esiste un metodo specifico / consigliato per la configurazione di una semplice applicazione GUI con test unitari che mi consenta di controllare adeguatamente lo stato e il comportamento, utilizzando gli strumenti che ho a portata di mano e senza ricorrere a un eccesso di ingegneria?
  2. Ho perso qualcosa di fondamentale sul modo in cui NUnit dovrebbe essere invocato / configurato durante il test di un EXE (al contrario di una DLL)?
  3. Potete fornirmi o indicarmi la direzione di esempi di come ottenere tutto ciò?

Mi rendo conto che potrebbe esserci più di un modo per farlo, quindi sto cercando specifiche linee guida di implementazione basate sulla tua esperienza.


NUnit non è progettato per testare direttamente le GUI. È necessario separare il livello di presentazione (ad es. Vista) dai dati e la logica aziendale (ad es. Modello) in modo da poter testare ciò che passa nella vista senza utilizzare la vista.
Bernard,

1
@Bernard Questa domanda non riguarda la stratificazione di una GUI per i test. Stratifico naturalmente tutte le mie app, anche quelle banali, quindi non è un problema per me. Ho modificato la domanda in base alle esigenze e spero che chiarisca eventuali equivoci. :)
S.Robins il

1
Non c'è nulla di terribilmente complicato nelle prove di unità in EXE. Basta fare in modo che la DLL di test faccia riferimento al file EXE e il gioco è fatto.
whatsisname

Risposte:


3

In uno dei miei commenti ho menzionato la risposta del simoraman che avevo pensato a un paio di modi per farlo. Una delle mie opzioni era simile al suggerimento nella risposta di Jalayn di creare un progetto duplicato e generare una DLL, mentre la mia altra idea era quella di collegarmi semplicemente ai file nel progetto in cui c'era il codice che volevo testare. Sebbene entrambe le opzioni possano funzionare, sono tutt'altro che ideali.

Nel secondo caso, avrei un pasticcio di dipendenze di unità da gestire a meno che non potessi davvero smantellare l'architettura per minimizzare le dipendenze. Questo va bene per i progetti più piccoli, ma quelli più grandi potrebbero facilmente diventare un vero casino da gestire. La mia più grande resistenza a questa opzione è comunque la pura ineleganza di essa. Certo che potreifarlo funzionare, ma nel fare ciò ho effettivamente bisogno di rompere l'incapsulamento per testare gli interni di un assembly direttamente via sorgente, piuttosto che testare tramite le interfacce pubbliche, che secondo me è un grande no-no. Allo stesso modo avere un file di progetto aggiuntivo significherebbe duplicare gli sforzi in due progetti alla volta, o trovare un modo per aggiungere automaticamente le impostazioni del file di progetto a due file alla volta, o ricordarsi di copiare e rinominare il campo del progetto ogni volta che costruisco. Questo può essere automatizzato sul server di build, forse, ma sarebbe un problema da gestire nell'IDE. Ancora una volta, può funzionare, ma nella migliore delle ipotesi è un kludge e, nel peggiore dei casi, un fastidio.

Il modo migliore sembra essere quello che whatsisname ha commentato alla mia domanda, e semplicemente includere EXE come riferimento nel progetto di test. Si scopre che in questo caso un EXE viene effettivamente trattato allo stesso modo di una DLL e sono in grado di accedere a tutte le mie classi ben stratificate per testare qualsiasi galleggiante della mia barca.


2

Penso che:

  • Il codice del test aziendale deve trovarsi in un progetto separato, testando la libreria del codice aziendale.
  • Il codice di test della GUI dovrebbe essere in un progetto separato, testare la libreria della GUI. Ora, come costruire una libreria GUI anziché un eseguibile, provo a rispondere più tardi.
  • Se hai un my.namespace.biz.MyClass, la tua classe di test dovrebbe essere my.namespace.biz.MyClassTest (o MyClassTestCase).
  • Se si desidera testare il codice trovato nella destinazione eseguibile, è necessario disporre di un'installazione che crea un file EXE e un'altra installazione che crea una libreria (DLL) che è quella su cui verrà avviato il test.

Queste sono le regole che mi piace seguire, che si tratti di Java o C # (tranne ovviamente che non ci sono problemi EXE con Java :-))

Per quanto riguarda come configurare il tuo ambiente di test, mi sembra che tu abbia almeno queste due scelte:

Utilizzando MSBuild

Crea un clone del tuo file .proj (ad esempio myproject-as-dll.proj ). Cambia il OutputTypenel file clonato da " EXE" a " Library". Usando il comando MSBuild ora sei in grado di produrre una libreria che puoi impostare come riferimento nel tuo progetto contenente casi di test NUnit.

Mi sembra possibile, ma non l'ho mai usato così onestamente, quindi non ne sono sicuro. Inoltre, potresti non avere MSBuild sul tuo server di test di integrazione e non so se può essere separato da Visual Studio ...

Utilizzando NAnt

Se non hai familiarità con NAnt, dovrai cercare su Google come configurare le build del tuo progetto. Forse dai un'occhiata a questo , è un po 'vecchio ma l'autore ha commentato i file NAnt e se lo trova autoesplicativo ( modifica: esaminando il suo file più in dettaglio, trovo il suo file di configurazione estremamente riutilizzabile ). Fa anche molto di più che costruire, poiché esegue casi di test e lancia strumenti di copertura del codice. Ora, ammetto di non aver mai usato NAnt, contrariamente alla sua controparte Java e padre "Ant" che ho usato molto, ma vedo che è praticamente la stessa cosa e non penso che sia così difficile da imparare.

Con quello strumento puoi creare una configurazione che ti permetterà di:

  • crea tutti i tuoi progetti (business logic, GUI, ecc.) in librerie separate
  • costruisci i tuoi progetti di test
  • avviare i test (quella parte specifica viene eseguita con l' attività NUnit2 ).
  • esaminare la copertura del codice con l' attività NCover .

Con un po 'più di codice, potresti persino:

  • eseguire distribuzioni notturne nel server di integrazione
  • se NAnt è disponibile nel server di integrazione, avviare test di integrazione notturni con l'aiuto di attività pianificate

Tutto è fatto senza cambiare nulla nei file di Visual Studio. E, davvero, non mi sembra troppo ingegneristico, è solo un file. Potrebbero volerci uno, forse due giorni per far funzionare tutto, ma secondo me avrai una buona configurazione.

Infine, darei al cliente tutto ciò che è necessario per costruire, testare ed eseguire i progetti. Tendo a pensare che mostri la tua professionalità e il fatto che tu scriva codice con qualità nella tua mente (cosa che mi sembra che fai poiché stai cercando soluzioni eleganti)


0

Solo perché il progetto è piccolo (inizialmente) non significa che l'architettura corretta sia eccessiva. Il fatto che tu voglia scrivere test dice che il tuo progetto non è un hack una tantum completamente banale.

Non hai menzionato quale GUI-Framework stai usando. WPF MVVM (Model-View-ViewModel) è buono e consente di scrivere test per tutta la logica abbastanza facilmente. Con WinForms ho sentito cose positive su MVP (Model-View-Presenter)


Scrivo test per tutto il codice che scrivo. Anche le cose che potresti trovare banali. L'unica volta in cui non scrivo un test è quando faccio un picco. In questo caso, sto spedendo un'utilità una tantum a un cliente, quindi testare è più di un semplice lusso, è un requisito per soddisfare i nostri standard di qualità. In termini di "over engineering", questa non è una scelta tra architettura buona o cattiva, ma piuttosto evitare la necessità di imporre livelli aggiuntivi che non sono richiesti in questo caso poiché l'app è monouso con un ciclo di vita relativamente breve.
S.Robins,

Per quanto riguarda la scelta del gui-framework, non vedo come questo influenzerà il modo in cui l'ambiente di test è impostato. Sto cercando il HOW specifico per implementare unit test per il livello GUI usando gli strumenti che ho a disposizione. Questa risposta particolare non mi dice davvero nulla al riguardo.
S.Robins,

Simoraman - Se togliessi il primo paragrafo piuttosto giudicante, questo otterrebbe una risposta. Risolvilo e rimuoverò il mio -1. @ S.Robins nota che il secondo paragrafo è rilevante, anche se non una risposta completa, sarebbe di aiuto. Se il tuo livello di interfaccia grafica è sottile, ben strutturato e ovvio e tutta la logica aziendale viene testata da unit test a livello di modello, è possibile che non sia necessario passare attraverso la seccatura aggiuntiva di testare l'interfaccia utente in modo esplicito.
Mark Booth,

1
@MarkBooth Layering non è davvero un problema. Come dice Simiraman, posso MVP, MVVM o posso costruire qualcosa di ancora più sottile. Tuttavia, ho alcuni elementi specifici della GUI che richiedono test espliciti, motivo per cui ho deciso di scrivere questo come una domanda. Ho un paio di idee, e se il peggio peggiora so che alla fine sarò in grado di risolvere il problema e scrivere una risposta da solo. Volevo tuttavia aprirlo alla comunità poiché pensavo che sarebbe stata una buona domanda per ProgrammersSE. ;-)
S.Robins il

0

Dai un'occhiata alla mia risposta a questa domanda: Come posso configurare MVP per una soluzione Winforms?

In realtà ho scritto un'applicazione di esempio che mostra come stratifico e come collaudo la mia GUI.

leggere la modifica: utilizzare un test runner che si integri con l'ambiente di sviluppo. Uso ReSharper.


Grazie per la raccomandazione ReSharper. Questo è uno strumento che utilizzo durante lo sviluppo. Sfortunatamente non sarà utile quando si eseguono i test sul server di compilazione dell'integrazione. Inoltre non mi dice come configurare i test Nunit per accedere al codice in un exe durante il test.
S.Robins,

1
Informalmente, lo fa. Exe è solo la vista, che carica il presentatore, i modelli e i modelli di visualizzazione da una libreria di classi come parte dell'avvio dell'applicazione. Almeno nella mia soluzione, la vista è abbastanza stupida che non la testiamo con test automatici, e facciamo semplicemente test di accettazione per assicurarci che le cose siano scritte correttamente e che i pulsanti siano dove dovrebbero essere. Non testare una DLL è molto semplice.
Bryan Boettcher,

0

Avevo scritto Nunit WinForms qualche anno fa (6 anni credo). Una cosa che ricordo specificamente è che, sebbene si tratti di un caso di test unitario, funge anche da caso di test end-to-end. A volte non c'è molto da testare su un front-end (un modulo semplice). Quindi, anche se stai cercando di verificare la presenza di una finestra di messaggio che si apre con un clic sul pulsante, stai testando involontariamente vari altri metodi da altri livelli. Ci sono alcune cose che non puoi automatizzare. L'aspetto, la sensazione e l'usabilità non possono essere automatizzati mediante test di unità automatizzati. Prima di rilasciare dovrai eseguire alcuni test manuali.


Se il tuo cliente specifica che una schermata dovrebbe apparire in un certo modo o dovrebbe cambiare in un certo modo, allora dovresti essere in grado di testare queste cose. Catturare le specifiche come test è il cuore della metodologia BDD e non ho mai trovato una situazione in cui non potessi, seppure in modo creativo, trovare un modo per automatizzare un test. La vera domanda è se i test saranno utili, se l'applicazione è stata presa in considerazione abbastanza bene da consentire in primo luogo di automatizzare tutti i test e se i test saranno efficaci in termini di costi. Sono d'accordo, tuttavia, che a volte non lo sono.
S.Robins,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.