haskell - Haskell 中的编译器集成测试

标签 haskell testing compiler-construction integration-testing

我打算用 Haskell 为一种非常简单的语言编写一个小玩具编译器,以加强我的 Haskell 技能并享受设计新语言的乐趣。我仍在考虑一些一般性的决定,最大的开放点之一是我将如何进行集成测试。我有以下要求:

  • 应该可以创建一个三元组列表(输入、程序、输出),以便我的集成测试运行我的编译器来编译程序,运行编译后的二进制文件,将输入传递给它并验证输出运行等于给定的输出。
    • 应该可以在以后扩展集成测试,以测试与程序的更复杂的交互,例如它更改文件或休眠至少 20 秒或类似的时间。

我还有以下可选要求:

  • 它应该尽可能“端到端”,即它应该尽可能将整个编译器视为一个黑盒,并且它不应该访问编译器的内部或类似的东西。<
  • 所有代码都应该用 Haskell 编写。
  • 如果我能免费获得典型的测试框架功能就好了,即无需自己实现。例如。一条绿色的“SUCCESS”消息或一组描述失败的错误消息。

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

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

我还不确定我应该选择哪个选项,我仍然希望我错过了一个好的解决方案。您对我如何创建满足我所有要求的集成测试有任何想法吗?

最佳答案

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

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

type Source = String

compile :: Source -> Program

你的程序执行是

data Report = Report Output TimeTaken OtherStats ...

execute :: Program -> IO Report

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

execute' :: Program -> Report -- or perhaps 'executeUnsafe'
execute' = unsafePerformIO . execute

然后

compileAndExec :: Source -> Report
compileAndExec = compile . execute'

并将其与 QuickCheck 一起使用。


execute 是否调用子进程、获取实际的二进制文件、执行它等等,或者在内存中解释二进制文件(或字节码),由您决定。

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

关于haskell - Haskell 中的编译器集成测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33032768/

相关文章:

haskell - 如果是单子(monad)的话

Haskell 长度和滤波器确定直线的凸度或凹度

haskell - haskell 中的 `foreach`

testing - 可以在 Katalon 中运行命令吗?

c++ - 为什么 BOOST_AUTO_TEST_CASE 不起作用?

programming-languages - 创建编程语言和编译器设计。他们有关系吗?

c# - C# 编译器如何区分抽象方法的具体子类实现和抽象基类中的重载?

haskell - 是否有实例替代((->)r)?

java - jackson 的 Access.WRITE_ONLY 在测试期间为空

java - 如何使用 JavaCC/JJTree 来存储 token ?