Utilizando el Lector de la mónada con QuickCheck / monadicIO
-
21-12-2019 - |
Pregunta
Me gustaría pasar un entero como un CLI argumento a un Haskell programa que hace uso de QuickCheck / monadicIO
.Que entero va a ser utilizado en el interior de la assert
para realizar las pruebas personalizables.El problema es que una vez que analizar el valor entero en main
, No sé cómo pasar dentro de la monadicIO
llame sin el uso de algo tan feo como un IORef
.Yo creo que una solución elegante podría ser el Reader
mónada, pero no pude encontrar una solución para hacer el trabajo, visto como quickCheck
es rígido en sus argumentos.Alguna idea?
Más Tarde Edit 1: Conforme a lo solicitado, estoy adjuntando el código real que estoy tratando en este, y en su defecto.La comentada líneas de representar a mi intento fallido.Antecedentes:la suite de prueba es la intención de ejercer una forma muy sencilla extremo remoto que calcula el SHA512 de la aleatorios de entrada generados por QuickCheck.El extremo remoto de Python/Matraz de base.
Después de Editar 2 en respuesta a @user2407038: Yo podría hacer propHasExpectedLengthCeiling
tome un argumento de tipo Int, pero quickCheck
iba a generar valores aleatorios para ella, y eso no es lo que quiero que suceda.Mi objetivo es utilizar la maxSegmentLengthCeiling
que estoy tomando desde los argumentos de línea de comandos y el uso en let testPassed = actualMaxSegmentLength <= maxSegmentLengthCeiling
en el interior de la monadicIO
el bloque.Ahora mismo maxSegmentLengthCeiling
se especifica como un valor de nivel superior, lo que significa que tengo que volver a compilar el código cada vez que cambie el valor.Yo aún no tiene ningún código que implica IORef
debido a que es un último recurso y la esencia de mi pregunta es como evitar el IORef
de la ruta.
import qualified Data.ByteString.Lazy.Char8 as LC
import Control.Applicative ( (<$>) )
import Data.Function ( on )
import Data.List ( groupBy )
import Data.Char ( isDigit )
--import Safe ( headMay
-- , readMay
-- )
--import System.Environment ( getArgs )
import Network.HTTP.Conduit ( simpleHttp )
import Test.QuickCheck ( Arbitrary
, Property
, arbitrary
, choose
, frequency
, quickCheckWith
, stdArgs
, vectorOf
)
import Test.QuickCheck.Test ( Args
, maxSuccess
)
import Test.QuickCheck.Monadic ( assert
, monadicIO
, run
)
newtype CustomInput = MkCustomInput String deriving Show
instance Arbitrary CustomInput where
arbitrary =
let
genCustomInput = vectorOf 20
$ frequency [ (26, choose ('0','9'))
, (10, choose ('a','z'))
]
in
MkCustomInput <$> genCustomInput
maxSegmentLengthCeiling :: Int
maxSegmentLengthCeiling = 22
urlPrefix :: String
urlPrefix = "http://192.168.2.3:5000/sha512sum/"
propHasExpectedLengthCeiling :: CustomInput -> Property
propHasExpectedLengthCeiling (MkCustomInput input) = monadicIO $ do
testPassed <- run $ do
response <- simpleHttp $ urlPrefix ++ input
let stringResponse = LC.unpack response
let brokenDownStringResponse = groupBy ( (==) `on` isDigit ) stringResponse
let actualMaxSegmentLength = maximum $ map length brokenDownStringResponse
let testPassed = actualMaxSegmentLength <= maxSegmentLengthCeiling
putStrLn ""
putStrLn ""
putStrLn $ "Input: " ++ input
putStrLn $ "Control sum: " ++ stringResponse
putStrLn $ "Breakdown: " ++ show brokenDownStringResponse
putStrLn $ "Max. length: " ++ show actualMaxSegmentLength
putStrLn $ "Ceiling: " ++ show maxSegmentLengthCeiling
putStrLn $ "Test result: " ++ if testPassed then "Pass" else "Fail"
putStrLn ""
putStrLn ""
return testPassed
assert $ testPassed
customArgs :: Args
customArgs = stdArgs { maxSuccess = 1000000 }
--readMayAsInt :: String -> Maybe Int
--readMayAsInt = readMay
main :: IO ()
main =
--main = do
-- cliArgs <- getArgs
-- let ceilingInputMay = headMay cliArgs >>= readMayAsInt
-- maxSegmentLengthCeiling <- case ceilingInputMay of
-- (Just lengthCeiling) -> return lengthCeiling
-- Nothing -> error "No valid number given"
quickCheckWith
customArgs
propHasExpectedLengthCeiling
Solución
Hacer maxSegmentLengthCeiling
un parámetro para propHasExpectedLengthCeiling
:
propHasExpectedLengthCeiling :: Int -> CustomInput -> Property
y llámalo como
main = do
[n] <- getArgs
quickCheckWith customArgs (propHasExpectedLengthCeiling (read n))