В ScalaCheck нет сокращения для положительных целых чисел.Вы должны написать свой собственный.
Обзор
A Shrink
должен быть определен как implicit
в области проверки вашего свойства.Затем Prop.forAll
найдет правильный класс Shrink
, если он находится в области видимости и имеет соответствующую сигнатуру типа для значения, которое не прошло тест.
По сути, экземпляр Shrink
является функцией, которая преобразуетошибочное значение x
для потока «сжатых» значений.Его типовая сигнатура примерно равна:
trait Shrink[T] {
def shrink(x: T): Stream[T]
}
Вы можете определить Shrink
с помощью метода apply
объекта-компаньона, который примерно такой:
object Shrink {
def apply[T](s: T => Stream[T]): Shrink[T] = {
new Shrink[T] {
def shrink(x: T): Stream[T] = s(x)
}
}
}
Ответ: Сокращение натуральных чисел
Сжатие для положительных целых чисел - это Stream
, которое уменьшается вдвое, чтобы найти наименьший сбойный случай при бинарном поиске, но останавливается до достижения нуля:
class ShrinkProp extends Properties("Shrink") {
implicit val posIntShrinker: Shrink[Int] = Shrink { x: Int =>
Stream.iterate(x / 2) { x: Int =>
x / 2
}.takeWhile { x: Int =>
x > 0 // Avoid zero.
}
}
property("posNum[Int]") = {
Prop.forAll(Gen.posNum[Int]) { _: Int =>
Prop.falsified
}
}
}
Доказательство этого сбояработает:
[info] ! Shrink.posNum[Int]: Falsified after 6 passed tests.
[info] > ARG_0: 2
[info] > ARG_0_ORIGINAL: 4
[info] Failed: Total 1, Failed 1, Errors 0, Passed 0
Еще лучше, вы могли бы написать свойство, чтобы проверить, как ваш усадчик ведет себя как следует:
property("posIntShrinker") = {
Prop.forAll { x: Int =>
val shrunk = Shrink.shrink(x)
Prop.atLeastOne(
(x >= 2) ==> shrunk.size > 0,
(x <= 1) ==> shrunk.isEmpty
)
}
}
[info] + Shrink.posIntShrinker: OK, passed 100 tests.
[info] Failed: Total 1, Failed 0, Errors 0, Passed 1
Было бы неплохо написать общий позитивчисла Shrink
, которые могли бы сжать другие типы чисел, такие как Long
, типы с плавающей запятой и BigDecimal
.