2017-09-23 220 views
1

嗨測試Haskell函數我有一個類似於下面的Haskell功能返回錯誤

test :: Int -> Bool 
test 1 = error "shouldnt have been 1" 
test 2 = error "shouldnt have been 2" 
test 11 = error "shouldnt have been 11" 
test 77 = error "shouldnt have been 77" 
test _ = True 

我有一個測試計劃,以測試無效輸入,以確保它們返回正確的錯誤

tc1 = test 1 
tc2 = test 2 
tc3 = test 11 
tc4 = test 77 

allTests = [tc1, tc2, tc3, tc4] 

但問題是,當我在ghci中運行allTests時,我只得到第一個錯誤。我想有所有的錯誤

如何才能做到這一點還是有些方法可以讓我趕上了錯誤的列表?

回答

4

你可以嘗試使用catchControl.Exception,但是這仍然是一個尷尬的方式來實現目標。

這將會是最好使用純數據類型來捕獲錯誤,因爲他們更容易編寫和收集。通常情況下,你會使用Either爲,但在這種特殊情況下,成功的情況下,將不攜帶信息,因此類會Either String(),這是同構的Maybe String。重寫test返回Maybe String很簡單:

test :: Int -> Maybe String 
test 1 = Just "shouldnt have been 1" 
test 2 = Just "shouldnt have been 2" 
test 11 = Just "shouldnt have been 11" 
test 77 = Just "shouldnt have been 77" 
test _ = Nothing 

tc1 = test 1 
tc2 = test 2 
tc3 = test 11 
tc4 = test 77 
tc5 = test 5 

我爲了證明當測試成功,會發生什麼情況增加了tc5值。

您可以評估所有這些測試用例,但是如果你只想要失敗的情況下,你可以使用catMaybesData.Maybe

allTests = catMaybes [tc1, tc2, tc3, tc4, tc5] 

下面是運行allTests結果:

*Q46376632> allTests 
["shouldnt have been 1", 
"shouldnt have been 2", 
"shouldnt have been 11", 
"shouldnt have been 77"] 

如果你不能改變你正在測試的功能,你可以嘗試像下面這樣,但它幾乎沒有優雅:

tc1 = catch (print $ test 1) (\err -> print (err :: SomeException)) 
tc2 = catch (print $ test 2) (\err -> print (err :: SomeException)) 
tc3 = catch (print $ test 11) (\err -> print (err :: SomeException)) 
tc4 = catch (print $ test 77) (\err -> print (err :: SomeException)) 
tc5 = catch (print $ test 5) (\err -> print (err :: SomeException)) 

allTests = sequence_ [tc1, tc2, tc3, tc4, tc5] 

當運行它,你得到的輸出是這樣的:

*Q46376632> allTests 
shouldnt have been 1 
CallStack (from HasCallStack): 
    error, called at 46376632.hs:14:10 in main:Q46376632 
shouldnt have been 2 
CallStack (from HasCallStack): 
    error, called at 46376632.hs:15:10 in main:Q46376632 
shouldnt have been 11 
CallStack (from HasCallStack): 
    error, called at 46376632.hs:16:11 in main:Q46376632 
shouldnt have been 77 
CallStack (from HasCallStack): 
    error, called at 46376632.hs:17:11 in main:Q46376632 
True 

在這一點上,你可能會使用適當的測試框架的更好。

+0

嗨,謝謝。我喜歡用'TC1 =捕捉(打印$測試1)(\ ERR - >打印(ERR :: SomeException))的代碼塊''...' – Jhoy

+0

我有一個問題,如果我有即'列表ALLTESTS = [tc1,tc2,tc3,tc4]'我可以在這個列表上使用類似的東西來減少重複代碼嗎? – Jhoy

+0

@Jhoy首先,明白'catch'代碼並不優雅,甚至不合適,Haskell代碼。也就是說,你可以在'[a]'上使用'map'(或'fmap')。 –