Domanda

Mi piacerebbe passare un numero intero come argomento CLI a un programma Haskell che fa uso di QuickCheck / monadicIO. Quel numero intero verrà utilizzato all'interno del assert per rendere i test personalizzabili. Il problema è che una volta analizzato il valore intero in main, non so come passarlo all'interno della chiamata monadicIO senza usare qualcosa come brutto come IORef. Penserei che una soluzione elegante potrebbe essere la monada Reader, ma non riesco a trovare una soluzione per farlo funzionare, visto come quickCheck è rigido nei suoi argomenti. Qualche idea?

Modifica successiva 1: Come richiesto, sto collegando il codice attuale che sto provando questo, e fallendo. Le linee commentate rappresentano il mio tentativo fallito. Sfondo: la suite di prova ha lo scopo di esercitare un endpoint remoto molto semplice che calcola lo SHA512 dell'ingresso randomizzato generato da QuickCheck. L'endpoint remoto è basato su Python / Boccette.

in seguito Modifica 2 In risposta a @ user2407038: Potrei rendere propHasExpectedLengthCeiling a prendere un argomento aggiuntivo di tipo int, ma quickCheck genererebbe valori casuali per questo, e non è quello che voglio accadendo. Il mio obiettivo è usare il maxSegmentLengthCeiling che sto intraprendendo dagli argomenti della riga di comando e lo usano in let testPassed = actualMaxSegmentLength <= maxSegmentLengthCeiling all'interno del blocco monadicIO. In questo momento maxSegmentLengthCeiling è specificato come valore di alto livello, il che significa che devo ricompilare il codice ogni volta che modifico il valore. Non ho ancora alcun codice che coinvolga IORef perché è un'ultima risorsa e l'essenza della mia domanda è come evitare di andare alla rotta IORef.

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
.

È stato utile?

Soluzione

Rendere maxSegmentLengthCeiling un parametro su propHasExpectedLengthCeiling:

propHasExpectedLengthCeiling :: Int -> CustomInput -> Property
.

e invocalo come

main = do 
  [n] <- getArgs
  quickCheckWith customArgs (propHasExpectedLengthCeiling (read n))
.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top