【发布时间】:2020-01-06 09:51:15
【问题描述】:
我正在尝试测试自定义数据类型的逻辑。它接收一个 Map Int String 作为参数,然后我需要在对象内的 Map 中添加一个元素。
类型声明和插入函数如下所示:
import qualified Data.IntMap.Strict as M
import Data.UUID (UUID)
import Control.Monad.State
import System.Random
type StrMap = M.IntMap String
type MType = State StdGen
data MyType = MyType {
uuid :: UUID,
strs :: StrMap
} deriving (Show)
create :: StrMap -> MType MyType
create pm = do
state <- get
let (uuid, newState) = random state
put newState
return $ MyType uuid pm
strsSize :: MyType -> Int
strsSize e = M.size $ strs e
addStr :: MyType -> String -> MyType
addStr e p = e { strs = M.insert (strsSize e) p $ strs e }
在 Map 中具有顺序键很重要,因此具有 [0, 1, 3] 是不可接受的。 我正在尝试使用 HSpec 和 QuickCheck 对其进行测试:
main :: IO ()
main = hspec spec
spec :: Spec
spec = describe "Creation and update" $ do
QuickCheck.prop "Check map addition" $ do
\xs str -> monadicIO $ do
state <- run(getStdGen)
let (result, newState) = runState (create xs) state
run(setStdGen newState)
let result' = addStr result str
assert $ (strsSize result) + 1 == strsSize result' -- fails here
问题是 QuickCheck 生成随机键,我不确定如何强制它为 Map 生成顺序键。缺少序列的问题是函数 addStr 可能会在重复键的情况下覆盖值,这是不可取的行为。
更新
感谢大家的帮助!经过长时间的讨论和某种思考,我最终得到了以下解决方案:
spec :: Spec
spec = describe "Creation and update" $ do
QuickCheck.prop "Check map addition" $ do
\xs str -> not (null xs) Property.==> monadicIO $ do
state <- run(getStdGen)
let mp = M.fromList $ zip [0..(length xs)] xs
let (result, newState) = runState (create mp) state
run(setStdGen newState)
let result' = addStr result str
assert $ (strsSize result) + 1 == strsSize result'
基本上,我必须生成一些随机字符串集,然后手动将它们转换为地图。它可能不是最优雅的解决方案,但它可以根据需要工作。
【问题讨论】:
-
当您说 QuickCheck 正在生成“随机密钥”时,您的意思是它正在生成随机的
StrMaps?这个问题我很难理解。 -
这不是一个最小可重现示例,所以我不能确定,但
(M.size . strs result)看起来像一个类型错误。如果您的示例代码无法编译,就很难回答这样的问题。 -
它正在生成一个地图,其内容如下:{(0, "xyz"), (3, "qwerty")} 或只是 {(5, "asd")}。就我而言,我需要确保键始终从零开始,并且它们之间没有间隙,即键应始终为 0,1,2,3,4,...
-
我认为这根本不是您需要的。我看不出这与您正在检查的财产有什么关系。您永远不会以任何方式实际测试 键的值,只测试连续映射的相对大小。
-
当然你可以澄清它是否编译。这是您的代码,您可以尝试编译它。
addStr是类型错误我错了,但我不得不猜测这些事情,因为您提供的代码不完整,根本无法编译。
标签: haskell quickcheck