Frage

Ich möchte eine Ganzzahl als CLI-Argument an ein Haskell-Programm übergeben, das QuickCheck / verwendet. monadicIO.Diese Ganzzahl wird innerhalb von verwendet assert um die Tests anpassbar zu machen.Das Problem ist, dass ich den ganzzahligen Wert einmal analysiere main, ich weiß nicht, wie ich es hineingeben soll monadicIO Rufen Sie an, ohne etwas so Hässliches wie ein zu verwenden IORef.Ich würde denken, dass eine elegante Lösung das sein könnte Reader monad, aber ich konnte keine Lösung finden, damit es funktioniert, gesehen als quickCheck ist in seinen Argumenten starr.Irgendwelche Ideen?

Spätere Bearbeitung 1: Wie gewünscht füge ich den eigentlichen Code bei, mit dem ich das versuche, aber es schlägt fehl.Die auskommentierten Zeilen stellen meinen gescheiterten Versuch dar.Hintergrund:Die Testsuite soll einen sehr einfachen Remote-Endpunkt testen, der den SHA512 der von QuickCheck generierten zufälligen Eingabe berechnet.Der Remote-Endpunkt basiert auf Python/Flask.

Später Edit 2 als Antwort an @user2407038: ich kann ... machen propHasExpectedLengthCeiling Nehmen Sie ein zusätzliches Argument vom Typ Int, aber quickCheck würde dafür zufällige Werte generieren, und das ist nicht das, was ich möchte.Mein Ziel ist es, das zu nutzen maxSegmentLengthCeiling dass ich die Befehlszeilenargumente übernehme und darin verwende let testPassed = actualMaxSegmentLength <= maxSegmentLengthCeiling innerhalb der monadicIO Block.Im Augenblick maxSegmentLengthCeiling wird als Wert der obersten Ebene angegeben, was bedeutet, dass ich den Code jedes Mal neu kompilieren muss, wenn ich den Wert ändere.Ich habe noch keinen entsprechenden Code IORef denn das ist der letzte Ausweg und der Kern meiner Frage ist, wie ich das vermeiden kann IORef Route.

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
War es hilfreich?

Lösung

Machen maxSegmentLengthCeiling ein Parameter für propHasExpectedLengthCeiling :

propHasExpectedLengthCeiling :: Int -> CustomInput -> Property

und rufe es auf als

main = do 
  [n] <- getArgs
  quickCheckWith customArgs (propHasExpectedLengthCeiling (read n))
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top