2012-10-19 27 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:我想過這個,不,考慮一下簡單的例子,當分析器中有'spaces'或其他可跳過的字符時,那麼產生的結果會不同。另外'parse'會有幫助。 – m0nhawk

回答

12

測試解析器並非完全無關緊要。 (取決於事物的複雜性,與所有測試一樣)。

你可以做的一件事是編寫一個Arbitrary實例,它構造所有有效的表達式(或者任何你想要解析的表達式),然後檢查如果你漂亮地打印這個東西然後解析結果字符串,你會回到你剛開始的時候。

有幾個問題與:

  • 如果答案是錯的,什麼是壞?解析器還是打印機?

  • 如果你正在解析的東西足夠複雜以至於沒有可選的方括號和東西,那麼你需要檢查它是否有可選的括號。通常,你漂亮的打印機只會以這種方式或其他方式進行打印。

  • 這並沒有檢查垃圾輸入是否真的被拒絕(並且沒有被解析爲奇怪的東西)。例如,我寫了大量的Parsec解析器,如果它發生在輸入的末端處,它將默默地忽略語法錯誤。

在一般情況下,我知道測試解析器的唯一真正徹底的辦法是隻寫很多很多的手工手工測試。 (並且每次你找到解析錯誤的東西時,都要添加另一個測試用例。)這基本上就是GHC用他們的測試套裝做的事情。

當然,這取決於您的解析器的複雜程度以及您想要的保證程度。如果您只是解析JSON,則可以相當容易地對其進行測試。如果你正在解析類似Markdown的東西......我的上帝憐憫你的靈魂!

+0

我正在寫[XCompose]的解析器(http://www.unix.com/man-page/all/5/XCompose/),如果有興趣[這裏](https://github.com/m0nhawk/ XComposeChecker)是來源。那麼,爲此創建QuickCheck是否有意義?或者手寫測試會更好?第二種情況下可以提出什麼樣的圖書館? – m0nhawk

+0

你當然可以做這些事情。使用QuickCheck驗證從AST到字符串到AST的往返行程是否有效,並編寫一些手動測試來檢查邊緣情況。它看起來像一個相當小的語法,所以它不應該太難測試... – MathematicalOrchid