簡體   English   中英

如何使用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”。 因此,我想測試該函數調用parseDb“ unknown”生成一個“ readerError”調用,根據我的說法,該調用應引發異常。

我已經嘗試了hspec shouldThrow函數,但是它不起作用。 似乎沒有異常被拋出。 readerError的返回類型為“ ReadM a”。 在花了幾天時間閱讀了monad和讀者monad之后,我仍然很困惑(並且很困惑),不知道如何進行測試以及是否有可能進行測試。 谷歌搜索時找不到任何相關示例。

以下是一些相關的類型信號:

parseDb :: String -> ReadM String

-- from Options.Applicative.Internal

runReadM :: MonadP m => ReadM a -> String -> m a
runP :: P a -> ParserPrefs -> (Either ParseError a, Context)

runReadMrunP文檔:( 鏈接)

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返回:

*Main> fst foo
Left (ErrorMsg "Unknown DB, 'foo'")

更新

這是測試像globalOptsParser這樣的Parser 方法

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是否是您想要的-它們會影響選項處理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM