Haskell中的编译器集成测试

Lyk*_*kos 10 compiler-construction testing integration-testing haskell

我打算在Haskell中编写一个小玩具编译器,以获得一种非常简单的语言,以加强我的Haskell技能,并设计一种新语言.我仍然在考虑一些一般性的决定,其中一个最大的开放点是如何进行集成测试.我有以下要求:

  • 应该可以创建三元组列表(输入,程序,输出),这样我的集成测试运行我的编译器来编译程序,运行编译的二进制文件,将输入传递给它并验证运行的输出是等于给定的输出.
    • 应该可以在稍后扩展整数测试以测试与程序的更复杂的交互,例如它改变文件或睡眠至少20秒或类似的东西.

我还有以下可选要求:

  • 它应该尽可能地"端到端",即它应该尽可能地将整个编译器视为黑盒子,它不应该访问编译器的内部或类似的东西.
  • 所有代码都应该用Haskell编写.
  • 如果我能免费获得典型的测试框架功能,即不自己实现,那将是很好的.例如绿色"SUCCESS"消息或描述失败的错误消息集合.

我试图找到满足我需求的东西,但到目前为止我还没有成功.我考虑的替代方案如下:

  • 除了我想在Haskell中编写代码的条件之外,shunit会满足一切.
  • QuickCheck允许我在Haskell中编写所有内容,但据我所知,它似乎主要适用于仅涉及Haskell函数及其结果的测试.所以我需要在编译器中测试函数并放宽我的"端到端"要求.
  • 我可以编写一个Haskell程序,在另一个进程中启动编译器,将输入程序传递给它,然后在另一个进程中启动编译后的代码,将其传递给inpit并检查输出.然而,这将涉及我在ordee中的大量编码,以实现在使用测试框架时免费获得的所有功能.

我不确定我应该选择哪个选项,我仍然希望我错过了一个很好的解决方案.您是否知道如何创建满足我所有要求的集成测试?

Eri*_*lun 4

\n\n

我在想unsafePerformIO这里应该非常安全,考虑到程序不应该与测试环境/逻辑所依赖的任何东西交互,或者换句话说,在测试环境中,编译和执行应该被视为纯函数。受控、隔离的环境。我认为在这种情况下测试你的编译器确实很有用。即使对于黑盒测试,QuickCheck 也应该成为一种选择。但一些更清醒的头脑可能会证明我是错的。

\n\n

所以假设你的编译器是这样的:

\n\n
type Source = String\n\ncompile :: Source -> Program\n
Run Code Online (Sandbox Code Playgroud)\n\n

你的程序执行是

\n\n
data Report = Report Output TimeTaken OtherStats ...\n\nexecute :: Program -> IO Report\n
Run Code Online (Sandbox Code Playgroud)\n\n

你可以很安全地使用unsafePerformIO其转换为

\n\n
execute\' :: Program -> Report -- or perhaps \'executeUnsafe\'\nexecute\' = unsafePerformIO . execute\n
Run Code Online (Sandbox Code Playgroud)\n\n

进而

\n\n
compileAndExec :: Source -> Report\ncompileAndExec = compile . execute\'\n
Run Code Online (Sandbox Code Playgroud)\n\n

并将其与 QuickCheck 一起使用。

\n\n
\n\n

无论execute调用子进程、获取实际的二进制文件、执行该二进制文件等、\xe2\x80\x94 或解释内存中的二进制文件(或字节码),都取决于您。

\n\n

但我建议将字节代码和二进制生成分开:这样您就可以将编译器与链接器/诸如此类的东西分开测试,这更容易,并且还可以在此过程中获得解释器。

\n