Ich bin ziemlich neu in Scalacheck (und Scala ganz) so kann dies eine ziemlich einfache Lösung seinScalacheck Shrink
Ich bin mit einem Scalacheck AST erzeugen Tests für und überprüfen, ob der Schreiber/Parser Arbeit. Ich habe diese Dateien
AST.scala
package com.test
object Operator extends Enumeration {
val Add, Subtract, Multiply, Divide = Value
}
sealed trait AST
case class Operation(left: AST, op: Operator.Value, right: AST) extends AST
case class Literal(value: Int) extends AST
GenOperation.scala
import com.test.{AST, Literal}
import org.scalacheck._
import Shrink._
import Prop._
import Arbitrary.arbitrary
object GenLiteral extends Properties("AST::Literal") {
property("Verify parse/write") = forAll(genLiteral){ (node) =>
// val string_version = node.writeToString() // AST -> String
// val result = Parse(string_version) // String -> AST
true
}
def genLiteral: Gen[Literal] = for {
value <- arbitrary[Int]
} yield Literal(value)
implicit def shrinkLiteral: Shrink[AST] = Shrink {
case Literal(value) =>
for {
reduced <- shrink(value)
} yield Literal(reduced)
}
}
GenOperation.scala
import com.test.{AST, Operation}
import org.scalacheck._
import Gen._
import Shrink._
import Prop._
import GenLiteral._
object GenOperation extends Properties("AST::Operation") {
property("Verify parse/write") = forAll(genOperation){ (node) =>
// val string_version = node.writeToString() // AST -> String
// val result = Parse(string_version) // String -> AST
true
}
def genOperation: Gen[Operation] = for {
left <- oneOf(genOperation, genLiteral)
right <- oneOf(genOperation, genLiteral)
op <- oneOf(Operator.values.toSeq)
} yield Operation(left,op,right)
implicit def shrinkOperation: Shrink[AST] = Shrink {
case Operation(l,o,r) =>
(
for {
ls <- shrink(l)
rs <- shrink(r)
} yield Operation(ls, o, rs)
) append (
for {
ls <- shrink(l)
} yield Operation(ls, o, r)
) append (
for {
rs <- shrink(r)
} yield Operation(l, o, rs)
) append shrink(l) append shrink(r)
}
}
Im Beispiel Code, den ich geschrieben (was oben eingefügt wird) erhalte ich die Fehler
ambiguous implicit values:
both method shrinkLiteral in object GenLiteral of type => org.scalacheck.Shrink[com.test.AST]
and method shrinkOperation in object GenOperation of type => org.scalacheck.Shrink[com.test.AST]
match expected type org.scalacheck.Shrink[com.test.AST]
ls <- shrink(l)
Wie schreibe ich die Schrumpfverfahren dafür?
Dies ist genau das, was ich suche. Ich schätze als Nebenfrage, da ich drei verschiedene Dateien habe, eine für AST, Operation und Literal, wie bekomme ich Scala, um die impliziten Defs zu erkennen? –
Sie könnten "Literal" - und "Operation" -Implikits (sowohl "Gen" als auch "Shrink") in zwei verschiedene Merkmale aufteilen. Dann können Sie sie zu einem einzigen 'AST'-Merkmal zusammenfassen und darin ein 'Shrink [AST]' definieren. Mischen Sie diese Merkmale in 'Properties'-Objekten, wenn sie benötigt werden. –
Eine alternative Lösung könnte sein, sich nicht auf implicits zu verlassen und 'shrinkAST' explizit mit' shrinkLiteral (l) 'und' shrinkOperation (o) 'zu definieren. –