假设我有两个类型为Numeric
的实例。
class Money(c: String, x: Long, y: Int)
class Quantity(c: String, x: Long, y: Int)
implicit val numericMoney: Numeric[Money] = new Numeric[Money]
implicit val numericQuantity: Numeric[Quantity] = new Numeric[Quantity]
货币和数量在数字实例中的行为应相同。 我有scalaTest测试,用于检查Money是否正常运行。
例如
import implicits.NumericMoney.numericMoney._
class MoneyOpsSpec extends WordSpec with Matchers {
val max = Money("", Long.MaxValue, 999999999)
val min = Money("", Long.MinValue, -999999999)
"A Money object" when {
"zero" should {
"be neutral element under addition" in {
zero + Money("", 15, 50) should ===(Money("", 15, 50))
Money("", 15, 50) + zero should ===(Money("", 15, 50))
}
"be neutral element under subtraction" in {
zero - Money("", 15, 50) should ===(Money("", -15, -50))
Money("", 15, 50) - zero should ===(Money("", 15, 50))
}
"be invariant under negation" in {
-zero should ===(zero)
}
}
}
}
Quantity
规范应以相同的方式执行。我可以实现通用规范并将Money
和Quantity
用作该规范的输入吗?还是scalaTest或specs2可以确保数字类型类实例的行为正确?我可以轻松切换测试框架。
答案 0 :(得分:1)
我可以实施通用规范并将货币和数量用作该规范的输入吗?
好的。只需将隐式作为构造函数参数即可。未经测试,但应该大致相同(变化很小):
abstract class NumOpsSpec[T](implicit num: Numeric[T], tag: ClassTag[T]) extends WordSpec with Matchers {
import num._
val max: T
val min: T
val someElement: T
s"A ${tag.runtimeClass.simpleName} object" when {
"zero" should {
"be neutral element under addition" in {
zero + someElement should ===(someElement)
someElement + zero should ===(someElement)
}
"be neutral element under subtraction" in {
zero - someElement should ===(- someElement)
someElement - zero should ===(someElement)
}
"be invariant under negation" in {
-zero should ===(zero)
}
}
}
}
class MoneyOpsSpec extends NumOpsSpec[Money] {
override val max = Money("", Long.MaxValue, 999999999)
override val min = Money("", Long.MinValue, -999999999)
override val someElement = Money("", 15, 50)
}
class QuantityOpsSpec extends NumOpsSpec[Quantity] {
override val max = ???
override val min = ???
override val someElement = ???
}
您还可以考虑使用https://github.com/typelevel/discipline来测试一般的类规则。
答案 1 :(得分:0)
我认为您需要创建用于测试不同操作的抽象方法,并将其与两个对象一起使用。对于前。测试添加
def testAddition[T](a: T, b: T, expectedResult: T)(implicit n: Numeric[T]) = {
n.plus(a, b) ==== expectedResult
}
然后您可以使用Money
或Quantity
来调用此方法
testAddition(Money(1, 1), Money(2, 2), Money(3, 3))
testAddition(Quantity(1, 1), Quantity(2, 2), Quantity(3, 3))