8

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はあまり助けにはなりません。

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

4

1 に答える 1

13

パーサーのテストは完全に簡単ではありません。(すべてのテストと同様に、物事の複雑さに依存します。)

実行できることの1つは、Arbitraryすべての有効な式(または解析しようとしているもの)を構築するインスタンスを作成し、それをきれいに印刷してから結果の文字列を解析すると、正確に何が返されるかを確認することです。あなたはから始めました。

これにはいくつかの問題があります。

  • 答えが間違っている場合、何が壊れていますか?パーサーまたはプリンター?

  • 解析しているものがオプションのブラケットやものを持つほど複雑な場合は、オプションのブラケットがある場合とない場合の両方で機能することを確認する必要があります。あなたのかわいいプリンターは、通常、どちらかの方法でしかそれを行いません。

  • これは、ガベージ入力が実際に拒否される(そして何か奇妙なものとして解析されない)ことをチェックしません。たとえば、入力の最後で構文エラーが発生した場合に構文エラーを黙って無視するParsecパーサーをたくさん作成しました。

一般に、パーサーのテストについて私が知っている唯一の本当に徹底的な方法は、手作業でたくさんの手動テストを書くことです。(そして、間違って解析するものを見つけるたびに、そのための別のテストケースを追加します。)これは、たとえば、GHCがテストスーツで行うことです。

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

于 2012-10-19T20:39:57.900 に答える