Comincerò con sndBigger
- si tratta di una funzione molto semplice, ma è possibile scrivere alcune proprietà che dovrebbero tenere su di esso. Per esempio, cosa succede quando si invertire i valori nella tupla:
// Reversing values of the tuple negates the result
let swap (a, b) = (b, a)
let prop_sndBiggerSwap x =
sndBigger x = not (sndBigger (swap x))
// If two elements of the tuple are same, it should give 'false'
let prop_sndBiggerEq a =
sndBigger (a, a) = false
EDIT: Questa regola prop_sndBiggerSwap
non sempre avviene (vedi commento di KVB ). Tuttavia il seguente dovrebbe essere corretta:
// Reversing values of the tuple negates the result
let prop_sndBiggerSwap a b =
if a <> b then
let x = (a, b)
sndBigger x = not (sndBigger (swap x))
Per quanto riguarda la funzione di pairs
, KVB già postato alcune buone idee. Inoltre, è possibile controllare che riportare l'elenco trasformato in un elenco di elementi restituisca l'elenco originale (sarà necessario gestire il caso quando l'elenco di input è dispari, a seconda di cosa dovrebbe fare la funzione pairs
in questo caso):
let prop_pairsEq (x:_ list) =
if (x.Length%2 = 0) then
x |> pairs |> List.collect (fun (a, b) -> [a; b]) = x
else true
per splitOn
, possiamo testare cosa simile - se concatenare tutte le liste restituite, dovrebbe dare la lista originale (questo non consente di verificare il comportamento scissione, ma è una buona cosa per cominciare - almeno garantisce che nessun elemento sarà perso).
let prop_splitOnEq f x =
x |> splitOn f |> List.concat = x
io non sono sicuro se FsCheck in grado di gestire questo però (!) Perché la proprietà prende una funzione come argomento (per cui sarebbe necessario generare "funzioni casuali"). Se questo non funziona, dovrai fornire un paio di proprietà più specifiche con alcune funzioni scritte a mano f
. Successivamente, l'attuazione del controllo che f
restituisce vero per tutte le coppie adiacenti negli elenchi a spacco (come KVB suggerisce) in realtà non è poi così difficile:
let prop_splitOnAdjacentTrue f x =
x |> splitOn f
|> List.forall (fun l ->
l |> Seq.pairwise
|> Seq.forall (fun (a, b) -> f a b))
Probabilmente l'unica ultima cosa che si potrebbe verificare è che f
restituisce false
quando gli si assegna l'ultimo elemento da una lista e il primo elemento dall'elenco successivo. Quanto segue non è del tutto completa, ma mostra la strada da percorrere:
let prop_splitOnOtherFalse f x =
x |> splitOn f
|> Seq.pairwise
|> Seq.forall (fun (a, b) -> lastElement a = firstElement b)
L'ultimo esempio mostra anche che si dovrebbe verificare se la funzione splitOn
può restituire un elenco vuoto come parte della lista restituita dei risultati (perché in quel caso, non potresti trovare il primo/ultimo elemento).
Grazie per i suggerimenti. Sto già verificando l'eccezione con xUnit, quindi nessun valore aggiunto lì (per quanto posso dire?).Al momento tutto sembra molto pensieroso per me e, come dici tu, in questi casi specifici, i test rischiano di essere più complicati degli originali. – Benjol
Gli assegni non dovrebbero essere più complicati, anzi, ciò vanifica lo scopo del test. ma possono essere ugualmente complessi, secondo la mia esperienza. Con il tempo, la tua implementazione potrebbe diventare più complessa (ad es. Ottimizzazioni), mentre le proprietà/specifiche di solito rimangono più o meno le stesse. Quindi, anche se potrebbe non avere senso ora, probabilmente sarai felice con le proprietà in seguito. –