3 votes

ScalaCheck, comportement différent lors de l'appel de Test.check ou Test.checkProperties

J'ai le code suivant qui utilise les propriétés ScalaCheck pour tester une certaine classe

package quickcheck.tests

import org.scalacheck.Arbitrary._
import org.scalacheck.Gen._
import org.scalacheck.Prop._
import org.scalacheck._
import org.scalacheck.util.ConsoleReporter

class Heap
{
}

object Heap
{
  val empty = new Heap
  def insert(i: Int, h: Heap) = new Heap
}

class TestCheck extends Properties("Heap")
{
  lazy val genHeap: Gen[Heap] =
  {
    def sizedHeap(size: Int): Gen[Heap] =
    {
      if (size <= 0)
        Heap.empty
      else
        for
        (
          i <- arbitrary[Int] suchThat(_ > Int.MinValue);
          s <- choose(0, size);
          h <- sizedHeap(s)
        )
          yield
            Heap.insert(i, h)
    }

    Gen.sized[Heap](sizedHeap)
  }

  implicit lazy val arbHeap: Arbitrary[Heap] = Arbitrary(genHeap)

  property("test1") = forAll
  {
    (h: Heap) => true
  }

  property("test2") = forAll
  {
    (h1: Heap, h2: Heap, n: Int) => true
  }
}

object MyTest extends App
{
  println("*** TEST 1")
  val checkHeap = new TestCheck
  Test.checkProperties(Test.Parameters.default.withTestCallback(ConsoleReporter(1)), 
    checkHeap)

  println("*** TEST 2")
  val checkHeap2 = new TestCheck
  checkHeap2.check

  println("*** TEST 3")
  val checkHeap3 = new TestCheck
  Test.check(Test.Parameters.default.withTestCallback(ConsoleReporter(1)),     checkHeap)
}

Si je le fais passer par le ScalaCheck Test classe J'obtiens des résultats différents si j'utilise la méthode Test.checkProperties ou méthode Test.check .

Voici le résultat que j'obtiens :

*** TEST 1
+ Heap.test1: OK, passed 100 tests.
+ Heap.test2: OK, passed 100 tests.
*** TEST 2
+ Heap.test1: OK, passed 100 tests.
+ Heap.test2: OK, passed 100 tests.
*** TEST 3
! Gave up after only 40 passed tests. 202 tests were discarded.

Ma question est de savoir pourquoi TEST1 donne un résultat différent de TEST3.

Si je retire le suchThat et laisser le for dans le sizeHead comme ceci :

for
(
  i <- arbitrary[Int]
  s <- choose(0, size);
  h <- sizedHeap(s)
)
  yield
    Heap.insert(i, h)

J'obtiens le résultat suivant :

*** TEST 1
+ Heap.test1: OK, passed 100 tests.
+ Heap.test2: OK, passed 100 tests.
*** TEST 2
+ Heap.test1: OK, passed 100 tests.
+ Heap.test2: OK, passed 100 tests.
*** TEST 3
+ OK, passed 100 tests.

S'agit-il d'un bogue ou d'un comportement correct ? Gardez à l'esprit que ScalaTest Checkers.check utilise Test.check .

1voto

lunaryorn Points 13621

Vous obtenez des résultats différents parce que vous faites des choses différentes. Vos deux premiers tests, qui sont effectivement le même -vérifier toutes les propriétés séparément, alors que votre troisième teste toutes les propriétés comme s'il s'agissait d'une seule propriété .

Jetez un coup d'œil aux signatures de Test.check y Test.checkProperties : Le premier prend un seul Prop alors que ce dernier prend un Properties conteneur.

Dans scalacheck 1.12 Properties hérite de Prop ; si vous passez Properties comme Prop vous obtenez un nouvelle propriété que teste si toutes les propriétés contenues tiennent . La conséquence est que vous testez tous vos TestCheck les propriétés avec un simple ), et naturellement cette configuration de contrôle est épuisée à un moment donné.

Donc oui, c'est un comportement attendu. Bien sûr, c'est absolument déroutant, c'est pourquoi scalacheck 1.13 a supprimé cette fonctionnalité : Properties n'hérite pas de Prop plus ; votre exemple ne compilerait plus sur scalacheck 1.13.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X