#scala #scalacheck #property-based-testing
#scala #scalacheck #тестирование на основе свойств
Вопрос:
У меня довольно большая структура классов case, и где-то глубоко внутри этой структуры у меня есть поля, которые я хочу уточнить, например, сделать списки непустыми. Можно ли указать ScalaCheck, чтобы сделать эти списки непустыми, используя автоматический вывод из проекта scalacheck-magnolia (без указания каждого поля отдельно)? Пример:
import com.mrdziuban.ScalacheckMagnolia.deriveArbitrary
import org.scalacheck.Arbitrary
import org.scalacheck.Gen
case class A(b: B, c: C)
case class B(list: List[Long])
case class C(list: List[Long])
// I've tried:
def genNEL[T: Gen]: Gen[List[T]] = Gen.nonEmptyListOf(implicitly[Gen[T]])
implicit val deriveNEL = Arbitrary(genNEL)
implicit val deriveA = implicitly[Arbitrary[A]](deriveArbitrary)
Но это не сработало.
Ответ №1:
Я не уверен, как быть универсальным, поскольку я не знаком с получением автоматического вывода для Arbitrary
с помощью scalacheck-magnolia. Похоже, scalacheck-magnolia хорош для получения Arbitrary
для классов case, но, возможно, не для контейнеров (списков, векторов, массивов и т.д.).
Если вы хотите просто использовать обычный ScalaCheck, вы могли бы просто определить неявный параметр Arbitrary
для A
себя. Выполнение этого вручную — это дополнительный шаблон, но его преимущество в том, что у вас больше контроля, если вы хотите использовать разные генераторы для разных частей вашей структуры данных.
Вот пример, когда Arbitrary
список длин по умолчанию непустой, но пуст для B
.
implicit val listOfLong =
Arbitrary(Gen.nonEmptyListOf(Arbitrary.arbitrary[Long]))
implicit val arbC = Arbitrary {
Gen.resultOf(C)
}
implicit val arbB = Arbitrary {
implicit val listOfLong =
Arbitrary(Gen.listOf(Arbitrary.arbitrary[Long]))
Gen.resultOf(B)
}
implicit val arbA = Arbitrary {
Gen.resultOf(A)
}
property("arbitrary[A]") = {
Prop.forAll { a: A =>
a.b.list.size >= 0 amp;amp; a.c.list.size > 0
}
}