单元测试 – 如何编写可确保并发失败的scala单元测试?

有没有办法写出像“单元测试”这样的东西,确保一些代码不能编译?

为什么我想要这样的事情?两个原因

1)检查API的类型安全.我想要一种方法来确保有人传递错误的值,您会收到编译器错误,而不仅仅是运行时错误.显然,我可以运行编译器并检查错误,但是在单元测试中将其正式化是有益于避免回归和也用于文档.

例如,考虑这个测试.有一些注释掉的代码,我用来检查类型安全:
https://github.com/squito/boxwood/blob/master/core/src/test/scala/com/quantifind/boxwood/EnumUnionTest.scala#L42
(第42行和第48行 – 在第34行我调用不同的API,它具有运行时异常,我可以检查)

实际上花了我一段时间才能获得类型安全权利,所以这些是重要的检查.现在,如果我去修改底层的实现,我不能只运行我的测试套件 – 我也必须记得取消注释这些行,并检查编译器错误.

2)测试宏的错误处理.如果一个宏有一些不好的输入,那应该会导致一个编译错误.同样的问题在这里,同样的愿望让它在一个易于运行的测试套件.

我使用ScalaTest,但我很高兴在这里有任何单元测试框架的解决方案.

最佳答案
正如我在上面发表的评论中所说,基于Stefan Zeiger的解决方案,Shapeless 2.0(尚未发布,但目前可用作里程碑)具有非常好的实现您要查找的功能.我已经为您的项目here添加了一个演示(请注意,我不得不更新到Scala 2.10,因为此解决方案使用宏).它的工作原理如下:

import shapeless.test.illTyped

//this version won't even compile
illTyped("getIdx(C.Ooga)")

//We can have multiple enum unions exist side by side
import Union_B_C._
B.values().foreach {b => Union_B_C.getIdx(b) should be (b.ordinal())}
C.values().foreach {c => Union_B_C.getIdx(c) should be (c.ordinal() + 2)}

//Though A exists in some union type, Union_B_C still doesn't know about it,
// so this won't compile
illTyped("""
  A.values().foreach {a => Union_B_C.getIdx(a) should be (a.ordinal())}
""")

如果我们将第二次调用illTyped中的代码更改为要编译的内容:

B.values().foreach {a => Union_B_C.getIdx(a) should be (a.ordinal())}

我们会收到以下编译错误:

[error] .../EnumUnionTest.scala:56: Type-checking succeeded unexpectedly.
[error] Expected some error.
[error]     illTyped("""
[error]             ^
[error] one error found
[error] (core/test:compile) Compilation failed

如果您希望失败的测试,您可以很容易地适应the implementation in Shapeless.请参阅Miles’s answermy previous question进行一些其他讨论.

转载注明原文:单元测试 – 如何编写可确保并发失败的scala单元测试? - 代码日志