使用 QuickCheck monadicIO 时如何防止测试功能输出到终端

How to prevent tested functions from outputting to terminal when using QuickCheck monadicIO

我想知道在使用 QuickCheck 和 monadicIO 通过 GHCI 测试函数时是否有某种方法可以防止函数打印到终端。

例如,假设我有以下代码:

import Test.Hspec
import Test.Hspec.QuickCheck
import Test.QuickCheck
import Test.QuickCheck.Monadic (assert, monadicIO, pick, run)

main :: IO ()
main = hspec $ do
  describe "Something to test" $ do
    it "What I'm testing" $ do
      prop_exampleTest

prop_exampleTest :: Property
prop_exampleTest = monadicIO $ do
  num    <- pick arbitrary
  newNum <- run $ exampleFunc num
  assert $ num == newNum

我只想测试 exampleFunc 的 return 值。但是,如果它使用 putStrLn,那么它会在每次检查时打印到终端。

exampleFunc :: Int -> IO Int
exampleFunc n = do
  putStrLn "One trick is to tell 'em stories that don't go anywhere - like the time I caught the ferry over to Shelbyville. I needed a new heel for my shoe, so, I decided to go to Morganville, which is what they called Shelbyville in those days. So I tied an onion to my belt, which was the style at the time. Now, to take the ferry cost a nickel, and in those days, nickels had pictures of bumblebees on 'em. Give me five bees for a quarter, you'd say..."
  return n

有什么办法可以避免这种情况吗?

正如 bradrn 评论的那样,这可以使用 silently 包来完成。只需将您的函数作为参数应用于其 silence 函数:

import Test.Hspec
import Test.Hspec.QuickCheck
import Test.QuickCheck
import Test.QuickCheck.Monadic (assert, monadicIO, pick, run)
-- Add the import statement for the silently 'silence' function.
import System.IO.Silently (silence)

main :: IO ()
main = hspec $ do
  describe "Something to test" $ do
    it "What I'm testing" $ do
      prop_exampleTest

prop_exampleTest :: Property
prop_exampleTest = monadicIO $ do
  num    <- pick arbitrary
  -- instead of running my function directly, apply it as an argument to silence
  newNum <- run $ silence (exampleFunc num)
  assert $ num == newNum


exampleFunc :: Int -> IO Int
exampleFunc n = do
  putStrLn "One trick is to tell 'em stories that don't go anywhere - like the time I caught the ferry over to Shelbyville. I needed a new heel for my shoe, so, I decided to go to Morganville, which is what they called Shelbyville in those days. So I tied an onion to my belt, which was the style at the time. Now, to take the ferry cost a nickel, and in those days, nickels had pictures of bumblebees on 'em. Give me five bees for a quarter, you'd say..."
  return n