如何用hspec测试readerError函数是否被执行
How to test with hspec whether the readerError function was executed
我是 Haskell 的新手。
我已经编写了以下代码段来解析发送到脚本的参数;
module Billing.Options
(
GlobalOpts(..)
, globalOptsParser
, parseDb
) where
import Options.Applicative
import Options.Applicative.Simple
import Options.Applicative.Types
import System.FilePath.Posix
import Text.Regex.PCRE
-- ------------------------------------------------------------
data GlobalOpts = GlobalOpts
{
optDb :: String,
optSql :: String
} deriving Show
-- ------------------------------------------------------------
globalOptsParser :: Parser GlobalOpts
globalOptsParser = GlobalOpts
<$> option (parseDb =<< readerAsk)
( long "db"
<> short 'd'
<> metavar "<DB name>"
<> help "dmt | report"
)
<*> option parseSql
( long "sql"
<> metavar "<SQL SELECT statement>"
<> help "sql select statement to use in order to generate JSON config file"
)
-- ------------------------------------------------------------
matches :: String -> String -> Bool
matches = (=~)
-- ------------------------------------------------------------
parseDb :: String -> ReadM String
parseDb val = do
if not (elem val ["dmt", "report"])
then readerError $ "Unknown DB, '" ++ val ++ "'"
else return val
-- ------------------------------------------------------------
parseSql :: ReadM String
parseSql = do
val <- readerAsk
if not (val `matches` "(?i)select .+ from .+")
then readerError $ "Please provide a valid SQL SELECT statement"
else return val
-- [EOF]
我想用 hspec 测试上面的 "parseDb" 函数。我想确保在指定未知数据库时抛出 "readerError"。因此我想测试函数调用
解析数据库 "unknown"
生成一个 "readerError" 调用,根据我的说法应该抛出异常。
我试过 hspec shouldThrow 函数,但它不起作用。似乎没有抛出异常。 reader错误的 return 类型是 "ReadM a"。在花了几天时间阅读 monads 和 reader monads 之后,我仍然卡住了(并且很困惑)并且不知道如何测试它以及是否有可能测试它。我用谷歌搜索时找不到任何相关示例。
以下是一些相关的类型信号:
parseDb :: String -> ReadM String
-- from Options.Applicative.Internal
runReadM :: MonadP m => ReadM a -> String -> m a
runP :: P a -> ParserPrefs -> (Either ParseError a, Context)
runReadM
和 runP
的文档:(link)
ParserPrefs
只是一个简单的数据结构。
这个类型检查:
import Options.Applicative.Types
import Options.Applicative.Internal
parseDb :: String -> ReadM String
parseDb val = do
if not (elem val ["dmt", "report"])
then readerError $ "Unknown DB, '" ++ val ++ "'"
else return val
foo :: (Either ParseError String, Context) -- might be [Context] now
foo = runP (runReadM (parseDb "foo") "asd") opts
where opts = ParserPrefs "suffix" False False False 80
正在评估 fst foo
returns:
*Main> fst foo
Left (ErrorMsg "Unknown DB, 'foo'")
更新
这里是如何测试 Parser
像 globalOptsParser:
import Options.Applicative.Common (runParser)
import Options.Applicative.Internal (runP)
bar = let mp = runParser AllowOpts globalOptsParser ["asd"]
opts = ParserPrefs "suffix" False False False 80
in fst $ runP mp opts
这里 ["asd"]
是要测试的命令行参数。
检查 ParserPrefs
是否是您想要的 - 它们会影响选项处理。
我是 Haskell 的新手。
我已经编写了以下代码段来解析发送到脚本的参数;
module Billing.Options
(
GlobalOpts(..)
, globalOptsParser
, parseDb
) where
import Options.Applicative
import Options.Applicative.Simple
import Options.Applicative.Types
import System.FilePath.Posix
import Text.Regex.PCRE
-- ------------------------------------------------------------
data GlobalOpts = GlobalOpts
{
optDb :: String,
optSql :: String
} deriving Show
-- ------------------------------------------------------------
globalOptsParser :: Parser GlobalOpts
globalOptsParser = GlobalOpts
<$> option (parseDb =<< readerAsk)
( long "db"
<> short 'd'
<> metavar "<DB name>"
<> help "dmt | report"
)
<*> option parseSql
( long "sql"
<> metavar "<SQL SELECT statement>"
<> help "sql select statement to use in order to generate JSON config file"
)
-- ------------------------------------------------------------
matches :: String -> String -> Bool
matches = (=~)
-- ------------------------------------------------------------
parseDb :: String -> ReadM String
parseDb val = do
if not (elem val ["dmt", "report"])
then readerError $ "Unknown DB, '" ++ val ++ "'"
else return val
-- ------------------------------------------------------------
parseSql :: ReadM String
parseSql = do
val <- readerAsk
if not (val `matches` "(?i)select .+ from .+")
then readerError $ "Please provide a valid SQL SELECT statement"
else return val
-- [EOF]
我想用 hspec 测试上面的 "parseDb" 函数。我想确保在指定未知数据库时抛出 "readerError"。因此我想测试函数调用 解析数据库 "unknown" 生成一个 "readerError" 调用,根据我的说法应该抛出异常。
我试过 hspec shouldThrow 函数,但它不起作用。似乎没有抛出异常。 reader错误的 return 类型是 "ReadM a"。在花了几天时间阅读 monads 和 reader monads 之后,我仍然卡住了(并且很困惑)并且不知道如何测试它以及是否有可能测试它。我用谷歌搜索时找不到任何相关示例。
以下是一些相关的类型信号:
parseDb :: String -> ReadM String
-- from Options.Applicative.Internal
runReadM :: MonadP m => ReadM a -> String -> m a
runP :: P a -> ParserPrefs -> (Either ParseError a, Context)
runReadM
和 runP
的文档:(link)
ParserPrefs
只是一个简单的数据结构。
这个类型检查:
import Options.Applicative.Types
import Options.Applicative.Internal
parseDb :: String -> ReadM String
parseDb val = do
if not (elem val ["dmt", "report"])
then readerError $ "Unknown DB, '" ++ val ++ "'"
else return val
foo :: (Either ParseError String, Context) -- might be [Context] now
foo = runP (runReadM (parseDb "foo") "asd") opts
where opts = ParserPrefs "suffix" False False False 80
正在评估 fst foo
returns:
*Main> fst foo
Left (ErrorMsg "Unknown DB, 'foo'")
更新
这里是如何测试 Parser
像 globalOptsParser:
import Options.Applicative.Common (runParser)
import Options.Applicative.Internal (runP)
bar = let mp = runParser AllowOpts globalOptsParser ["asd"]
opts = ParserPrefs "suffix" False False False 80
in fst $ runP mp opts
这里 ["asd"]
是要测试的命令行参数。
检查 ParserPrefs
是否是您想要的 - 它们会影响选项处理。