2013-09-01 8 views

答えて

4

私はQuickCheckの専門家ではありません。質問前にモナディックチェックの経験はありませんでしたが、新しいことを学ぶ機会としてstackoverflowが表示されています。これがうまくいっているというエキスパートの回答がある場合は、私を削除します。

testは、exitWithを使用して例外をスローする可能性があるとします。ここで私はあなたがそれをテストできると思います。キー機能はprotectで、例外をキャッチしてテストすることができます。

import System.Exit 
import Test.QuickCheck 
import Test.QuickCheck.Property 
import Test.QuickCheck.Monadic 

test :: Int -> IO Int 
test n | n > 100 = do exitWith $ ExitFailure 1 
     | otherwise = do print n 
         return n 

purifyException :: (a -> IO b) -> a -> IO (Maybe b) 
purifyException f x = protect (const Nothing) $ return . Just =<< f x 

testProp :: Property 
testProp = monadicIO $ do 
    input <- pick arbitrary 
    result <- run $ purifyException test $ input 
    assert $ if input <= 100 then result == Just input 
          else result == Nothing 

これには2つの欠点がありますが、私には分かりますが、それ以上の方法はありません。

  1. 私はprotectが扱うことができるAnExceptionからExitCode例外を抽出する方法を発見しました。したがって、すべての終了コードはここで同じ扱いになります(これらはNothingにマップされています)。私は持っていただろう:

    purifyException :: (a -> IO b) -> a -> IO (Either a ExitCode) 
    
  2. 私はテストのI/O動作をテストする方法が見つかりませんでした。

    test :: IO() 
    test = do 
        n <- readLn 
        if n > 100 then exitWith $ ExitFailure 1 
          else print n 
    

    次に、どのようにあなたはそれをテストします:testだったと仮定?

私はさらに専門家の回答に感謝します。

2

QuickCheck expectFailure機能を使用して、このタイプのものを処理できます。今、私たちは、エラー処理のいくつかのプロパティをテストすることができ

positive :: Int -> Either String Int 
positive x | x > 0  = Right x 
      | otherwise = Left "not positive" 

negative :: Int -> Either String Int 
negative x | x < 0  = Right x 
      | otherwise = Left "not negative" 

import System.Exit 
import Test.QuickCheck 
import Test.QuickCheck.Monadic 

handle :: Either a b -> IO b 
handle (Left _) = putStrLn "exception!" >> exitWith (ExitFailure 1) 
handle (Right x) = return x 

とダミー機能のカップルをかき立てる:この単純な(と-推奨されません)エラー処理フレームワークを取ります。まず、Right値は、例外が発生してはならない。

prop_returnsHandledProperly (Positive x) = monadicIO $ do 
    noErr <- run $ handle (positive x) 
    assert $ noErr == x 

-- Main*> quickCheck prop_returnsHandledProperly 
-- +++ OK, passed 100 tests. 

Lefts例外が発生しなければなりません。 expectFailureが最初に付いていることに注意してください。

prop_handlesExitProperly (Positive x) = expectFailure . monadicIO $ 
    run $ handle (negative x) 

-- Main*> quickCheck prop_handlesExitProperly 
-- +++ OK, failed as expected. Exception: 'exitWith: invalid argument (ExitFailure 0)' (after 1 test): 
+0

しかし、これはすべての種類の障害が予想されるようです。 'exitWith'呼び出しで生成されたものを分離できますか?私たちは失敗のコードが何であるかを主張することができますか? – nickie

+0

@nickie終了コードに関するプロパティをテストする場合は、エラー処理自体に配管を追加することができます。私。 exitWithが呼び出す 'determineCode :: Aither a b - > ExitCode'関数を持ち、その動作についてアサーションを行います。さらに進むことができるかどうかは分かりません。 – jtobin

+0

'expectFailure'は、すべてのテストが失敗した場合とは対照的に、テストが失敗した場合のように見えます。 – Dan

関連する問題