Есть ли assertException в любой из тестовых фреймворков Haskell?

Я пишу несколько тестов с использованием HUnit, и я хотел бы утверждать, что определенная функция генерирует исключение, учитывая определенный вход. Я не могу найти функцию assert, которая обеспечивает требуемую функциональность. Кто-нибудь знает тестовую структуру, которая делает?

Ответы

Ответ 1

Хотя HUnit не приходит с любыми утверждениями об исключении, легко написать свой собственный:

import Control.Exception
import Control.Monad
import Test.HUnit

assertException :: (Exception e, Eq e) => e -> IO a -> IO ()
assertException ex action =
    handleJust isWanted (const $ return ()) $ do
        action
        assertFailure $ "Expected exception: " ++ show ex
  where isWanted = guard . (== ex)

testPasses = TestCase $ assertException DivideByZero (evaluate $ 5 `div` 0)
testFails  = TestCase $ assertException DivideByZero (evaluate $ 5 `div` 1)

main = runTestTT $ TestList [ testPasses, testFails ]

Вы можете сделать что-то более необычное, например, использовать предикат вместо явного сравнения, если хотите.

$ ./testex
### Failure in: 1                         
Expected exception: divide by zero
Cases: 2  Tried: 2  Errors: 0  Failures: 1

Обратите внимание, что evaluate здесь может быть оптимизирован (см. билет GHC # 5129), но для тестирования кода в монаде IO это должно работать нормально.

Ответ 3

hspec (или, точнее, hspec-ожидания) имеет shouldThrow.