scala - 如何对 Numeric 的不同类型类实例进行单元测试?
问题描述
假设我有两个 typeclass 实例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]
Money 和 Quantity 在 Numeric 实例中的行为应该相同。我有 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
spec 应该以同样的方式执行。我可以实现一个通用规范并使用Money
和Quantity
作为该规范的输入吗?或者 scalaTest 或 specs2 是否有一些东西可以确保 Numeric 类型类实例的行为正确?我可以轻松切换测试框架。
解决方案
我可以实现一个通用规范并使用 Money 和 Quantity 作为该规范的输入吗?
当然。只需将隐式作为构造函数参数即可。未经测试,但应该是近似的(变化很小):
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以测试一般类型的法律。
推荐阅读
- java - 从 6.0.5 升级到 6.2 后的 Liferay 编码
- javascript - javascript:未捕获的引用错误
- java - 添加网站不同子目录的不同意图
- java - 流启动后 Spark Stream 新作业
- php - 无法更改 Travis-CI PHP memory_limit
- yaml - 带括号的 Homestead.yaml 格式目录路径
- angular - 在收到 HTTP Post 的响应之前,如何阻止循环继续?(离子 3)
- javascript - 为什么将联系人添加到数组中的方法不起作用?
- python - 根据输入更改列表的顺序
- apache-spark - spark基于其他数据集的数据集值计算