如何测试解释器或编译器?

Ste*_*ell 11 compiler-construction testing interpreter brainfuck

我一直在尝试为Brainfuck创建一个解释器,虽然很容易制作和启动并运行,但我的一部分希望能够针对它运行测试.我似乎无法理解可能需要编写多少测试来测试所有可能的指令组合以确保实现正确.

显然,使用Brainfuck,指令集很小,但我不禁想到随着更多指令的添加,您的测试代码将呈指数级增长.比任何速度的典型测试都要多.

现在,我就像编写编译器和解释器一样可以得到新手,所以我的假设很可能会偏离基础.

基本上,你甚至从哪里开始测试这样的东西?

Nor*_*sey 11

测试编译器与测试其他类型的应用程序略有不同,因为只要编译器都做正确的事情,编译器就可以生成程序的不同汇编代码版本.但是,如果您只是测试一个解释器,它与任何其他基于文本的应用程序几乎相同.这是一个以Unix为中心的视图:

  1. 您将需要构建回归测试套件.每个测试都应该有
    • 你要解释的源代码,比方说 test001.bf
    • 比如你将要解释的程序的标准输入 test001.0
    • 比如,你期望翻译人员在标准输出上产生什么 test001.1
    • 您希望解释器在标准错误上产生什么,比如说test001.2 (您关心标准错误,因为您想测试解释器的错误消息)
  2. 您将需要一个"运行测试"脚本,它执行以下操作

    function fail {
      echo "Unexpected differences on $1:"
      diff $2 $3
      exit 1
    }
    
    for testname
    do
      tmp1=$(tempfile)
      tmp2=$(tempfile)
      brainfuck $testname.bf < $testname.0 > $tmp1 2> $tmp2
      [ cmp -s $testname.1 $tmp1 ] || fail "stdout" $testname.1 $tmp1
      [ cmp -s $testname.2 $tmp2 ] || fail "stderr" $testname.2 $tmp2
    done
    
    Run Code Online (Sandbox Code Playgroud)
  3. 你会发现有一个"创建测试"脚本可以做类似的事情

    brainfuck $testname.bf < $testname.0 > $testname.1 2> $testname.2
    
    Run Code Online (Sandbox Code Playgroud)

    只有当您完全确信解释器适用于该情况时,才会运行此操作.

  4. 您将测试套件保持在源代码管理之下.

  5. 修饰测试脚本很方便,因此可以省略预期为空的文件.

  6. 任何时候任何变化,你重新运行所有测试.你可能也会通过一个cron工作整夜重新运行它们.

  7. 最后,您希望添加足够的测试以获得编译器源代码的良好测试覆盖率.覆盖工具的质量差异很大,但GNU Gcov是一个足够的覆盖工具.

祝你的翻译好运!如果你想看一个精心设计但没有很好记录的测试基础设施,请查看Quick C--编译器test2目录.