2016-01-07 12 views
6

Sono un n00b al test di unità. Ho installato FsCheck.Nunit e NUnitTestAdapter da Nuget e sto provando a fare test basati sulle proprietà, in gran parte ispirati a the inestimable Scott Wlaschin.Come posso riprovare un test basato sulla proprietà se gli input generati casualmente non sono utili?

Sto usando l'attributo [<Property>], e vorrei la possibilità di "saltare" gli ingressi che non soddisfano i requisiti della prova:

[<Property(MaxTest=10)>] 
let ``Calling unzipTo with an invalid destination will yield a failure.`` badDest = 
    if Directory.Exists(badDest) 
    then // somehow skip to the next randomized input 
    else // do the actual test 

Qual è il modo più semplice per fare questo?

Preferirei una risposta per FsCheck/NUnit se esiste, ma prenderei in considerazione qualsiasi altro framework i cui test possano essere eseguiti in Visual Studio. (Pensavo di aver visto qualche framework dove c'era una semplice funzione per fare esattamente questo, ma non riesco a capire di cosa si trattasse.)

Ho preferito FsCheck.NUnit finora perché può generare input casuali per F # tipi (sindacati discriminati, ecc.) senza ulteriore lavoro.

+0

È necessario un generatore personalizzato. –

+0

IIRC per l'istruzione then è sufficiente restituire il risultato che indica il test riuscito senza eseguire il test. Qualcosa di semplice come "vero" potrebbe funzionare.Mi sono imbattuto in questi anni fa e il problema è stato il pensiero eccessivo. Ricorda che il test è solo una funzione e il test driver vuole solo un risultato che indichi il successo o l'insuccesso, quindi dargli un successo. –

+0

@Guy Coder Lo sfregio è che voglio che il test venga ripetuto con diversi input casuali se quelli generati non sono utili - Non voglio che la funzione venga eseguita molte volte con input inadatti e dichiari un successo se non ha mai effettivamente eseguito il test. –

risposta

6

Si dovrebbe essere in grado di fare qualcosa del genere:

open FsCheck 
open FsCheck.Xunit 

[<Property(MaxTest=10)>] 
let ``Calling unzipTo with an invalid destination will yield a failure.`` badDest = 
    (not Directory.Exists(badDest)) ==> lazy 
    // do the actual test 

La prima riga è una condizione booleana, e ==> è un operatore personalizzato definito dal modulo FsCheck. Sarà forzata solo la valutazione dell'espressione pigra se la condizione sul lato destro è pari a true.

Considerare, tuttavia, il refactoring di questo test in modo che non dipenda dal file system. Il file system è persistente, in modo che venga creata automaticamente una Fix Persistent, che è a lot of trouble to manage; non impossibile da gestire, ma meglio evitare.

Questo esempio utilizza FsCheck.Xunit, ma IIRC FsCheck.Nunit funziona allo stesso modo. Si dovrebbe seriamente considerare l'utilizzo di FsCheck.Xunit invece di FsCheck.Nunit, tuttavia. Il modello di estensibilità di NUnit 2 è straordinariamente scadente, il che significa che la maggior parte delle librerie di colla che tentano di estendere NUnit hanno molti problemi. Questo non è un problema con FsCheck.Nunit, ma con NUnit stesso, ma si manifesterà in un sacco di problemi per voi.

+0

Fantastico, è esattamente quello che stavo cercando. Probabilmente l'ho visto sul tuo blog in primo luogo. Grazie per il suggerimento su NUnit vs Xunit. –

+0

Normalmente cerco di mantenere i test indipendenti dal file system, dallo stato del database, ecc., Ma per le funzioni che sto sviluppando qui, la manipolazione del file system è il loro scopo principale. In quale altro modo posso testarli a tutti? –

+0

@OverlordZurg Forse questa risposta risponde a questa domanda: http://codereview.stackexchange.com/a/99290/3878 ... o forse non lo è :) –

0

Non ho molta familiarità con F # o fscheck, ma NUnit fornisce la funzione Assert.Ignore(), che interromperà immediatamente il test e contrassegnato come "ignorato". Potresti anche utilizzare Assert.Inconclusive() o Assert.Pass() se ritieni che si tratti di stati più appropriati.

+0

Ho provato "Assert.Ignore()", ma questo causa l'esito negativo dei test contrassegnati con l'attributo [], che non è il comportamento che voglio. –

1

FsCheck.Prop.discard() sembra fare ciò che voglio: quando eseguo il test con la registrazione, vedo che alcuni tentativi sono stati scartati, ma sono state completate 10 corse senza essere scartate.

L'operatore ==> funziona per l'esecuzione dei test con FsCheck.Quick o simili. Tuttavia, ciò richiede che la parte pigra sia nel formato di "Testabile", dove i test che sto attualmente scrivendo sono solo <inputs>->unit.

+1

* "che richiede che la parte pigra sia nel formato di 'Testabile' * Questo non dovrebbe essere un problema. Il compilatore dedurrà il tipo appropriato per te. Vedi qui per gli esempi: http://blog.ploeh.dk/2015/09/08/ad-hoc-arbitraries-with-fscheckxunit –

+2

Chiamando 'scarta' nel tuo ramo' then', o usando l'approccio con '== > 'dovrebbe essere completamente equivalente. Anche se '==>' è l'approccio preferito - legge meglio imo e 'discard' funziona lanciando e catturando un'eccezione sotto il cofano, quindi può essere lento e dirompente per il debug. –

+0

Trovato il problema - stavo cercando di restituire l'unità, ma avevo bisogno di restituire bool. Sfortunatamente, restituire bool dalla parte pigra (piuttosto che Assert.AreEqual()) mi fa perdere la bella formattazione che indica esplicitamente il valore atteso rispetto al valore reale. Sto continuando ad esplorare le opzioni, ma almeno ora capisco :) –

Problemi correlati