haskell - test - quick check near me
Haskell quickcheck: cómo generar solo cadenas imprimibles (2)
Actualmente, QuickCheck
tiene un tipo PrintableString
, que también tiene una instancia de arbitrary
, lo que significa que puede generar fácilmente cadenas arbitrarias con:
arbitraryPrintableString :: Gen String
arbitraryPrintableString = getPrintableString <$> arbitrary
Tengo un conjunto de programas de demostración simples que codifican / decodifican cadenas, y quiero generar algunas pruebas de QuickCheck para ellas, pero para limitar las pruebas solo a cadenas imprimibles. El uso de una guarda es demasiado lento y falla debido a la cantidad de casos de prueba generados y rechazados, así que quiero crear un generador seguro para este dominio.
Las referencias a esto que he visto dicen a (1) definir la propia instancia arbitraria de Char y usarla para generar solo caracteres imprimibles para cadenas, o (2) tener que envolver las funciones en un nuevo tipo y escribir un Arbitrary instancia para eso.
Pero intentar hacerlo (1) falla porque ahora hay una definición para esto en Test.QuickCheck, y entonces, ¿cómo se haría esto? Crear un generador de SafeChar para un nuevo tipo y luego volver a tener que producir un adaptador para las funciones probadas. ? (La sección del libro de RWH en esta nota indica que está desactualizada al recomendar esta definición de DIY Char).
Tratar de hacer (2) parece que puedo agregar una protección a la propuesta de prueba que es localizada y simple (pero falla), o escribir un nuevo envoltorio y un generador asociado, lo que parece más complicado.
Claramente, esto es simple (!) Y se proporcionan todas las herramientas, pero ¿podría alguien avisar si este es un análisis correcto y dar un ejemplo de cómo hacer esto de la mejor manera?
El punto de partida es definitivamente un generador genSafeChar
, que puede tener el tipo Gen Char
. Por ejemplo:
genSafeChar :: Gen Char
genSafeChar = elements [''a''..''z'']
Luego puede construirlo en un generador genSafeString
, por ejemplo, con listOf
:
genSafeString :: Gen String
genSafeString = listOf genSafeChar
En este punto tienes un par de opciones razonables. O bien hacer un envoltorio newtype
para String
:
newtype SafeString = SafeString { unwrapSafeString :: String }
deriving Show
instance Arbitrary SafeString where
arbitrary = SafeString <$> genSafeString
(En este caso, puede que solo genSafeString
la definición de genSafeString
)
y luego puedes usarlo así:
testWibble (SafeString str) = str == str
O puede usar forAll
en cada punto en el que necesite una cadena segura:
testWibble = forAll genSafeString $ /str -> str == str