2012-10-19 24 views
7

私はParsecパーサーのテストを書いてみたいです。Haskell - QuickCheckの助けを借りたParsecテスト

data Event = Event { keyEvent :: String } 
    deriving Show 

parseKey :: Parser Event 
parseKey = do 
      char '<' 
      k <- many1 (letter <|> digit <|> oneOf "_") 
      char '>' 
      return $ Event k 

私はparse = parse . pretty . parseプロパティをチェックする必要があることを知っている:ここでは、パーサーとデータ構造の一例です。しかし、どのように正しくないテストケースを生成する必要がありますか?一般に、与えられたBNFのテストケースをどのように生成すればよいですか?私はinstance Arbitraryについて知っていますが、それほど助けにはなりません。

この単純なパーサーのジェネレータの例をよくコメントしていただければ幸いです。

+2

正しいテストケースでは、 'id = parse。かなり美味しい? (また、 'oneOf" _ "== char '_'') – huon

+0

私はそれが十分だろうと思う、ええ! (また、最初のバージョンははるかに奇妙でした)。 – m0nhawk

+2

@dbaupp:私はこれについて考えましたが、パーザに 'スペース 'やその他のスキップ可能な文字がある場合の単純な例を考えてみると、結果は異なるでしょう。さらに 'parse'が助けになります。 – m0nhawk

答えて

12

パーサーのテストは、あまり一般的ではありません。

あなたができることは、すべての有効な式(または解析しようとしているもの)を構築するArbitraryインスタンスを作成し、それをチェックすることですあなたがその物を美しく印刷して結果の文字列を解析すると、あなたが始めたものを正確に返すことができます。答えは壊れているもの、間違っている場合

  • はそれで問題がいくつかありますか?パーサまたはプリンタ?

  • 解析しているものがオプションの角かっこを持つほど複雑な場合は、オプションの角かっこを使用する場合と使用しない場合の両方で機能することを確認する必要があります。あなたのかわいいプリンターは、通常は一方通行か他方通行しか行いません。

  • これは、ガベージ入力が本当に拒否されるかどうかをチェックしません(奇妙なものとして解析されません)。たとえば、入力の末尾にある場合、構文エラーを黙って無視するParsecパーサーをたくさん作成しました。一般的に

、パーサをテストするための、私が知っているだけで、本当に徹底の方法は、単に手で手動テストのとてもたくさんを書くことです。 (そして、間違っているものが見つかるたびに、別のテストケースを追加してください。)これは、基本的に、GHCがテストスーツで行うことです。

もちろん、パーサの複雑さと保証の程度によって異なります... JSONを解析するだけの場合は、かなり簡単にテストできます。あなたがMarkdownのようなものを解析しているなら...私の神はあなたの魂に慈悲を持っています!

+0

興味があれば、[XCompose](http://www.unix.com/man-page/all/5/XCompose/)のパーサを書いています(https://github.com/m0nhawk/) XComposeChecker)がソースです。だから、このためにクイックチェックを作成するのは理にかなっていますか?または手書きのテストは良いでしょうか?そして2番目のケースではどのようなライブラリを提案できますか? – m0nhawk

+0

あなたはもちろんこれらの事の両方を行うことができます。 QuickCheckを使用して、ASTからASTへのラウンドトリップが動作していることを確認し、エッジケースをチェックするための手動テストを作成します。それは非常に小さい文法のように見えるので、テストするのは難しくありません。 – MathematicalOrchid

関連する問題