I have written a Fuzzer that generates fixed length alphanumeric (latin) strings. The generation works fine, but I cannot figure out how to apply a shrinker that generates a shrunk value that conforms to my length restriction and shrinks appropriately.
If I implement the Fuzzer
like below it generates the appropriate string but shrinks incorrectly to empty string :
module HotFuzz exposing (..)
import Fuzz exposing (..)
import Random.Char as RandomChar
import Random.Extra as RandomExtra
import Shrink as Shrink exposing (Shrinker)
nLengthUpperCaseAlphanumeric: Int -> Fuzzer String
nLengthUpperCaseAlphanumeric length =
let
charGen = RandomExtra.choices (RandomChar.char 48 57) [RandomChar.upperCaseLatin]
gen = RandomString.string length charGen
charShrinker = Shrink.atLeastChar '0'
shrinker = Shrink.convert (String.fromList) (String.toList) (Shrink.list charShrinker)
in
custom gen shrinker
I’ve also tried some more advanced shrinking but it doesn’t do what I want.
What I want is to have is a Shrinker that demonstrates the following properties:
- The shrunk string should shrink to a string of length
"length"
- The shrunk string should have each char in it shrunk to
'0'
(i.e. for size 3ABB
should shrink to000
)
I’ve also tried a more advanced (convoluted) Shrinker that I’m not sure even shrinks:
nLengthUpperCaseAlphanumeric : Int -> Fuzzer String
nLengthUpperCaseAlphanumeric length =
let
charGen = RandomExtra.choices (RandomChar.char 48 57) [RandomChar.upperCaseLatin]
gen = RandomString.string length charGen
charShrinker = Shrink.atLeastChar '0'
mkString ch = List.repeat length ch |> String.fromList
shrinker str =
str
|> String.toList
|> List.map (\_ -> '0')
|> List.head
|> Maybe.withDefault '0'
|> charShrinker
|> Shrink.map mkString
in
custom gen shrinker
This “shrinker” does keep my string length to the expected length, but it collapses to more choices than I’d expect.