2017-06-22 2 views
0

J'essaie d'utiliser forAll de ScalaCheck en conjonction avec les fonctions de comportement, mais je rencontre des problèmes. Les fonctions de comportement ressemblent à ceci:Générateurs ScalaCheck avec les fonctions de comportement de ScalaTest

def someBehaviour(args: FunArgs) 

FunArgs est essentiellement un type d'union des différentes possibilités que je veux vérifier. Donc, il y a un FunArgs1 et un FunArgs2 que les deux hériter de FunArgs mais ont des membres différents (par exemple on a deux Int s tandis que l'autre a un String, un Long et un Int). La fonction réelle que je veux tester traite de ces différents cas en interne.

sealed trait FunArgs 
final case class FunArgs1(a: Int, b: Int) extends FunArgs 
final case class FunArgs2(x: Long, y: Int, z: String) extends FunArgs 

sealed trait FunRes 
final case class FunRes1(...) extends FunRes 
final case class FunRes2(...) extends FunRes 

def someFun(args: FunArgs): FunRes = args match { 
    // do stuff and return some subclass of FunRes 
} 

trait SomeBehaviors { this: UnitSpec => 

    def someBehavior(args: FunArgs) { 

    it should "do stuff " in { 
     val result = someFun(args) // creates an instance of FunRes 
     ... 
     result should contain theSameElementsAs expected 
    } 

    it should "do more stuff" in { 
     // similar to before 
     ... 
     result should contain theSameElementsAs expected 
    } 
    } 
} 

l'intérieur de la fonction de comportement sont multiples clauses in parce que toutes les fonctions doivent satisfaire le même comportement.

Le problème est que je ne peux pas le faire parce que cela va créer des noms de test en double:

forAll { (a: Int, b: Int) => 
    someBehavior(FunArgs1(a, b)) 
} 

Mais je ne peux pas non plus le faire à cause de « devrait » à l'intérieur « dans »:

"someFun1" should "do stuff" in { 
    forAll { (a: Int, b: Int) => 
    someBehaviour(FunArgs1(a, b)) 
    } 
} 

Et la ligne ci-dessous ne me donne pas la possibilité d'utiliser des générateurs parce que je devrais mettre le forAll dans le comportement où je ne sais pas nécessairement combien et quels types les arguments sont.

"someFun1" should behave like someBehaviour(MakeFunArgs1(a, b)) 

Existe-t-il un moyen de faire ce que je veux?

+0

Si je comprends bien ce que vous essayez de réaliser, vous devriez probablement définir un générateur 'Gen [FunArgs]' personnalisé (nommé, par exemple, 'funArgs'). Ensuite, vous pouvez facilement écrire une propriété de la forme 'forAll (funArgs) {fa => someBehavior (fa)}', qui couvrirait tous les sous-types 'FunArgs', par opposition à l'écriture d'une propriété pour chaque sous-type. – Jubobs

Répondre

0

Vous pouvez faire quelque chose comme ça

trait SomeBehaviors { this: UnitSpec => 

    def someBehavior(index:Int, args: FunArgs) { 

    it should s"do stuff $index" in { 
     val result = someFun(args) // creates an instance of FunRes 
     ... 
     result should contain theSameElementsAs expected 
    } 

    it should "do more stuff $index" in { 
     // similar to before 
     ... 
     result should contain theSameElementsAs expected 
    } 
    } 
} 

Vous pouvez appeler la suite avec testCaseName unique:

var index=0 
forAll { (a: Int, b: Int) => 
    someBehavior(index,FunArgs1(a, b)) 
    index = index+1 
} 

au lieu d'index, vous pouvez également générer un nom unique en utilisant un & b, qui va résoudre le problème.

+0

Cela va créer un nombre potentiellement énorme de sous-cas qui seront listés même s'ils ne devraient avoir qu'une seule entrée dans le rapport de test. Ils vérifient tous la même chose après tout, juste pour différentes entrées. –