ããŒã2.ãžã§ãã¬ãŒã¿ãŒ
ãã®ã·ãªãŒãºã®å
¥éèšäºã§ããžã§ãã¬ãŒã¿ãŒãæ¢ã«ç¥ã£ãŠããããšãé¡ã£ãŠããŸãã ãã®ãã¥ãŒããªã¢ã«ã§ã¯ãåŠç¿ããç¥èãçµ±åããç¬èªã®ïŒååž°ãå«ãïŒãžã§ãã¬ãŒã¿ãŒã®äœææ¹æ³ãåŠç¿ããŸãã ãžã§ãã¬ãŒã¿ãŒå°çšã§ãããããããã£ã«ã€ããŠãå¿ããŸããã ããã«ãããããç©æ¥µçã«äœ¿çšããŠããžã§ãã¬ãŒã¿ãŒã¡ã«ããºã ã®ãã«ãã¯ãŒãå®èšŒããŸãã åææ¡ä»¶ã®ã¡ã«ããºã ãæ€èšããŠãã ããã ãããããã·ãªãŒãºã®2çªç®ã®èšäºãããããã£ã«åœãŠãæ¹ãè«ççã§ããããããããããæ£ããæ±ºå®ã§ãããã ããããç§ã®å人çãªèгå¯ã«ãããšãæãå°é£ãªã®ã¯ãžã§ãã¬ãŒã¿ãŒã§ãã æ¬¡ã®èšäºã§ããããã£ãæ€èšããŸãã
ãµã€ã¯ã«æ§é
çºé»æ©
Prop
ãªããžã§ã¯ãã®forAll
ã¡ãœããã¯ãã©ã³ãã ã«çæãããããŒã¿ã䜿çšããŸãã åçŽãªããŒã¿åãŸãã¯ã³ã³ããïŒ è€å ïŒåã®ããããã§ãã ScalaCheckã§ã¯ããžã§ãã¬ãŒã¿ãŒã¯Genã®åå«ã§ãã
sealed abstract class Gen[+T] { def apply(prms: Gen.Params): Option[T] ... }
ã¯ã©ã¹ã¯ãçæãããå€ã®ã¿ã€ãã«ãã£ãŠãã©ã¡ãŒã¿ãŒã決ãŸããŸãã ãããã£ãŠãæååã«ã¯Gen[String]
ããããæªåé«ãPerson
- Gen[Person]
ãŸãã å¿
èŠãªåœ±é¿ãç¯å²å
ã§ããã°ã Arbitrary
ãªããžã§ã¯ãã®arbitrary
ã¡ãœããã䜿çšããããšãã§ããŸãã
ãžã§ãã¬ãŒã¿ãŒã«æé»çãªãµããŒãã远å ããŸã
æé»ã®ããšã話ããŠããã®ã§ã arbitrary
ããªãã®ã¿ã€ãã«ã ãŸããåèªäœãå¿
èŠã§ãã
sealed trait LED case object Red extends LED case object Green extends LED case object Blue extends LED
次ã«ããã€ãªãŒãçšã®ãžã§ãã¬ãŒã¿ãŒãäœæããŸãã
val ledGenerator: Gen[LED] = Gen.oneOf(Red, Green, Blue)
ããã§ããžã§ãã¬ãŒã¿ãŒããimplicit
Arbitrary
ã€ã³ã¹ã¿ã³ã¹ãäœæããŸãã
implicit val arbitraryLed: Arbitrary[LED] = Arbitrary(ledGenerator) Arbitrary.arbitrary[LED].sample
ããã§ãã¹ã³ãŒãå
ã«LEDãããã®ã§ãããã€ãã®ããããã£ã確èªã§ããŸãã
val ledProp = forAll { diode: LED =>
倿°ã®ããªããã£ãåãšæšæºã©ã€ãã©ãªã®ã³ã³ããã®å Žåãæé»çãªå€æã¯Arbitrary
ãªããžã§ã¯ãå
ã§ãã§ã«äºåå®çŸ©ãããŠããŸãã
import org.scalacheck.Arbitrary.arbitrary val arbitraryString = arbitrary[String] val arbitraryInteger = arbitrary[Int]
Gen.resultOf
ã¯ããã®åé¡ã§ããªãã倧ãã«å©ããããšãã§ããŸãã ãã®é¢æ°ã¯ã arbitrary
å€ãæ¢ã«å®çŸ©ãããŠããã³ã³ã¹ãã©ã¯ã¿ãŒãã©ã¡ãŒã¿ãŒã«å¯ŸããŠãã±ãŒã¹ã¯ã©ã¹ãåãå
¥ããŸãã
case class Coord(x: Double, y: Double)
sample
æ¹æ³
æ®å¿µãªããã toString
ã¡ãœããã¯Gen
ã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ã«å¯ŸããŠå®çŸ©ãããŠããŸãããããã䟿å©ã§äŸ¿å©ãªã¡ãœããããããŸãã ãžã§ãã¬ãŒã¿ãŒãäœæãããšãã«ã¯ãéåžžã«é »ç¹ã«äœ¿çšããå¿
èŠãããããŸãã ããã¯Gen.sample
ã¡ãœããã§ãã Option
å
ã§çæãããå€ã®äŸãè¿ããŸãã
// ScalaCheck , // 10 . Arbitrary.arbitrary[String].sample map (_ take 10) // . // Some(ïŒ±åæ§éŸî¬èœâ®»æç®ã) Arbitrary.arbitrary[Double].sample // Some(-5.180668081211655E245)
åã®ããŒãã§ãã§ã«èª¬æããããã«ã map
ã¡ãœããã¯ãžã§ãã¬ãŒã¿ãŒã«ãé©çšã§ããŸãã ãããæ¬¡ã®äŸã§èª¬æããŸãã
val octDigitStr = choose(0, 7) map (_.toString) octDigitStr.sample
ãã£ã«ã¿ãªã³ã°
ãžã§ãã¬ãŒã¿ãŒçšã®filter
ã¡ãœããããããŸãããå®éã«ã¯ãããã¯suchThat
ã¡ãœãããåŒã³åºãããã®åãªããšã€ãªã¢ã¹ã§ãã
val evenOct = octDigit.filter(_ % 2 == 0) evenOct.sample // None // , : evenOct.sample // None // , ? evenOct.sample // Some(2)
äžèšã®äŸã¯ã filter
ãsuchThat
䜿çšããªãçç±ã瀺ããŠããŸãã æ°ãããžã§ãã¬ãŒã¿ãŒã¯ããã£ã«ã¿ãŒãééããªãå€ãåã«æåŠããŸãã ããã«ããããã¹ãããã»ã¹ã倧å¹
ã«é
ããªããŸãã
åææ¡ä»¶ã¯ãã£ã«ã¿ãŒãšåæ§ã«æ©èœããŸãã
åææ¡ä»¶
ScalaCheckã®å«ææäœã«ãã£ãŠããžãã¯ã§æç€ºãããåææ¡ä»¶ã¯ãããããã£å
ã§äœ¿çšãããã¡ãœããã§ãã å
¥åãå¶éããããšãã§ããŸãã æŒç®å==>
ã«ãã£ãŠæžãããŸããã åææ¡ä»¶ã䜿çšããã«ã¯ã Prop.propBoolean
ã«è¿œå ããå¿
èŠãããProp.propBoolean
ã ãããã£ãŠãå¶æ°ã®å ŽåãæåŸã®æ¡ãå¶æ°ã«ãªããšããã¹ããŒãã¡ã³ãã確èªããŸãããã
import org.scalacheck.Prop.{forAll, propBoolean} def isEven(number: Int) = number % 2 == 0 // . def lastChar(number: Int) = number.toString.last.toInt // . val p2 = forAll(arbitrary[Int] suchThat isEven) { number => isEven(lastChar(number)) } // . val p1 = forAll(arbitrary[Int]) { number => isEven(number) ==> isEven(lastChar(number)) }
ããããã£ãéå§ããã«ã¯ã check
æ©èœã䜿çšã§ããŸãã
// p1.check // + OK, passed 100 tests. // p2.check // + OK, passed 100 tests.
ãã£ã«ã¿ãŒã硬ãã»ã©ãããå€ãã®å€ãç¡èŠãããŸãã ããã¯ãå€ã®å°ããªã»ãããŸãã¯äºãã«éåžžã«é¢ããŠããå€ã®å Žåã«éèŠã«ãªãããšããããŸãã ããšãã°ãç¯å²Intã®çŽ æ°ã ãã®ãããªåãçµã¿ãããScalaCheckã¯ç°¡åã«ç²ããŠãããªãã«éäŒããããšãã§ããŸãã
scala> p1.check ! Gave up after only 1 passed tests. 100 tests were discarded
å¶æ°ã®äŸã§ã¯ããã«æ°ä»ããªãã§ãããããåçŽãªæ°ã®äŸã§ã¯ç°¡åã§ãã æ¬¡ã®ããšãç¥ã£ãŠããå¿
èŠããããŸãã
å¶æ°ã®ãã£ã«ã¿ãŒã¯ããŸããŸãªæ¹æ³ã§å®è£
ã§ããŸãã ããšãã°ãããªãã¯åãããšãã§ããŸã
ä»»æã®æŽæ°ã§ã2ãæããŸããçŽ æ°ã®å Žå
äºåã«ã«ãŠã³ãããæ¹ãã¯ããã«ç°¡åã§ããããšãã°ã
ãšã©ãã¹ããã¹ã®ãµãã ããããŠãªã¹ããçªãåºã
Gen.oneOf
å
ã®èšç®å€ãããã«ã€ããŠã¯åŸã§èª¬æããŸã
èšäºã
suchThat
ã䜿çšããŠãžã§ãã¬ãŒã¿ãŒãsuchThat
ãåé¡ãçºçããå¯èœæ§ããããŸãã ãã®ãããªå Žåã¯ã retryUtil
ã¡ãœããã䜿çšããå¿
èŠããããŸãã suchThat
ãšã¯ç°ãªããScalaCheckã®åäœãé£ãããªããç¡éã«ãŒãã«é¥ãããšããããŸãã retrtyUtil
ãretrtyUtil
fiter
ãŸãã¯suchThat
䌌ãŠãsuchThat
ïŒ
arbitrary[Int] retryUntil isEven
ãŸãã fromOption
flatten
ãšflatten
ãããã³fromOption
ãDeprecated
ãšå®£èšãããŠããããšã«fromOption
ãããããŸããã ããã¯ã空ã®ãžã§ãã¬ãŒã¿ãŒãäœæããèªæãå°ãªãããããã«è¡ãããŸãã
ç¬èªã®ãžã§ãã¬ãŒã¿ãŒãäœæãã
åè¿°ã®ããã«ãæ¢åã®ãžã§ãã¬ãŒã¿ãŒãçè§£ã®ããã«çµã¿åãããããšã§ãç¬èªã®ãžã§ãã¬ãŒã¿ãŒãäœæã§ããŸãã
val coordGen = for { i <- arbitrary[Int]; j <- arbitrary[Int] } yield (i, j) coordGen.sample // Option[(Int, Int)] = Some((45,60)) coordGen.sample // Option[(Int, Int)] = Some((29, 37))
ä»»æã®ããŒã¿æ§é ã®ãžã§ãã¬ãŒã¿ãŒã宣èšã§ããŸãã ADTã䜿çšããåçŽãªã±ãŒã¹ïŒ
sealed trait LightColor case object Red extends LightColor case object Orange extends LightColor case object Green extends LightColor case object FlashingGreen extends LightColor case object Extinct extends LightColor val colorGen = Gen.oneOf(Red, Orange, Green, Extinct)
人çãè€éã«ããŠãããªãã培åºçã«ïŒ
// , . type Color = LightColor object PedestrianTrafficLight { sealed class State(_1: Color, _2: Color) case object Stop extends State(Red, Extinct) case object Move extends State(Extinct, Green) case object FinishMove extends State(Extinct, FlashingGreen) def states: Seq[State] = Seq(Move, FinishMove, Stop) } object VehicularTrafficLight { sealed class State(_1: Color, _2: Color, _3: Color) case object Stop extends State(Red, Extinct, Extinct) case object Ready extends State(Red, Orange, Extinct) case object Move extends State(Extinct, Extinct, Green) case object Warn extends State(Red, Orange, Extinct) case object FinishMove extends State(Extinct, Extinct, FlashingGreen) def states: Seq[State] = Seq(Stop, Ready, Move, Warn, FinishMove) } sealed trait TrafficLight case class PedestrianTrafficLight(state: PedestrianTrafficLight.State) extends TrafficLight case class VehicularTrafficLight(state: VehicularTrafficLight.State) extends TrafficLight
ãžã§ãã¬ãŒã¿ãŒã宣èšããŸãã
import Gen._ // val pedestrianTrafficLightStateGen = Gen.oneOf(PedestrianTrafficLight.states) // val vehicularTrafficLightStateGen = Gen.oneOf(VehicularTrafficLight.states)
ãããŠãæ©è¡è
ãšäº€éä¿¡å·ããã¿ãã«ãçæããŸãã äžã€ã ããããŸãïŒä¿¡å·æ©ã®ç¶æ
ã¯çžäºã«æä»çã§ãã£ãŠã¯ãªããŸããã ãŸããæ©è¡è
ãæäœã§ããæ¡ä»¶ãæ±ºå®ããŸãã åæã«ãã£ãŠãžã§ãã¬ãŒã¿ãŒãäœæããããã retryUntil
代ããã«suchThat
ã䜿çšããŸãã
val pedestrianCanGo = pedestrianTrafficLightStateGen.retryUntil { state => state != PedestrianTrafficLight.Stop }
次ã«ãä¿¡å·æ©ã®ç¶æ
ãçæããããããå§ããŠãæ©è¡è
ã®èš±å®¹ç¶æ
ãæ±ºå®ãããããããªã¹ãã«çµåããŸãã åãåã£ããžã§ãã¬ãŒã¿ãŒã®ã¿ã€ãã¯ã Gen[(VehicularTrafficLight.State, PedestrianTrafficLight.State)]
ã§ãã
val states = vehicularTrafficLightStateGen flatMap { case vehState @ VehicularTrafficLight.Stop => pedestrianCanGo map (pedState => (vehState, pedState)) case pedestrianCanNotGo => (pedestrianCanNotGo, PedestrianTrafficLight.Stop) }
ãªããžã§ã¯ãèªäœã«ä¿¡å·æ©ã®ã¹ããŒã¿ã¹ã衚瀺ããŸãïŒ
val trafficLightPair = states map { case (v, p) => (VehicularTrafficLight(v), PedestrianTrafficLight(p)) }
çµæã確èªããŸããïŒ ç§ã¯åãåã£ãïŒ
(VehicularTrafficLight(FinishMove),PedestrianTrafficLight(Stop))
ãããŠ
(VehicularTrafficLight(Move),PedestrianTrafficLight(Stop))
ããã¯å
šãæ¬åœã§ãã å€åã©ããç§ãééã£ãŠããã äž»ãªããšã¯ãã¡ã«ããºã èªäœãå®èšŒããããšã§ããã
ScalaCheckã§ã¯ãååž°çãªããŒã¿æ§é ãçæããããšãã§ããŸãã
ãã ãããã®ããã»ã¹ãç°¡åãã€äºçްãªããšãšåŒã¶ããšã¯å°é£ã§ãã ããã«ããã§
ãã®èšäºã§ã¯ãååž°ãžã§ãã¬ãŒã¿ãŒãšããã®åé¡ã«ã€ããŠèŠãŠãããŸãã
ãããã䜿çšãããšãã«ééãããããããŸããã
ããããã£ã®ãžã§ãã¬ãŒã¿ãŒ
åè¿°ã®ã»ãšãã©ã®äŸã§ã¯ãScalaCheckã¯ãžã§ãã¬ãŒã¿ãŒã®é©åãªã€ã³ã¹ã¿ã³ã¹ãåå¥ã«éžæããããã䜿çšããŠããããã£ãèšç®ããŸãã ãã ãããžã§ãã¬ãŒã¿ãŒãç¬èªã«äœæããã®ã¯ãã®ããã§ã¯ãªããScalaCheckã¯ã¹ã³ãŒãããäœããåé€ããŸãã ãäºææ§ã®ãããä¿¡å·æ©ãèŠããŠããŸããïŒ ããããã©ããã«ããã·ã¥ããŸãããïŒ
import Prop.{forAll, propBoolean} def isRed(trafficLight: VehicularTrafficLight) = trafficLight.state == VehicularTrafficLight.Stop def notRed(trafficLight: PedestrianTrafficLight) = trafficLight.state != PedestrianTrafficLight.Stop // Prop.forAll val canNotBothBeRed = forAll(trafficLightPair) { case (vehicular, pedestrian) => isRed(vehicular) ==> notRed(pedestrian) }
ãã§ãã¯ããŠã¿ãŠïŒ
canNotBothBeRed.check
ãããŠããã¹ãŠãæ£åžžã§ããããšã確èªããŸãã
+ OK, passed 100 tests.
å€ãã®å Žåã1ã€ã®ãžã§ãã¬ãŒã¿ãŒã§ã¯ååã§ã¯ãªããããè€æ°ã®ãžã§ãã¬ãŒã¿ãŒã䜿çšã§ããŸãã
val p = forAll(Gen.posNum[Int], Gen.negNum[Int]) { (pos, neg) => neg < pos }
ãžã§ãã¬ãŒã¿ãŒãªã©ã®ããããã£ã¯ãäžç·ã«ãã¹ãã§ãããããäžèšã®äŸã次ã®ããã«æžãæããããšãã§ããŸãã
val p = forAll(Gen.posNum[Int]) { pos => forAll(Gen.negNum[Int]) { neg => neg < pos } }
ãã¹ããããforAll
åŒã³åºãã®ä»£ããã«ã䜿çšãããžã§ãã¬ãŒã¿ãŒããã¿ãã«ãã³ã³ãã€ã«ããããšãã§ããŸãã ãŸãã forAll
2ååŒã³åºããªãã§ãã ããã
çºé»æ©ã®ã©ãã«
ã¿ã°ã䜿çšããããšããå§ãããŸãã ããã«ããããšã©ãŒå ±åãæ¹åããããžã§ãã¬ãŒã¿ãŒã䜿çšããã³ãŒãã®å¯èªæ§ãåäžããŸãã ã©ãã«ã远å ããã«ã¯ã |:
ããã³:|
䜿çšã§ããŸã:|
ã ã©ãã«ã¯ãæååãŸãã¯æåã®ããããã§ãã è€æ°ã®ã¿ã°ããžã§ãã¬ãŒã¿ã«è¿œå ã§ããŸãã 説æããããã«ãåã®äŸã䜿çšããŠã èšå·ã倿Žããããããã£ãäžæ¡çã«ããŸãã
// |: :| . val p = forAll('positive |: Gen.posNum[Int]) { pos => forAll(Gen.negNum[Int] :| "negative numbers") { neg => neg > pos } }
åæããŠãè¯ããªã£ãïŒ
! Falsified after 0 passed tests. > positive: 0 > positive_ORIGINAL: 1 > negative numbers: 0
ããªããã£ããžã§ãã¬ãŒã¿ãŒ
宿°
Gen.const
ãããç°¡åãªãã®ãGen.const
ã¯Gen.const
ã§ãã ä»»æã®å€ãåãããžã§ãã¬ãŒã¿ãŒã«æ³šææ·±ãããã¯ããŸãã é©åãªã¿ã€ãã³ã°ã§é©åãªå Žæã«ãããªããžã§ã¯ãã¯ãæé»çã«Gen
ãã£ã¹ããããŸãGen
ãããã£ãŠãã»ãšãã©ã®å Žåããã®ã¡ãœãããæç€ºçã«åŒã³åºãå¿
èŠã¯ãããŸããã
æ»ã¬
ScalaCheckã¯ãå®è¡äžå¯èœãªãžã§ãã¬ãŒã¿ãŒãè¿ãGen.fail
ã¡ãœããã䜿çšããŸãã sample
ã¡ãœãããåŒã³åºãããšãããšãåžžã«None
ãŸãã ã»ãšãã©ã®å Žåã圌ã¯ããªãã®æ¹æ³ã§äŒãããšã¯ãããŸããã圌ãäŒã£ãå Žåãããªãã¯åœŒã«ç²ŸéããŠããããšãèæ
®ããŠãã ããïŒ
Gen.fail.sample // Option[Nothing] = None
æ°å
Gen.posNum
ãšGen.negNum
ã䜿çšããŠãããããæ£ã®æ°ãšè² ã®æ°ãçæã§ããŸãã
import org.scalacheck.Gen import org.scalacheck.Prop.forAll val negative = Gen.negNum[Int] val positive = Gen.posNum[Int] val propCube = forAll (negative) { x => x * x * x < 0 }
Gen.chooseNum
ã«ã¯è峿·±ãæ©èœããããŸãïŒãã®ãžã§ãã¬ãŒã¿ãŒã¯ãæå®ãããç¯å²ïŒå
æ¬çïŒã§ããŒãïŒæå®ãããç¯å²å
ã«åãŸãå ŽåïŒãæå°å€ãšæå€§å€ãããã³æç€ºãããå€ã®ãªã¹ãã®éã¿ã§æ°å€ãçæããŸãïŒ
Gen.choose
ã䜿çšããŠãç¹å®ã®ç¯å²å
ã®æ°å€ãçæã§ããŸãã ããã«ãããã¯æ±ºããŠå€±æããªããŸããªã¿ã€ãã®ãžã§ãã¬ãŒã¿ãŒã§ãã ã·ã³ãã«ã§ã䜿çšã§ããŸãã ãã£ã©ã¯ã¿ãŒãžã§ãã¬ãŒã¿ãŒãšããã°...
ãã£ã©ã¯ã¿ãŒ
ScalaCheckã«ã¯å€ãã®æåãžã§ãã¬ãŒã¿ãŒããããŸãã æ¬¡ããéžæããããã«æåŸ
ãããŸãã
Gen.alphaUpperChar
Gen.alphaLowerChar
Gen.alphaChar
Gen.numChar
Gen.alphaNumChar
ããã§ã¯ããæµ·æŠãã§ã²ãŒã ã®åº§æšãçæããŠã¿ãŸãããã
val coord = for { letter: Char <- Gen.alphaUpperChar number: Char <- Gen.numChar } yield s"$letter$number" coord.sample
çè§£ã®ãããã§ããªã¹ããã¿ãã«ãæååãªã©ã®ä»»æã®éèšãçæã§ããŸãã è¡ãšããã°...
è¡
ç°¡åã«çæããããšãã§ããŸãã Gen.alphaStr
ã¯ãã¢ã«ãã¡ãããæåããã®ã¿æååãçæããŸãã Gen.numStr
ã¯æ°å€æååãçæããŸãã Gen.alphaLowerStr
ãšGen.alphaUpperStr
ãç°ãªãæåããæååãåå¥ã«çæããããšãã§ããŸãGen.alphaLowerStr
ãšGen.alphaUpperStr
ã¯ããããã®ç®çã®ããã«èšèšãããŠããŸãã Gen.idenifier
ã¯ãåžžã«å°æåã®ã¢ã«ãã¡ãããæåã§å§ãŸãããã®åŸã«è±æ°åãç¶ã空ã§ãªãæååãæäŸããŸãã äžéšã®ææ³ã§ã¯ãããã¯éåžžã«èå¥åã§ãã
import org.scalacheck.Gen val stringsGen = for { key <- Gen.identifier value <- Gen.numStr } yield Bucket(key take 8, value take 2) stringsGen.sample
æ©èœ
Scalacheckã¯é¢æ°ïŒ Function0
ã€ã³ã¹ã¿ã³ã¹ïŒ () => T
ïŒãçæã§ããŸãã ãããè¡ãã«ã¯ãæ»ãå€ãçæãããžã§ãã¬ãŒã¿ãŒãGen.function0
ãŸãã
val f = Gen.function0(Arbitrary.arbitrary[Int]).sample // tostring , - : // some(org.scalacheck.gen$$$lambda$40/1418621776@4f7d0008)
ã³ã³ããçºé»æ©
arbitrary
ã䜿çšããŠãæšæºã³ã¬ã¯ã·ã§ã³ã®ã€ã³ã¹ã¿ã³ã¹ãçæã§ããŸãã
import Arbitrary.arbitrary val listgen = arbitrary[List[Int]] val optgen = arbitrary[Option[Int]]
ããããããã¯å€ãã®å Žåååã§ã¯ãªããããScalaCheckã¯ã³ã¬ã¯ã·ã§ã³ãšãã®çæãæäœããããã®é«åºŠãªããŒã«ãæäŸããŸãã æ¬¡ã«ã sample
ã¡ãœããã«ãã£ãŠè¿ãããOption
ãçç¥ãã誀解ãæããªãããã«ãããã«å€ã衚瀺ããŸãã
çæãªãã·ã§ã³
Gen.some
ã䜿çšãããšããåå
¥ããä¿èšŒãããŸãã
// : Gen.some("") // Some()
ããã«æªãããšã«ããéã«è¿œå ã®èªç±åºŠãããå ŽåïŒ
// . Gen.option("") // None
ãªã¹ããšèŸæžãçæããŸã
Gen.listOf
ã¯ä»»æã®é·ãã®ãªã¹ããçæãã Gen.listOfN
ã¯æå®ãããé·ãã®ãªã¹ããçæããŸãã
// 3 Gen[Int]. Gen.listOf(3) map (_ take 5) // List(3, 3, 3, 3, 3) // . Gen.listOfN(5, Gen.posNum[Double]) map (_ take 5)
Gen.listOf
ãžã§ãã¬ãŒã¿ãŒã¯ç©ºã®ãªã¹ããè¿ãå ŽåããããŸãã 空ã§ãªããªã¹ããå¿
èŠã§ããããšãä¿èšŒãããŠããå Žåã¯ã Gen.nonEmptyListOf
ã䜿çšã§ããŸãã èŸæžãŸãã¯ãããïŒ Map
ïŒãçæããã«ã¯ãåæ§ã®ã¡ãœããããããŸãïŒ Gen.mapOf
ã Gen.mapOfN
ãããã³Gen.nonEmptyMapOf
ã§ãã ãªã¹ãã¡ãœãããšã¯ç°ãªããèŸæžãžã§ãã¬ãŒã¿ãŒã«ã¯ã2èŠçŽ ã®ã¿ãã«ãžã§ãã¬ãŒã¿ãŒãå¿
èŠã§ãã
import Arbitrary._ val tupleGen = for { i <- arbitrary[Short] j <- arbitrary[Short] } yield (i, j) Gen.mapOfN(3, tupleGen) map (_ take 3)
ç¹å®ã®ã»ããã®èŠçŽ ã®ãªã¹ããçæããŸã
Gen.someOf
ã¯ãæå®ããã»ããã«å«ãŸããç¹å®ã®èŠçŽ ã»ããããArrayBuffer
ãè¿ããŸããæ¬¡ã«äŸã瀺ããŸãã
import org.scalacheck.Gen.someOf val numbers = someOf(List(1, 2, 3, 4, 5)).sample
Gen.pick
ãšåæ§ã«Gen.someOf
ãŸãã å¯äžã®éãã¯ã Gen.pick
䜿çšãããšãå¿
èŠãªèŠçŽ æ°ãæå®ã§ããããšã§ãã
import org.scalacheck.Gen.pick val lettersGen = Gen.pick(2, List('a', 'e', 'i', 'o', 't', 'n', 'm')).sample
ã·ãŒã±ã³ã¹ãçæãã
Gen.sequence
ã¯ãåãå
¥ããããå€ã®ã·ãŒã±ã³ã¹ã«åºã¥ããŠArrayList
ãäœæããŸãã æäŸããããžã§ãã¬ãŒã¿ãŒã®å°ãªããšã1ã€ã該åœããå Žåãã·ãŒã±ã³ã¹å
šäœã該åœããŸãã
import Gen.{const, choose} val ArrayListGen = Gen.sequence(List(const('a'), const('b'), choose('c', 'd')))
ç¡éã®ã¹ããªãŒã ãçæããŸã
ScalaCheckã¯ãç¡éã¹ããªãŒã ãçæããæ©èœããµããŒãããŠããŸãã
val stream = Gen.infiniteStream(Gen.choose(0,1))
ã³ã³ããçºé»æ©
èŸæžãšãªã¹ãã®äžèšã®ã¡ãœããã¯ãå®éã«ã¯ã Gen.containerOf
ãšãã®ããŒãããŒã䜿çšããç¹æ®ãªã±ãŒã¹ã§ãïŒ containerOfN
ãšnonEmptyContainerOf`ã ããã¯ãç§ãã¡ãç¥ã£ãŠããã»ãšãã©ã®ã³ã¬ã¯ã·ã§ã³ãçæã§ããæãäžè¬çãªåœ¢åŒã§ãã æ¬¡ã®äŸãèŠãŠã¿ãŸãããã
import Arbitrary._ // «» . val prettyShortSeq = Gen.containerOfN[Seq, Short](3, arbitrary[Short]) // Vector(0, -24114, 32767) // : . val genNonEmptyList = Gen.nonEmptyContainerOf[Map[K, V], (K, V)] (oneOf("foo", "bar"))
containerOf
äœæããããžã§ãã¬ãŒã¿ãŒã¯ãåã§ã¯ãªãæœè±¡åã§äœæãããŸãã containerOf
ã¡ãœããã®ã·ã°ããã£ãèŠãŠã¿ãŸãããã
def containerOf[C[_],T](g: Gen[T])(implicit evb: Buildable[T,C[T]], evt: C[T] => Traversable[T] ): Gen[C[T]] =
ãããŠãã®å®è£
ã«ã€ããŠïŒ
buildableOf[C[T],T](g)
ãããã£ãŠããªã¹ããŸãã¯* â¶ *
ãšããŠè¡šãããšãã§ããäœããçæããå¿
èŠãããå Žåã containerOf
ã圹ç«ã¡ãŸãã ãããŠã * â¶ * â¶ *
ãããªãã®ïŒããšãã°Map
ïŒãçæããå¿
èŠãããå Žåã¯ã * â¶ * â¶ *
å®è£
ã§èŠãããšãã§ããããã«æœè±¡çãªã¡ãœããã䜿çšããå¿
èŠããããŸãã
def mapOf[T,U](g: => Gen[(T,U)]) = buildableOf[Map[T,U],(T,U)](g)
container
ã¡ãœãããšåæ§ã«ãã¡ãœããnonEmptyBuildableOf
ã nonEmptyBuildableOf
ããã³nonEmptyBuildableOf
ãŸãã éåžžãScalacheckã¯ãæž¡ãããã³ã¬ã¯ã·ã§ã³ãåãšããŠæ§ç¯ããæ¹æ³ã決å®ããŸãã ãããè¡ãããã«ãã¿ã€ãorg.scalacheck.util.Buildable
æé»çãªã€ã³ã¹ã¿ã³ã¹ã䜿çšããŸãã ãã®ãããªã€ã³ã¹ã¿ã³ã¹ã¯ããã¹ãŠã®æšæºã³ã¬ã¯ã·ã§ã³ã¿ã€ãã®ScalaCheckã§å®£èšãããŸãã Arbitrary
ã€ã³ã¹ã¿ã³ã¹ãšåæ§ã«ãã³ã¬ã¯ã·ã§ã³ãå®è£
ããŠcontainerOf
ãµããŒããååŸããã®ã¯ç°¡åã§ãã
é«ãçºé»æ©
芪æãªãèªè
ã®çããã é«éã®æ©èœã¯äœãç¥ã£ãŠãããšæããŸãã ãžã§ãã¬ãŒã¿ãŒã«ãåæ§ã®åäœããããŸãããžã§ãã¬ãŒã¿ãŒã¯ãä»ã®ãžã§ãã¬ãŒã¿ãŒãåŒæ°ãšããŠåãåããä»ã®ãžã§ãã¬ãŒã¿ãŒãçæã§ããŸãã ãŸãã«äŸå€ãé€ããŠã以åã«æ€èšããã³ã³ãããŒãžã§ãã¬ãŒã¿ãŒã髿¬¡ãžã§ãã¬ãŒã¿ãŒã§ãã
å€ãã®äžã€
Gen.oneOf
ã¯2ããN
ãžã§ãã¬ãŒã¿ãŒãåãåãããšãã§ããããã«ãã£ãŠæ°ãããžã§ãã¬ãŒã¿ãŒãçæããŸãã
import Gen.{oneOf, const, choose} // Gen[T] val dogies = oneOf("Lucy", "Max", "Daisy", "Barney") // val windows = oneOf(choose(1, 8), const(10))
oneOf
ããªã¹ããªã©ã®scala.collection.Seq
æž¡ãããšãã§ããŸãã
åšæ³¢æ°çºçåš
Gen.frequency
ã¯ãå
¥åãšããŠã¿ãã«ã®ãªã¹ããåãå
¥ããŸãã ããããããžã§ãã¬ãŒã¿ãŒãšãã®ç¢ºççéã¿ã§æ§æãããŸãã åºåã¯ãæž¡ãããæŽæ°å€ã確çã®éã¿ãšããŠäœ¿çšããæ°ãããžã§ãã¬ãŒã¿ãŒã§ãã
val russianLettersInText = Gen.frequency ( (9, ''), (9, ''), (8, ''), (7, ''), (6, '')
ã¬ã€ãžãŒãžã§ãã¬ãŒã¿ãŒ
Gen.lzy
ã䜿çšãããšãæ¬åœã«å¿
èŠã«ãªããŸã§çæãé
ããŸãã åæãžã§ãã¬ãŒã¿ãŒããASTãªã©ã®ååž°çãªããŒã¿æ§é ã®çæã«éåžžã«åœ¹ç«ã¡ãŸãã Gen.lzy
ã䜿çšããå Žåãèšç®ã¯1åå®è¡ãããŸãã Gen.delay
èšç®ãGen.delay
ããæ¯åå®è¡ãããŸãã
çºé»æ©ãµã€ãº
Gen.size
ã¯ãå¯äžã®ãã©ã¡ãŒã¿ãŒãšããŠã©ã ããåãããã©ã¡ãŒã¿ãŒãšããŠæŽæ°ãåããŸãã ãã®æ°å€ã¯ãScalaCheckãå®è¡æã«ç€ºããµã€ãºã§ãã Gen.resize
䜿çšGen.resize
ãšãå¿
èŠã«å¿ããŠãžã§ãã¬ãŒã¿ãŒã®ãµã€ãºãèšå®ã§ãGen.resize
ã ãããæ¬¡ã®äŸã§èª¬æããŸãã
def genNonEmptySeq[T](genElem: Gen[T]): Gen[Seq[T]] = Gen.sized { size => for { listSize <- Gen.choose(1, size) list <- Gen.containerOfN[Seq, T](listSize, genElem) } yield list } val intVector = genNonEmptySeq(Arbitrary.arbitrary[Int]) val p = Prop.forAll(Gen.resize(5, intVector)) { list => list.length <= 5 }
ãã§ãã¯ïŒ
p.check
Gen.resize
ã¯ãæ¢åã®Gen.resize
ãããã®ã«åºã¥ããŠæ°ãããžã§ãã¬ãŒã¿ãŒãäœæãGen.resize
ã ããã¯ãååž°ãžã§ãã¬ãŒã¿ãŒãäœæãããšããããã³åæã䜿çšããŠåçŽãªãžã§ãã¬ãŒã¿ãŒããè€éãªãžã§ãã¬ãŒã¿ãŒãäœæãããšãã«äŸ¿å©ã§ãã
ãã©ã¯ã¿ã«ãžã§ãã¬ãŒã¿
å€ãã®å Žåãååž°çãªããŒã¿æ§é ãã€ãŸãASTã䜿çšããå¿
èŠããããŸãã . , , , . :
trait IntTree case class Leaf (value: Int) extends IntTree case class Node (children: Seq[IntTree]) extends IntTree
:
import org.scalacheck.Gen._ def treeGen: Gen[IntTree] = oneOf(leafGen, nodeGen) def leafGen: Gen[Leaf] = arbitrary[Int] map (value => Leaf(value)) def nodeGen: Gen[Node] = listOf(treeGen) map (children => Node(children))
:
treeGen.sample Exception in thread "main" java.lang.StackOverflowError at org.scalacheck.ArbitraryLowPriority$$anon$1.arbitrary(Arbitrary.scala:70) at org.scalacheck.ArbitraryLowPriority.arbitrary(Arbitrary.scala:74) at org.scalacheck.ArbitraryLowPriority.arbitrary$(Arbitrary.scala:74) at org.scalacheck.Arbitrary$.arbitrary(Arbitrary.scala:61)
treeGen
. . . treeGen
:
def treeGen: Gen[IntTree] = lzy(oneOf(leafGen, nodeGen))
:
treeGen.sample // Some(Leaf(857998833)) // Some(Leaf(2147483647)) // Some(Leaf(489549235))

Exception in thread "main" java.lang.StackOverflowError at org.scalacheck.rng.Seed.next(Seed.scala:17) at org.scalacheck.rng.Seed.long(Seed.scala:39) at org.scalacheck.Gen$Choose$.org$scalacheck$Gen$Choose$$chLng(Gen.scala:309) at org.scalacheck.Gen$Choose$$anon$5.$anonfun$choose$1(Gen.scala:358) at org.scalacheck.Gen$$anon$3.doApply(Gen.scala:254) at org.scalacheck.Gen.$anonfun$map$1(Gen.scala:75) at org.scalacheck.Gen$$anon$3.doApply(Gen.scala:254) at org.scalacheck.Gen.$anonfun$flatMap$2(Gen.scala:80) at org.scalacheck.Gen$R.flatMap(Gen.scala:242) at org.scalacheck.Gen$R.flatMap$(Gen.scala:239)
, , . . Gen.sized
Gen.resize
:
def nodeGen: Gen[Node] = sized { size => choose(0, size) flatMap { currSize => val nGen = resize(size / (currSize + 1), treeGen) listOfN(currSize, nGen) map (child => Node(child)) } }
:
val nGen = resize(size / (currSize + 1), treeGen)
ããå°ããªãµã€ãºã®æ°ãããžã§ãã¬ãŒã¿ãŒãäœæããŸãïŒãã¹ãã®ã¬ãã«ã«æ¯äŸããŠãµã€ãºãçž®å°ãããŸããç¹å®ã®Nã«å¯ŸããŠãµã€ãº0ã®ç©ºã®ãžã§ãã¬ãŒã¿ãŒãäœæãããã¹ã¿ãã¯ãªãŒããŒãããŒã¯çºçããŸããããžã§ãã¬ãŒã¿ãŒã¯ããã¹ãã®ã¬ãã«ãããããªããããæ¯åãžã§ãââã¬ãŒã¿ãŒã®ãµã€ãºãå°ããããå¿
èŠããããŸãã
ããã§ãååž°çãªãžã§ãã¬ãŒã¿ãŒãèŠã€ããŸãããJSONã®ASTçæã®äŸã¯ãEric TorreborreïŒspecs2ã®äœæè
ïŒããã°ã«ãããŸãã
ããã§ããžã§ãã¬ãŒã¿ãŒãšã®é¢ä¿ãçµäºããããããã£ã«é²ã¿ãŸãããããã®è©³çްã«ã€ããŠã¯ãã·ãªãŒãºã®æ¬¡ã®èšäºã§èª¬æããŸããããããïŒ