QuickCheck / を利用する Haskell プログラムに CLI 引数として整数を渡したいと思いますmonadicIO
。その整数はassert
、テストをカスタマイズ可能にするために内部で使用されます。問題は、 の整数値を解析するmain
とmonadicIO
、IORef
. Reader
洗練された解決策はモナドかもしれないと思いますが、それを機能させるための解決策を見つけることができませんでしquickCheck
た。何か案は?
後で編集1:要求に応じて、これを試して失敗している実際のコードを添付しています。コメントアウトされた行は、失敗した試みを表しています。背景: このテスト スイートは、QuickCheck によって生成されたランダム化された入力の SHA512 を計算する非常に単純なリモート エンドポイントを実行することを目的としています。リモート エンドポイントは Python/Flask ベースです。
@ user2407038 に応じて後で編集 2:propHasExpectedLengthCeiling
Int 型の追加の引数を取ることができますが、quickCheck
ランダムな値が生成されますが、それは私が望んでいることではありません。私の目標はmaxSegmentLengthCeiling
、コマンド ライン引数から取得した を使用し、それをブロックlet testPassed = actualMaxSegmentLength <= maxSegmentLengthCeiling
内で使用することです。monadicIO
現在maxSegmentLengthCeiling
、最上位の値として指定されているため、値を変更するたびにコードを再コンパイルする必要があります。IORef
これは最後の手段であり、私の質問の本質は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