Unit testing 单元测试Haskell中lazy表达式中未定义的求值
在Haskell中编写一个单元测试,当遇到Unit testing 单元测试Haskell中lazy表达式中未定义的求值,unit-testing,haskell,hspec,Unit Testing,Haskell,Hspec,在Haskell中编写一个单元测试,当遇到undefined时,表达式应该失败,这有点棘手。我用HSpec尝试了以下方法: module Main where import Test.Hspec import Control.Exception (evaluate) main :: IO () main = hspec $ do describe "Test" $ do it "test case" $ do evaluate (take 1 $ map (+1) [
undefined
时,表达式应该失败,这有点棘手。我用HSpec尝试了以下方法:
module Main where
import Test.Hspec
import Control.Exception (evaluate)
main :: IO ()
main = hspec $ do
describe "Test" $ do
it "test case" $ do
evaluate (take 1 $ map (+1) [undefined, 2, 3]) `shouldThrow` anyException
无济于事。它报告我没有得到预期的异常:SomeException
如果我在REPL中计算相同的表达式,我会得到:
[*** Exception: Prelude.undefined
CallStack (from HasCallStack):
error, called at libraries\base\GHC\Err.hs:79:14 in base:GHC.Err
undefined, called at <interactive>:2:20 in interactive:Ghci1
[***例外:Prelude.undefined
调用堆栈(来自HasCallStack):
错误,在base:GHC.Err中的libraries\base\GHC\Err.hs:79:14处调用
未定义,在interactive:Ghci1中于:2:20调用
问题是求值
不会强制你的表达式为NH甚至WHNF1。试试x这个答案很好,但当你说求值
在什么时候不求值为WHNF时,我感到困惑。@AlexisKing我站得对了!无论如何,WNHF是不够的,因此你需要NFData
。所以,实际上测试通过是因为它生成了一个包含单个未定义元素的列表?为什么不应用(+1)函数?因为不需要检查列表的第一个元素,Haskell不必费心去计算(+1)未定义的。thunk就在那里,但Haskell不需要为计算。
ghci> x <- evaluate (take 1 $ map (+1) [undefined, 2, 3])
ghci> :sprint x
x = [_]
import Test.Hspec
import Control.Exception (evaluate)
import Control.DeepSeq (force)
main :: IO ()
main = hspec $ do
describe "Test" $ do
it "test case" $ do
evaluate (force (take 1 $ map (+1) [undefined, 2, 3] :: [Int]))
`shouldThrow` anyException