Question

J'aimerais transmettre un entier comme argument CLI à un programme Haskell qui utilise QuickCheck / monadicIO.Cet entier va être utilisé à l'intérieur du assert pour rendre les tests personnalisables.Le problème est qu'une fois que j'analyse la valeur entière dans main, je ne sais pas comment le passer à l'intérieur du monadicIO appeler sans utiliser quelque chose d'aussi laid qu'un IORef.Je pense qu'une solution élégante pourrait être la Reader monade, mais je n'ai pas trouvé de solution pour que ça marche, vu comme quickCheck est rigide dans ses arguments.Des idées?

Modification ultérieure 1 : Comme demandé, je joins le code sur lequel j'essaie cela et j'échoue.Les lignes commentées représentent ma tentative ratée.Arrière-plan:la suite de tests est destinée à exercer un point de terminaison distant très simple qui calcule le SHA512 de l'entrée aléatoire générée par QuickCheck.Le point de terminaison distant est basé sur Python/Flask.

Plus tard, modifiez 2 en réponse à @ user2407038 : je pourrais faire propHasExpectedLengthCeiling prendre un argument supplémentaire de type Int, mais quickCheck générerait des valeurs aléatoires pour cela, et ce n'est pas ce que je veux qu'il se produise.Mon objectif est d'utiliser le maxSegmentLengthCeiling que je récupère des arguments de ligne de commande et que je l'utilise dans let testPassed = actualMaxSegmentLength <= maxSegmentLengthCeiling à l'intérieur du monadicIO bloc.Tout de suite maxSegmentLengthCeiling est spécifié comme valeur de niveau supérieur, ce qui signifie que je dois recompiler le code chaque fois que je modifie la valeur.Je n'ai pas encore de code impliquant IORef parce que c'est un dernier recours et l'essentiel de ma question est de savoir comment éviter d'aller dans ce sens. IORef itinéraire.

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
Était-ce utile?

La solution

Faire maxSegmentLengthCeiling un paramètre à propHasExpectedLengthCeiling :

propHasExpectedLengthCeiling :: Int -> CustomInput -> Property

et l'invoquer comme

main = do 
  [n] <- getArgs
  quickCheckWith customArgs (propHasExpectedLengthCeiling (read n))
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top