如何为在Nim中编译失败的代码编写单元测试?

时间:2016-02-08 21:19:20

标签: nim

我在unittest模块的帮助下编写了大部分单元测试,但我不确定如何将它用于编译器在编译时应拒绝的代码。例如,如果我想编写以下代码并确保编译器在编译期间总是出错(类型和模板将在一个单独的模块中),我该如何为此编写测试用例?

import macros
type
  T[n:static[int]] = object
template foo3(n: int): expr =
  static:
    if n > 3: error "n > 3"
  type T3 = T[n]
  T3
var
  bar: foo3(4)

3 个答案:

答案 0 :(得分:3)

您可以使用系统模块提供的compiles魔法做类似的事情。

以下是编译器测试套件的示例:
https://github.com/nim-lang/Nim/blob/devel/tests/metatype/tbindtypedesc.nim#L19

请注意,在文件的顶部,我们使用accept魔法将rejectcompiles定义为简单的静态断言,我们在整个文件中使用它们来测试有效和无效的重载调用

就我个人而言,我认为在编译时失败更好,但您可以将compiles的结果分配给运行时值或在check语句中使用它。这样做的唯一好处是将以标准方式报告单元测试库的失败。

答案 1 :(得分:1)

只是添加一个如何将checkcompiles结合使用的示例:

template notCompiles*(e: untyped): untyped =
  not compiles(e)

# usage in unit tests:
check:
  notCompiles: 
    does not compile
  notCompiles:
    let x = 1    # would fail

我正在使用模板,因为直接将not与块直接组合是不可能的,我不想使用括号。

答案 2 :(得分:0)

https://github.com/shaunc/cucumber_nim/blob/b1601a795dbf8ea0d0b5d96bf5b6a1cd90271327/tests/steps/dynmodule.nim

我有一个包装器,可以编译并加载一个nim源模块。当然,你不想运行它,但这项技术可能适合你:

  sourceFN = "foo.nim"
  ... (write source) ...
  libFN = "foo.dll"
  let output = execProcess(
    "nim c --verbosity:0 --app:lib $1" % sourceFN,
    options = {poStdErrToStdOut, poUsePath, poEvalCommand})
  if not fileExists(libFN):
    echo "COULDN'T COMPILE"