【发布时间】:2016-07-28 19:05:20
【问题描述】:
我需要测试很多访问数据库的函数(通过 Persistent)。虽然我可以使用monadicIO 和withSqlitePool 来做到这一点,但它会导致测试效率低下。每个测试,而不是属性,而是测试,都会创建和销毁数据库池。如何防止这种情况发生?
重要:忘记效率或优雅。我什至无法使QuickCheck 和Persistent 类型组合起来。
instance (Monad a) => MonadThrow (PropertyM a)
instance (MonadThrow a) => MonadCatch (PropertyM a)
type NwApp = SqlPersistT IO
prop_childCreation :: PropertyM NwApp Bool
prop_childCreation = do
uid <- pick $ UserKey <$> arbitrary
lid <- pick $ LogKey <$> arbitrary
gid <- pick $ Aria2Gid <$> arbitrary
let createDownload_ = createDownload gid lid uid []
(Entity pid _) <- run $ createDownload_ Nothing
dstatus <- pick arbitrary
parent <- run $ updateGet pid [DownloadStatus =. dstatus]
let test = do
(Entity cid child) <- run $ createDownload_ (Just pid)
case (parent ^. status, child ^. status) of
(DownloadComplete ChildrenComplete, DownloadComplete ChildrenNone) -> return True
(DownloadComplete ChildrenIncomplete, DownloadIncomplete) -> return True
_ -> return False
test `catches` [
Handler (\ (e :: SanityException) -> return True),
Handler (\ (e :: SomeException) -> return False)
]
-- How do I write this function?
runTests = monadicIO $ runSqlite ":memory:" $ do
-- whatever I do, this function fails to typecheck
【问题讨论】:
-
你能举一个你的快速检查属性的例子吗?
-
您不想在调用
monadicIO之外使用withSqlitePool吗?例如,tests = withSqlitePool $ \pool -> do monadicIO (test1 pool); monadicIO (test2 pool). -
我们使用 SQLite 连接到
:memory:(我认为这或多或少只是一个内存 SQLite 数据库)。它似乎工作得很好,当然永远不会成为瓶颈,但也许你移动的数据比我们多。您可以做的缓慢而艰巨的事情是创建自己的PersistStore实例并使用(例如)一堆Data.Maps 来实现它。但这绝对会阻止您在Database.Persist.Sql中使用任何东西,在这种情况下,您将需要花费一臂之力来构造SqlBackend值。 -
添加了测试的伪代码。现在在手机上,将添加我笔记本电脑上的实际代码。
-
基本上我正在寻找的是一个高效的样板,它设置数据库一次,维护一个连接池,并在测试/属性之间清除数据库。
标签: haskell persistent quickcheck