我正在寻找一种使用多个输入来测试我的Scala代码的方法。来自Java / JUnit,我立刻想到了@RunWith(Theories.class)
。
我遇到的问题是@DataPoints的使用以及Scala中缺少静态成员/方法。那么有没有办法在Scala中编写以下代码?
@RunWith(classOf[Theories])
class ScalaTheory {
@DataPoints
val numbers = Array(1, 2, 3)
@Theory
def shouldMultiplyByTwo(number : Int) = {
// Given
val testObject = ObjectUnderTest
// When
val result = testObject.run(number)
// Then
assertTrue(result == number * 2)
}
}
我既不是JUnit也不是Theories,所以如果这个用例有特定于Scala的东西,我很乐意使用它。
答案 0 :(得分:4)
要完成这项工作,您必须做两件事:使用方法[请参阅下面的编辑],而不是值,其次,在随播对象中定义@DataPoints
。以下应该有效:
object ScalaTheory {
@DataPoints
def numbers() = Array(1, 2, 3) // note def not val
}
@RunWith(classOf[Theories])
class ScalaTheory {
@Theory
def shouldMultiplyByTwo(number : Int) = {
// Given
val testObject = ObjectUnderTest
// When
val result = testObject.run(number)
// Then
assertTrue(result == number * 2)
}
}
在Scala中的伴随对象中定义方法或字段时,您将在类中获得静态转发器。使用JAD进行反编译:
@Theories
public static final int[] numbers()
{
return ScalaTheory$.MODULE$.numbers();
}
因此,这将解决静态问题。但是,当我们使用val numbers = ...
时,注释不会转移到字段,而是用于方法。因此,使用def
可以正常工作。
正如其他人所说的那样,如果你是从头开始,那么可能值得开始使用像scalatest这样的Scala框架。与scalatest的工具集成正在改进(即maven,Eclipse,Intellij),但它不是JUnit的级别,因此在开始之前为您的项目评估它。
编辑:事实上,在this discussion on scala-user之后,您可以使用val,但是您需要告诉scala编译器将DataPoints批注应用于静态转发器:
object ScalaTheory {
@(DataPoints @scala.annotation.target.getter)
val numbers = Array(1, 2, 3)
}
getter注释表示@DataPoints注释应该应用于数字字段的访问器方法,即编译器创建的numbers()方法。请参阅package target。
答案 1 :(得分:2)
我希望每个Scala测试框架都能满足您的需求。我只熟悉Specs2,所以这是我的镜头:
class DataPoints extends Specification {
val objectUnderTest: Int => Int = _ + 2
val testCases = 1 :: 2 :: 3 :: 4 :: Nil
def is: Fragments =
(objectUnderTest must multiplyByTwo((_: Int))).foreach(testCases)
def multiplyByTwo(i: Int): Matcher[(Int) => Int] =
(=== (i * 2)) ^^
((f: Int => Int) => f(i) aka "result of applying %s to %d".format(f, i))
}
输出是:
result of applying <function1> to 1 '3' is not equal to '2'; result of applying <function1> to 3 '5' is not equal to '6'; result of applying <function1> to 4 '6' is not equal to '8'
我并未声明这是非常易读的。我也不是Specs2的专家用户。
答案 2 :(得分:2)
就像ziggystar一样,我无法真正帮助你解决直接问题。但我强烈建议切换到scala测试框架。我个人最喜欢的是scalatest。
在这里的最后一个例子中:http://blog.schauderhaft.de/2011/01/16/more-on-testing-with-scalatest/我演示了编写运行多个输入的测试是多么简单和直接。这只是一个简单的循环!