OCaml:如何测试我自己的正则表达式库

时间:2016-01-27 16:15:07

标签: regex unit-testing testing ocaml

我创建了一个简单的正则表达式引擎,它支持连接,交替,闭包和char a .. z

我代表nfa和dfa的方式是使用记录:

type state       = int with sexp, compare
type alphabet    = char with sexp, compare
type transaction = state * alphabet option * state with sexp, compare
type d_transaction = state * alphabet * state with sexp, compare

type state_set = State_set.t
type states_set = States_set.t

type nfa = {
  states       : State_set.t ;
  alphabets    : Alphabet_set.t ;
  transactions : Transaction_set.t; 
  start_state  : state;
  final_states : State_set.t;
}


type dfa = {
  d_states       : State_set.t ;
  d_alphabets    : Alphabet_set.t;
  d_transactions : D_Transaction_set.t ;
  d_start_state  : state ;
  d_final_states : State_set.t;
}

例如,字符串“a *”将被解析为Closure (Char 'a'),然后进行转换 到 nfa states: 0 1 2 3 alphabets: a transactions: 0->e->1, 1->a>2, 2->e->3, 2->e->1, 0->e->3 start_state: 0 final_states: 3

然后 dfa

states: 0 1 alphabets: a transactions: 0->a->1, 1->a->1 start_state: 0 final_states: 0 1

但是,我在代码中使用了很多递归。我的程序为nfa和dfa中的每个节点生成状态编号的方式实际上是不可预测的。我不知道如何在不使用笔和纸张自己进行测试的情况下验证生成的dfa是否正确

我正在尝试找出一种更好的方法来测试我的代码,以便将来可以在我的程序中添加更多功能。

有人可以给我一些建议吗?

3 个答案:

答案 0 :(得分:2)

如果没有正式验证,您可以:

  1. 使用单元测试库(例如OUnitalcotest)根据大量示例测试您的引擎。这是nice blog post比较其他一些测试库。
  2. 将其与Bisect_ppx等覆盖工具相结合,有两个目的:它直接帮助确保您的示例测试生成器中的各种分支,并间接导致您更仔细地查看生成器并考虑如何编写示例来测试各种代码路径。以下是another blog post简要比较覆盖率工具。
  3. 编辑:我想如果你想直接测试你的DFA,你可能想要写一些小的专业"覆盖工具"对于您的特定类型,它会告诉您在测试每个DFA期间已达到的状态和/或状态/转换对的比例,以及哪些。这将是您当前用于沿输入字符串遍历DFA的函数的一些修改形式。

    免责声明:我目前正致力于改进Bisect_ppx(这是"现代" Bisect的分支)。但是,我没有附属或参与此处提到的任何其他内容。

答案 1 :(得分:2)

一个相当精细的计划是将DFA转换回正则表达式,然后测试结果是否与原始正则表达式相同。这是一个SO页面,提供了一些测试RE等价的方法:Regex: Determine if two regular expressions could match for the same input?

希望两个逆转换有助于相互调试: - )

答案 2 :(得分:2)

正则表达式库的一个property-based test是写

  1. 生成随机正则表达式的正则表达式生成器
  2. 一个字符串生成器,在给定正则表达式的情况下,会生成该语言中的随机字符串。
  3. 一个属性,给定正则表达式,你的正则表达式匹配器匹配字符串生成器的输出。
  4. 对于OCaml中基于属性的测试,您可以使用QCheck