باستخدام القارئ موناد مع كويك تشيك / موناديسيو
-
21-12-2019 - |
سؤال
أود أن تمرير عدد صحيح كوسيطة كلي لبرنامج هاسكل الذي يجعل من استخدام كويكشيك / monadicIO
.سيتم استخدام هذا العدد الصحيح داخل assert
لجعل الاختبارات قابلة للتخصيص.المشكلة هي أنه بمجرد تحليل قيمة عدد صحيح في main
, ، أنا لا أعرف كيفية تمريرها داخل monadicIO
اتصل دون استخدام شيء قبيح مثل IORef
.أعتقد أن الحل الأنيق قد يكون Reader
موناد ، ولكن لم أتمكن من العثور على حل لجعلها تعمل ، ينظر إليها على أنها quickCheck
جامدة في حججها.أي أفكار?
في وقت لاحق تحرير 1: كما هو مطلوب ، أقوم بإرفاق الرمز الفعلي الذي أحاول تشغيله ، وفشل.تمثل الخطوط المعلقة محاولتي الفاشلة.معلومات أساسية:ويهدف جناح الاختبار إلى ممارسة نقطة نهاية بعيدة بسيطة جدا أن يحسب شا 512 من المدخلات العشوائية التي تم إنشاؤها بواسطة كويكشيك.نقطة النهاية عن بعد هي بيثون / قارورة مقرها.
في وقت لاحق تحرير 2 ردا على @ المستخدم2407038: أنا يمكن أن تجعل propHasExpectedLengthCeiling
خذ حجة إضافية من نوع كثافة العمليات ، ولكن 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
المحلول
جعل maxSegmentLengthCeiling
معلمة إلى propHasExpectedLengthCeiling
:
propHasExpectedLengthCeiling :: Int -> CustomInput -> Property
واستدعاء ذلك على النحو التالي
main = do
[n] <- getArgs
quickCheckWith customArgs (propHasExpectedLengthCeiling (read n))