Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unit testing 模拟IO操作:getArgs和putStrLn_Unit Testing_Haskell_Mocking_Monads_Hunit - Fatal编程技术网

Unit testing 模拟IO操作:getArgs和putStrLn

Unit testing 模拟IO操作:getArgs和putStrLn,unit-testing,haskell,mocking,monads,hunit,Unit Testing,Haskell,Mocking,Monads,Hunit,我试图测试一个小函数(或者更确切地说,IO操作),它接受一个命令行参数并将其输出到屏幕。我最初的(不稳定的)功能是: -- In Library.hs module Library where import System.Environment (getArgs) run :: IO () run = do args <- getArgs putStrLn $ head args 这个库。,前奏曲。和系统环境。是为了避免编译器抱怨出现含糊不清的情况。我的测试文件如下所示 --

我试图测试一个小函数(或者更确切地说,IO操作),它接受一个命令行参数并将其输出到屏幕。我最初的(不稳定的)功能是:

-- In Library.hs
module Library where

import System.Environment (getArgs)

run :: IO ()
run = do
  args <- getArgs
  putStrLn $ head args
这个
库。
前奏曲。
系统环境。
是为了避免编译器抱怨
出现含糊不清的情况。我的测试文件如下所示

-- In LibrarySpec.hs
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}

import Library
import Test.Hspec
import Control.Monad.State

data MockArgsAndResult = MockArgsAndResult [String] String
  deriving(Eq, Show)

instance SystemMonad (State MockArgsAndResult) where 
    getArgs = do 
      MockArgsAndResult args _ <- get
      return args
    putStrLn string = do
      MockArgsAndResult args _ <- get
      put $ MockArgsAndResult args string
      return ()

main :: IO ()
main = hspec $ do
  describe "run" $ do
    it "passes the first command line argument to putStrLn" $ do
      (execState run (MockArgsAndResult ["first", "second"] "")) `shouldBe` (MockArgsAndResult ["first", "second"] "first")
--在LibrarySpec.hs中
{-#语言类型同义词实例}
{-#语言灵活实例}
导入库
进口测试
进口控制单体状态
数据MockArgsAndResult=MockArgsAndResult[String]字符串
推导(等式,显示)
实例SystemMonad(State MockArgsAndResult),其中
getArgs=do

mockargs和result args\up>更好的方法是通过将计算的核心分离为纯函数,避免提供
getArgs
putStrLn
的模拟版本

考虑这个例子:

main = do
  args <- getArgs
  let n = length $ filter (\w -> length w < 5) args
  putStrLn $ "Number of small words: " ++ show n

现在我们只需测试countSmallWords,这很简单,因为它是纯函数。

我认为您的代码很好/干净/惯用。真正的问题是这能解决你的问题吗?您的“模型”是否足以准确表示您正在建模的实际“文件系统”?如果是这样的话,也许就没有必要过度考虑这一点。但是,
putStrLn
可能应该将其字符串参数附加到状态中的旧字符串,而不是忽略旧字符串,如果您真的想模拟
Prelude。putStrLn
@user2407038附加到旧字符串听起来是个好主意。是的,分离成纯函数似乎不错,但是总会有一些IO操作(/返回IO操作的函数)需要测试,至少它们通过了纯函数的测试结果。请举个例子,我们可以探索如何组织它以使测试更容易。呃。。。我最初问题中的那个,和你答案中的那个,似乎都是很好的例子!也许我不理解你的要求?拿出一个更复杂的现实例子。
main = do
  args <- getArgs
  let n = length $ filter (\w -> length w < 5) args
  putStrLn $ "Number of small words: " ++ show n
main = do
  args <- getArgs
  let n = countSmallWords args
  putStrLn $ "Number of small words: " ++ show n

countSmallWords :: [String] -> Int
countSmallWords ws = ...