如何综合编译器测试数据?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何综合编译器测试数据?相关的知识,希望对你有一定的参考价值。
我正在写一个简单的编译器作为学校工作。我正在寻找一种自动化的方法来生成正面和负面的测试数据,以测试我的编译器,给出正式的语法和其他规范。我正在处理的语言是中等大小,有38个左右的非终端。为了便于说明,这里是语法的快照:
program: const_decl* declaration* ENDMARKER
# statement
stmt: flow_stmt | '{' stmt* '}' | NAME [stmt_trailer] ';' | ';'
stmt_trailer: arglist | ['[' expr ']'] '=' expr
flow_stmt: if_stmt | for_stmt | while_stmt | read_stmt ';' | write_stmt ';' | return_stmt ';'
return_stmt: 'return' ['(' expr ')']
if_stmt: 'if' '(' condition ')' stmt ['else' stmt]
condition: expr ('<'|'<='|'>'|'>='|'!='|'==') expr | expr
for_stmt: ('for' '(' NAME '=' expr ';' condition ';'
NAME '=' NAME ('+'|'-') NUMBER ')' stmt)
是否有任何工具可以在语法的帮助下生成输入文件?手写测试过于乏味或太弱而无法发现问题。这里有一种语言的例子:
void main() {
int N;
int temp;
int i, j;
int array_size;
reset_heap;
scanf(N);
for (i = 0; i < N; i = i + 1) {
scanf(array_size);
if (array_size > max_heap_size) {
printf("array_size exceeds max_heap_size");
} else {
for (j = 0; j < array_size; j = j + 1) {
scanf(temp);
heap[j] = temp;
}
heap_sort(array_size);
print_heap(array_size);
}
}
}
自动生成可控测试数据可以节省时间。鉴于语言的简单性,必须有一些方法来有效地做到这一点。非常感谢任何指针和洞察力。
非常感谢任何指针和洞察力。
这应该有How to avoid combinatorial explosion when generating test data
的副标题。
虽然有些工具可以为语法生成测试数据,但我不会感到惊讶,我已经创建了几个应用程序。
我在此发现的最好的系列文章之一是Eric Lippert,Every Binary Tree There Is,认为BNF转换为二元运算符,然后在读取树时转换为AST。然而他使用Catalan(每个分支有两个叶子),当我写我的应用程序时,我更喜欢Motzikin(一个分支可以有一个或两个叶子)。
他也用LINQ在C#中做了他,我用prazxswpoi在Prolog做了我的。
基于BNF或DCG生成数据并不难,真正的诀窍是限制扩展区域和扩展的大小并注入不良数据。
通过扩展区域可以说你想测试三层深层的嵌套if语句,但必须有编译的有效代码。显然,您需要样板代码才能使其编译,然后通过添加或删除else子句开始更改深层嵌套。因此,您需要设置约束,以使样板代码保持不变,并且测试部分是可变的。
通过扩展的大小,可以说你想测试条件表达式。您可以轻松地计算出,如果您有许多操作员,并且您希望将它们全部组合测试,那么很快就会遇到组合爆炸。诀窍是确保你测试足够深,并且有足够的宽度但不是每个组合。司法使用约束有助于此。
所以这一切的重点在于你从一个接收BNF并生成有效代码的工具开始。然后修改BNF以添加约束并修改生成器以了解生成代码示例的约束。
然后修改BNF以获取无效数据,同样修改生成器以了解这些规则。
在此之后,您可以开始在自动化级别上进行分层。
如果你确实走这条路并决定你必须学习Prolog,请先看看DCG。我没有和水星一起做过这件事,但如果我再次这样做,水星就是名单上的佼佼者。
虽然我的实际代码不公开,但Mercury和this是最接近它的公共代码。
一路走来,我在this玩得很开心。
当生成诸如保留字或类型值的终端时,您可以使用包含有效和无效数据的预定义列表,例如,对于Code Golf,如果语言区分大小写,我会在列表中包括if
,if
,If
,IF
等。对于值类型,如无符号字节,我将包括iF
,-1
,0
和255
。
当我用256
,+
,-
和*
测试基本二进制数学表达式时,我用三个基本数字^
,-2
,-1
,0
和1
生成了所有测试。我认为它没用,因为我已经有数百个测试用例,但由于生成所有测试用例只花了几分钟而运行它几个小时,令我惊讶的是它发现了一个我没有覆盖的模式。这里的观点与大多数人对许多测试用例的说法相反,请记住,只有在计算机上通过更改一些约束才能进行大量测试。
以上是关于如何综合编译器测试数据?的主要内容,如果未能解决你的问题,请参考以下文章