我想为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
,但对此没什么帮助。
如果您为这个简单的解析器提供一个评论良好的生成器示例,我将不胜感激。
答案 0 :(得分:12)
测试解析器并非完全无关紧要。 (与所有测试一样,取决于事物的复杂性。)
你可以做的一件事是编写一个Arbitrary
实例来构造所有有效的表达式(或者你正在尝试解析的任何东西),然后检查一下你是否打印出来然后解析结果字符串,你会准确地回到你的开始。
有几个问题:
如果答案错了,那什么坏了?解析器或打印机?
如果你正在解析的东西很复杂,有可选的括号和东西,你需要检查它是否可以使用和不使用可选括号。你漂亮的打印机通常只会这样或那样。
这不会检查垃圾输入是否真的被拒绝(并且没有被解析为奇怪的东西)。例如,我写了很多Parsec解析器,如果它出现在输入的 end ,它将默默地忽略语法错误。
一般来说,我所知道的测试解析器的唯一真正彻底的方法是手工编写大量的手动测试。 (每当你发现解析错误的内容时,请为它添加另一个测试用例。)例如,这基本上就是GHC对他们的测试套装所做的事情。
当然,这取决于你的解析器有多复杂,以及你想要多少保证......如果你只是解析JSON,你可以相当容易地测试它。如果你正在解决像Markdown这样的事情......我的上帝怜悯你的灵魂!