SlideShare a Scribd company logo
2TQRGTV[$CUGF6GUVKPI 
YKVJ5ECNC%JGEM 
CXKF)CNKEJGV 
(TGGNCPEG(WPEVKQPCN2TQITCOOGT 
6YKVVGTFICNKEJGV
5EJGFWNG 
 .KOKVCVKQPUQHVTCFKVKQPCNVGUVKPIVGEJPKSWGU 
 (KTUVGZCORNGQH2TQRGTV[$CUGF6GUVKPIYKVJ5ECNC%JGEM 
 6GUVECUGIGPGTCVKQP 
 GHKPKPICRTQITCORTQRGTVKGU 
 +PVTQFWEKPI#NIGDTCKEGUKIP 
 6JGECUGQH/QPQKF
1RVKQPUVQEJGEMEQTTGEVPGUUQH 
CRTQITCO 
ō 6GUVTKXGPGXGNQROGPVVGEJPKSWGU
Z7PKVŎ 
ō $GJCXKQTTKXGPGXGNQROGPV 
ō 2TQRGTV[$CUGF6GUVKPI 
ō 6[RG TKXGP GXGNQROGPV GRGPFGPV 6[RGU 
6JGQTGO 2TQXGTU 2CTCOGVTKEKV[ 
6JGQTGOU HQT 
(TGGŎ
6GUVTKXGPGXGNQROGPV 
ō #RTQITCOKUXGTKHKGFD[UGXGTCNWPKVVGUVU 
ō 2TQITCOCPFVGUVUCTGFGXGNQRGFKVGTCVKXGN[ 
ō 6GUVU CTG EQPETGVG GZCORNGU QH JQY C RTQITCO 
UJQWNFRGTHQTOKPCRCTVKEWNCTUKVWCVKQP 
ō 6JG[FQPņVIKXGCUUWTCPEGVJCVVJGQXGTCNNDGJCXKQT 
QHCRTQITCOKUEQXGTGF
$GJCXKQTTKXGPGXGNQROGPV 
ō 5RGEKHKECVKQPU CTG FGHKPGF WUKPI C PCVWTCN 
HQTOCNKUO VJCV KU GZGEWVCDNG CPF ECP XGTKH[ C 
RTQITCO 
ō 6GUVU OWUV DG GZJCWUVKXG VQ EQXGT VJG QXGTCNN 
RTQITCODGJCXKQT
2TQRGTV[$CUGF6GUVKPI 
ō 2TQRGTV[$CUGF6GUVKPICNNQY[QWVQFGUETKDG[QWT 
RTQITCO RTQRGTVKGU NGVVKPI VJG WPFGTN[KPI 
HTCOGYQTM IGPGTCVG VGUV ECUGU CPF XGTKH[ 
RTQRGTVKGU 
ō #RTQRGTV[KUCPCDUVTCEVURGEKHKECVKQP 
ō )GPGTCVGFVGUVECUGKPENWFGGFIGECUGU 
ō %QXGTCIGKUJKIJGTVJCPVTCFKVKQPCNVGUVU
6TCFKVKQPCNVGUVUNKOKVCVKQPU 
6GUVGF1- 
0QVVGUVGF$TGCMU 
2TQITCOQOCKP
6TCFKVKQPCNVGUVUNKOKVCVKQPU 
6GUVGF1- 
0QVVGUVGF$TGCMU 
2TQITCOQOCKP
5EJGFWNG 
 .KOKVCVKQPUQHVTCFKVKQPCNVGUVKPIVGEJPKSWGU 
 (KTUVGZCORNGQH2TQRGTV[$CUGF6GUVKPIYKVJ5ECNC%JGEM 
 6GUVECUGIGPGTCVKQP 
 GHKPKPICRTQITCORTQRGTVKGU 
 +PVTQFWEKPI#NIGDTCKEGUKIP 
 6JGECUGQH/QPQKF
5ECNC%JGEM 
ō #2TQRGTV[$CUGF6GUVKPIHTCOGYQTM 
ō #2+HQTCWVQOCVKEVGUVECUGIGPGTCVKQP 
ō #2+HQTRTQRGTV[FGHKPKVKQP 
ō 2TQRGTV[EJGEMKPITWPVKOGKPENWFKPI6GUV%CUG 
5KORNKHKECVKQP 
ō +PVGITCVKQPYKVJVGUVHTCOGYQTMU
UWEJCU5RGEUQT 
5ECNC6GUV
5ECNC%JGEMKUIQQFHQTŎ 
ō EJGEMKPIEQTTGEVPGUUQHCRTQITCO 
ō TGITGUUKQPEJGEMKPI 
ō RTQXKPICNIGDTCKE.CYU 
ō VGUVKPIYKVJNGUUEQFG 
ō KPXGUVKICVGRTQRGTV[HCKNWTGU
(KTUVGZCORNG 
val propMax = Prop.forAll { (x: Int, y: Int) = 
val z = math.max(x, y) 
(z == x || z == y)  (z = x  z = y) 
} 
propMax.check 
+ OK, passed 100 tests.
(KTUVGZCORNG 
7PKXGTUCN3WCPVKHKECVKQP∀ 
val propMax = Prop.forAll { (x: Int, y: Int) = 
val z = math.max(x, y) 
(z == x || z == y)  (z = x  z = y) 
} 
propMax.check 
+ OK, passed 100 tests.
(KTUVGZCORNG 
#DUVTCEVFGHKPKVKQPQH+PRWVU 
7PKXGTUCN3WCPVKHKECVKQP∀ 
val propMax = Prop.forAll { (x: Int, y: Int) = 
val z = math.max(x, y) 
(z == x || z == y)  (z = x  z = y) 
} 
propMax.check 
+ OK, passed 100 tests.
(KTUVGZCORNG 
#DUVTCEVFGHKPKVKQPQH+PRWVU 
val propMax = Prop.forAll { (x: Int, y: Int) = 
val z = math.max(x, y) 
(z == x || z == y)  (z = x  z = y) 
} 
propMax.check 
+ OK, passed 100 tests. 
%QORNGVGFGHKPKVKQPQHOCZ 
7PKXGTUCN3WCPVKHKECVKQP∀
(KTUVGZCORNG 
#DUVTCEVFGHKPKVKQPQH+PRWVU 
val propMax = Prop.forAll { (x: Int, y: Int) = 
val z = math.max(x, y) 
(z == x || z == y)  (z = x  z = y) 
} 
propMax.check 
+ OK, passed 100 tests. 
%QORNGVGFGHKPKVKQPQHOCZ 
7PKXGTUCN3WCPVKHKECVKQP∀ 
VGUVUJCXGDGGPTWP
5EJGFWNG 
 .KOKVCVKQPUQHVTCFKVKQPCNVGUVKPIVGEJPKSWGU 
 (KTUVGZCORNGQH2TQRGTV[$CUGF6GUVKPIYKVJ5ECNC%JGEM 
 6GUVECUGIGPGTCVKQP 
 GHKPKPICRTQITCORTQRGTVKGU 
 +PVTQFWEKPI#NIGDTCKEGUKIP 
 6JGECUGQH/QPQKF
6GUVECUGIGPGTCVKQP 
ō 5ECNC%JGEMRTQXKFGUIGPGTCVQTUVQFGHKPGCDUVTCEVVGUVECUGU 
ō 6JGUG IGPGTCVQTU CTG WUGF VQ TCPFQON[ ETGCVG EQPETGVG VGUV 
ECUGU 
ō )GP=6? FGHKPKVKQP KU SWKVG UKORNG # IGPGTCVQT GXGPVWCNN[ 
TGVWTPUCXCNWGQHV[RG6 
class Gen[+T] { 
def apply(prms: Gen.Params): Option[T] 
} 
%QPVCKPU4CPFQO)GPGTCVQT 
WUGFVQIGPGTCVGCTCPFQO6
7UKPICIGPGTCVQT 
)GP=6?TGVWTPUCP1RVKQP=6? 
Gen.choose(0, 100).sample 
res0: Option[Int] = Some(89) 
Prop.forAll(Gen.choose(0, 100)) ( _ = 100 ).check 
+ OK, passed 100 tests. 
)GPGTCVQTKURCUUGFGZRNKEKVN[
5ECNC%JGEM)GP 
5ECNC%JGEMFGHKPGUCNCTIGUGVQH)GPGTCVQTU 
scala Gen. 
alphaChar fail nonEmptyContainerOf sequence 
alphaLowerChar freqTuple nonEmptyListOf size 
alphaNumChar frequency nonEmptyMap sized 
alphaStr identifier numChar someOf 
alphaUpperChar isInstanceOf numStr toString 
asInstanceOf listOf oneOf uuid 
choose listOf1 option value 
chooseNum listOfN parameterized wrap 
const lzy pick zip 
containerOf mapOf posNum 
containerOf1 mapOfN resize 
containerOfN negNum resultOf
Custom Generators 
)GPKUC/QPCFCPFECPDGWUGFKPHQTEQORTGJGPUKQP 
val personGenerator = for { 
name - Gen.alphaStr 
age - Gen.choose(0, 150) 
} yield Person(name, age) 
Prop.forAll(personGenerator :| Person) { p = 
p.toString ?= sPerson(${p.name},${p.age}) 
} 
case class Person(name: String, age: Int)
1VJGTUCORNGUQH%WUVQO 
)GPGTCVQT 
#IGPGTCVQTECPFGRGPFHTQOXCNWGQHCPQVJGTQPG 
NKMGKPVJGHQNNQYKPIGZCORNG 
for { 
s - Arbitrary.arbitrary[String] 
index - Gen.choose(0, s.length) 
} yield (s, index)
9GKIJVGFIGPGTCVQTYKVJ 
HTGSWGPE[ 
val even = Gen.posNum[Int].suchThat(_ % 2 == 0) 
val odd = Gen.posNum[Int].suchThat(_ % 2 == 1) 
val number = Gen.frequency((2, even), (4, odd), (1, 0)) 
Prop.forAll(number) { i = 
val label = 
if (i == 0) zero 
else if (i % 2 == 0) even 
else odd 
Prop.collect(label)(true) 
}.check(1000) 
+ OK, passed 1000 tests. 
 Collected test data: 
57% odd 
29% even 
14% zero
9GKIJVGFIGPGTCVQTYKVJ 
HTGSWGPE[ 
GHKPGYGKIJVHQTGCEJ)GPGTCVQT 
val even = Gen.posNum[Int].suchThat(_ % 2 == 0) 
val odd = Gen.posNum[Int].suchThat(_ % 2 == 1) 
val number = Gen.frequency((2, even), (4, odd), (1, 0)) 
Prop.forAll(number) { i = 
val label = 
if (i == 0) zero 
else if (i % 2 == 0) even 
else odd 
Prop.collect(label)(true) 
}.check(1000) 
+ OK, passed 1000 tests. 
 Collected test data: 
57% odd 
29% even 
14% zero
9GKIJVGFIGPGTCVQTYKVJ 
HTGSWGPE[ 
GHKPGYGKIJVHQTGCEJ)GPGTCVQT 
val even = Gen.posNum[Int].suchThat(_ % 2 == 0) 
val odd = Gen.posNum[Int].suchThat(_ % 2 == 1) 
val number = Gen.frequency((2, even), (4, odd), (1, 0)) 
Prop.forAll(number) { i = 
val label = 
if (i == 0) zero 
else if (i % 2 == 0) even 
else odd 
Prop.collect(label)(true) 
}.check(1000) 
+ OK, passed 1000 tests. 
 Collected test data: 
57% odd 
29% even 
14% zero 
GHKPGCNCDGNHQTGCEJ 
MKPFQHXCNWG
)GPGTCVGCNKUV 
sealed trait Coin 
case object Head extends Coin 
case object Tail extends Coin 
#TDKVTCT[UKGFNKUVQHCoin 
val coin = Gen.oneOf(Head, Tail) 
(KZGFUKGFNKUVQHCoin 
val coins = Gen.listOf(coin) 
val threeCoins = Gen.listOfN(3, coin) 
scala coins.sample 
res1: Option[List[Coin]] = Some(List(Head, Tail, Head, Tail, …)) 
scala threeCoins.sample 
res2: Option[List[Coin]] = Some(List(Head, Head, Tail))
5EJGFWNG 
 .KOKVCVKQPUQHVTCFKVKQPCNVGUVKPIVGEJPKSWGU 
 (KTUVGZCORNGQH2TQRGTV[$CUGF6GUVKPIYKVJ5ECNC%JGEM 
 6GUVECUGIGPGTCVKQP 
 GHKPKPICRTQITCORTQRGTVKGU 
 +PVTQFWEKPI#NIGDTCKEGUKIP 
 6JGECUGQH/QPQKF
2TQITCORTQRGTVKGU 
ō 5ECNC%JGEMIKXGUCDKNKV[VQFGHKPGVJGGZRGEVGF 
DGJCXKQTQHCRTQITCOKPCRTQITCOOCVKEYC[ 
ō 6JGRTQRGTV[QHCRTQITCOKUEQORQUGFQHVYQ 
VJKPIU 
C VJGFQOCKPQHVJGRTQITCO
HWPEVKQPWPFGTVGUV 
D CPCUUGTVKQPVJCVVJGRTQITCOOWUVXGTKH[ 
IKXGPRCTCOGVGTUHTQOVJGURGEKHKGFFQOCKP
4GOKPFGTFQOCKPEQFQOCKP 
QOCKPKUVJG+PRWV6[RGQHCHWPEVKQP%QQOCKPKU 
VJG1WVRWV6[RGQHCHWPEVKQP 
Int,String… HWPEVKQP Int, String… 
QOCKP %QQOCKP 
#QOCKPCPFC%QQOCKPECPDGGKVJGTRTKOKVKXG 
V[RGUVWRNGUNKUVUHWPEVKQPU#NIGDTCKECVC6[RGŎ
5CORNG2TQRGTV[ 
Prop.forAll { xs: List[Int] = xs.reverse.reverse == xs }
5CORNG2TQRGTV[ 
QOCKPKUCPCTDKVTCT[XCNWGQHV[RG.KUV=+PV? 
Prop.forAll { xs: List[Int] = xs.reverse.reverse == xs }
5CORNG2TQRGTV[ 
QOCKPKUCPCTDKVTCT[XCNWGQHV[RG.KUV=+PV? 
Prop.forAll { xs: List[Int] = xs.reverse.reverse == xs } 
6JKUKUCTQWPFVTKRRTQRGTV[ 
#RRNKECDNGQPN[HQTKPXGTUKDNGHWPEVKQPU
6GUVECUGTGUVTKEVKQP 
9KVJVGUVECUGTGUVTKEVKQPYGCFFEQPUVTCKPVQP 
RTQITCOFQOCKP
JGTGZKUCRQUKVKXGPWODGT 
import org.scalacheck.Prop.BooleanOperators 
Prop.forAll { x: Int = 
(x = 0) == { 
val root = math.sqrt(x) 
math.round(root * root) == x 
} 
}
6GUVECUGTGUVTKEVKQPUECWVKQP 
$GECTGHWNVQPQVDGVQQTGUVTKEVKXGKH[QWYCPV 
5ECNC%JGEMDGCDNGVQRTQFWEGXCNWGU 
val p = Prop.forAll { n: Int = 
(n = 0  n % 2 == 0  n % 3 == 0) == 
n = 0 
} 
scala p.check 
! Gave up after only 52 passed tests. 262 tests were discarded.
6GUVECUGTGUVTKEVKQPUECWVKQP 
$GECTGHWNVQPQVDGVQQTGUVTKEVKXGKH[QWYCPV 
5ECNC%JGEMDGCDNGVQRTQFWEGXCNWGU 
val p = Prop.forAll { n: Int = 
(n = 0  n % 2 == 0  n % 3 == 0) == 
n = 0 
} 
scala p.check 
! Gave up after only 52 passed tests. 262 tests were discarded. 
7UGKPUVGCFCEWUVQOIGPGTCVQT 
val genNum = Gen.choose(0, Int.MaxValue) 
.retryUntil(_ % 2 == 0) 
.retryUntil(_ % 3 == 0) 
val p = Prop.forAll(genNum) { x: Int = x = 0 } 
scala p.check 
+ OK, passed 100 tests.
6GUVECUGUKORNKHKECVKQP 
val p = Prop.forAll( 
Gen.choose(0, Int.MaxValue) :| x, 
Gen.choose(0, Int.MaxValue) :| y 
) { case (x, y) = 
add(x, y) = x  add(x, y) = y 
} 
scala p.check 
! Falsified after 0 passed tests. 
 x: 195667048 
 x_ORIGINAL: 1350546201 
 y: 1951816600 
 y_ORIGINAL: 2004457204
6GUVECUGUKORNKHKECVKQP 
val p = Prop.forAll( 
Gen.choose(0, Int.MaxValue) :| x, 
Gen.choose(0, Int.MaxValue) :| y 
) { case (x, y) = 
add(x, y) = x  add(x, y) = y 
} 
scala p.check 
! Falsified after 0 passed tests. 
 x: 195667048 
 x_ORIGINAL: 1350546201 
 y: 1951816600 
 y_ORIGINAL: 2004457204 
195667048 + 1951816600 == Int.MaxValue + 1
6GUVECUGUKORNKHKECVKQP 
val p = Prop.forAll( 
Gen.choose(0, Int.MaxValue) :| x, 
Gen.choose(0, Int.MaxValue) :| y 
) { case (x, y) = 
add(x, y) = x  add(x, y) = y 
} 
scala p.check 
! Falsified after 0 passed tests. 
 x: 195667048 
 x_ORIGINAL: 1350546201 
 y: 1951816600 
 y_ORIGINAL: 2004457204 
195667048 + 1951816600 == Int.MaxValue + 1 
VGUVECUGUKORNKHKECVKQPOGEJCPKUOJCUHQWPFVJG 
UKORNGUVVGUVECUGVJCVOCMGVJGVGUVHCKN
6GUVECUGUKORNKHKECVKQP 
val genListPosNum = Gen.listOf(Gen.choose(1, Int.MaxValue)) 
val p = Prop.forAll(genListPosNum :| positive numbers) { xs: List[Int] = 
xs.sorted.foldLeft(Option(0)) { 
case (mp, x) = mp.flatMap(p = if (p  x) Some(x) else None) 
}.isDefined 
} 
scala p.check 
! Falsified after 6 passed tests. 
 positive numbers: List(1, 1) 
 positive numbers_ORIGINAL: List(1901315974, 963110019, 991102462)
6GUVECUGUKORNKHKECVKQP 
val genListPosNum = Gen.listOf(Gen.choose(1, Int.MaxValue)) 
val p = Prop.forAll(genListPosNum :| positive numbers) { xs: List[Int] = 
xs.sorted.foldLeft(Option(0)) { 
case (mp, x) = mp.flatMap(p = if (p  x) Some(x) else None) 
}.isDefined 
} 
scala p.check 
! Falsified after 6 passed tests. 
 positive numbers: List(1, 1) 
 positive numbers_ORIGINAL: List(1901315974, 963110019, 991102462)
6GUVECUGUKORNKHKECVKQP 
val genListPosNum = Gen.listOf(Gen.choose(1, Int.MaxValue)) 
val p = Prop.forAll(genListPosNum :| positive numbers) { xs: List[Int] = 
xs.sorted.foldLeft(Option(0)) { 
case (mp, x) = mp.flatMap(p = if (p  x) Some(x) else None) 
}.isDefined 
} 
scala p.check 
! Falsified after 6 passed tests. 
 positive numbers: List(1, 1) 
 positive numbers_ORIGINAL: List(1901315974, 963110019, 991102462)
+PVGITCVKQPYKVJ5RGEU 
class SampleTest extends Specification with ScalaCheck { 
Integer should { 
have a max method in { 
Prop.forAll { (x: Int, y: Int) = 
val z = math.max(x, y) 
(z == x || z == y)  (z = x  z = y) 
} 
} 
}
5EJGFWNG 
 .KOKVCVKQPUQHVTCFKVKQPCNVGUVKPIVGEJPKSWGU 
 (KTUVGZCORNGQH2TQRGTV[$CUGF6GUVKPIYKVJ5ECNC%JGEM 
 6GUVECUGIGPGTCVKQP 
 GHKPKPICRTQITCORTQRGTVKGU 
 +PVTQFWEKPI#NIGDTCKEGUKIP 
 6JGECUGQH/QPQKF
#NIGDTCKEFGUKIP 
ō #NIGDTCKEFGUKIPKUWUGFVQFGHKPGNKDTCTKGUQH 
HWPEVKQPU 
ō +PCNIGDTCKEFGUKIPYGHQEWUQPHWPEVKQPU 
QRGTCVKPIQXGTFCVCV[RGUCPFNCYUVJCVFGHKPG 
VJGUGHWPEVKQPU 
ō 6JGCNIGDTCQHCNKDTCT[FQGUPņVFGRGPFQPVJG 
KPVGTPCNUQHVJGFCVCV[RGUKVQRGTCVGUQXGT
#NIGDTCKEFGUKIP 
ō 5GXGTCNV[RGENCUUGUGZKUVUYKVJCRTQRGTN[FGHKPGF 
CNIGDTC
HWPEVKQPUCPFNCYU 
ō /QUVRQRWNCTV[RGENCUUGUKPENWFG/QPCFU 
/QPQKFU(WPEVQT#RRNKECVKXGUŎ 
ō 6JGHWPEVKQPCNRTQITCOOKPINKDTCT[5ECNCFGHKPGU 
CNCTIGUGVQHV[RGENCUUGUYKVJVJGKTEQODKPCVQTU 
CPF.CYFGHKPKVKQPU
5EJGFWNG 
 .KOKVCVKQPUQHVTCFKVKQPCNVGUVKPIVGEJPKSWGU 
 (KTUVGZCORNGQH2TQRGTV[$CUGF6GUVKPIYKVJ5ECNC%JGEM 
 6GUVECUGIGPGTCVKQP 
 GHKPKPICRTQITCORTQRGTVKGU 
 +PVTQFWEKPI#NIGDTCKEGUKIP 
 6JGECUGQH/QPQKF
6JGECUGQH/QPQKF 
ō #6[RG#KUC/QPQKFKHVJGTGKU 
ō #PCUUQEKCVKXGENQUGFDKPCT[QRGTCVKQP 
ō #PKFGPVKV[GNGOGPV
QTGTQ 
ō #UCPGZCORNG+PVKUC/QPQKFYKVJ
CUDKPCT[ 
QRGTCVKQPCPFCUKFGPVKV[GNGOGPV
GHKPKVKQPQHC/QPQKF 
trait Monoid[A] { 
def op(a1: A, a2: A): A 
def zero: A 
object Laws { 
import scalaio.scalacheck.Eq 
import Eq._ 
def monoidIsAssociative(in: Gen[(A, A, A)])(implicit eq: Eq[A]): Prop = 
Prop.forAll(in) { case (x, y, z) = 
op(op(x, y), z) === op(x, op(y, z)) 
} 
def monoidHaveZero(in: Gen[A])(implicit eq: Eq[A]): Prop = 
Prop.forAll(in) { a = (op(a, zero) === a)  (op(zero, a) === a)} 
} 
}
'ZCORNGUQH/QPQKF 
val stringMonoid = new Monoid[String] { 
override def zero =  
override def op(a1: String, a2: String) = a1 + a2 
} 
def listMonoid[A] = new Monoid[List[A]] { 
override def op(a1: List[A], a2: List[A]) = a1 ++ a2 
override def zero = List.empty[A] 
} 
val intAdditionMonoid = new Monoid[Int] { 
override def op(a1: Int, a2: Int) = a1 + a2 
override def zero = 0 
} 
val intMultiplicationMonoid = new Monoid[Int] { 
override def op(a1: Int, a2: Int) = a1 * a2 
override def zero = 1 
} 
def endoMonoid[A] = new Monoid[A = A] { 
override def op(a1: A = A, a2: A = A) = { a: A = a1(a2(a)) } 
override def zero = identity 
}
%QODKPCVQTUHQT/QPQKFU 
def productMonoid[A, B](a: Monoid[A], b: Monoid[B]): Monoid[(A, B)] = new Monoid[(A, B)] { 
override def op(a1: (A, B), a2: (A, B)) = (a.op(a1._1, a2._1), b.op(a1._2, a2._2)) 
override def zero = (a.zero, b.zero) 
} 
def mapMergeMonoid[K, V](V: Monoid[V]): Monoid[Map[K, V]] = new Monoid[Map[K, V]] { 
override def op(a1: Map[K, V], a2: Map[K, V]) = a1.map { 
case (k, v) = (k, V.op(v, a2.get(k) getOrElse V.zero)) 
} 
override def zero = Map() 
} 
9GECPETGCVGPGY/QPQKFUHTQOGZKUVKPIKPUVCPEGU
%QODKPCVQTUHQT/QPQKFU 
)KXGP/QPQKFCUUQEKCVKXKV[NCY/QPQKFKPUVCPEGUCTG 
RTGVV[YGNNUWKVGFVQRGTHQTOKPRCTCNNGNQTKP 
FKUVTKDWVGFYC[ 
def parReduce[A](as: List[A]) 
(implicit M: Monoid[A]): A = ??? 
def parMapReduce[A, B](as: List[A], f: A = B) 
(implicit M: Monoid[B]): B = ???
6GUVKPI/QPQKF.CYU 
String Monoid should { 
be associative in { 
val genTriple = arbitrary[(String, String, String)] 
Monoids.stringMonoid.Laws.monoidIsAssociative(genTriple) 
} 
have a zero in { 
Monoids.stringMonoid.Laws.monoidHaveZero(arbitrary[String]) 
} 
}
'SV[RGENCUUFGHKPKVKQP 
trait Eq[A] { 
def equals(a1: A, a2: A): Prop 
} 
object Eq { 
implicit def orderedEq[A: Ordering]: Eq[A] = new Eq[A] { 
override def equals(a1: A, a2: A) = implicitly[Ordering[A]].equiv(a1, a2) 
} 
implicit def functionEq[A: Arbitrary, B]: Eq[A = B] = new Eq[A = B] { 
override def equals(f1: (A) = B, f2: (A) = B) = 
Prop.forAll(arbitrary[A]) { a = f1(a) == f2(a) } 
} 
implicit def listEq[A]: Eq[List[A]] = new Eq[List[A]] { 
override def equals(a1: List[A], a2: List[A]) = a1 == a2 
} 
implicit class EqOps[A: Eq](a1: A) { 
def ===(a2: A): Prop = implicitly[Eq[A]].equals(a1, a2) 
} 
}
6QIQHWTVJGT 
Functional Programming in Scala 
Paul Chiusano and Rúnar Bjarnason 
Manning 
ScalaCheck 
The Definitive Guide 
Richard Nilson 
artima
3WGUVKQPU!

More Related Content

PDF
اسئلة و اجوبة للصغار و لا يستغني عنها الكبار
PDF
The Ring programming language version 1.3 book - Part 63 of 88
PDF
The Ring programming language version 1.3 book - Part 50 of 88
PDF
The Ring programming language version 1.5.3 book - Part 77 of 184
PDF
Emergencias veterinarias
PDF
The Ring programming language version 1.4 book - Part 18 of 30
PDF
Idiomatic kotlin
PDF
[213] Fashion Visual Search
اسئلة و اجوبة للصغار و لا يستغني عنها الكبار
The Ring programming language version 1.3 book - Part 63 of 88
The Ring programming language version 1.3 book - Part 50 of 88
The Ring programming language version 1.5.3 book - Part 77 of 184
Emergencias veterinarias
The Ring programming language version 1.4 book - Part 18 of 30
Idiomatic kotlin
[213] Fashion Visual Search

What's hot (20)

PDF
Numerical Methods with Computer Programming
PDF
The Ring programming language version 1.7 book - Part 73 of 196
PDF
The Ring programming language version 1.8 book - Part 75 of 202
PDF
The Ring programming language version 1.5.2 book - Part 66 of 181
PDF
Apuntes psg
PDF
The Ring programming language version 1.5.4 book - Part 69 of 185
PDF
The Ring programming language version 1.2 book - Part 47 of 84
PDF
El text.life science6.matsubayashi191120
PDF
The Ring programming language version 1.2 book - Part 49 of 84
PDF
The Ring programming language version 1.10 book - Part 79 of 212
DOCX
R (Shiny Package) - UI Side Script for Decision Support System
PDF
The Ring programming language version 1.7 book - Part 72 of 196
DOCX
R (Shiny Package) - Server Side Code for Decision Support System
PDF
The Ring programming language version 1.10 book - Part 81 of 212
PDF
The Ring programming language version 1.8 book - Part 74 of 202
PDF
Hadoop eco story 이해
TXT
Hospital management
PDF
Building Real Time Systems on MongoDB Using the Oplog at Stripe
PDF
Webinar: What's New in Aggregation
PDF
The Ring programming language version 1.5.4 book - Part 67 of 185
Numerical Methods with Computer Programming
The Ring programming language version 1.7 book - Part 73 of 196
The Ring programming language version 1.8 book - Part 75 of 202
The Ring programming language version 1.5.2 book - Part 66 of 181
Apuntes psg
The Ring programming language version 1.5.4 book - Part 69 of 185
The Ring programming language version 1.2 book - Part 47 of 84
El text.life science6.matsubayashi191120
The Ring programming language version 1.2 book - Part 49 of 84
The Ring programming language version 1.10 book - Part 79 of 212
R (Shiny Package) - UI Side Script for Decision Support System
The Ring programming language version 1.7 book - Part 72 of 196
R (Shiny Package) - Server Side Code for Decision Support System
The Ring programming language version 1.10 book - Part 81 of 212
The Ring programming language version 1.8 book - Part 74 of 202
Hadoop eco story 이해
Hospital management
Building Real Time Systems on MongoDB Using the Oplog at Stripe
Webinar: What's New in Aggregation
The Ring programming language version 1.5.4 book - Part 67 of 185
Ad

Viewers also liked (20)

PDF
ScalaCheck Cookbook v1.0
PPTX
Indeisgn tuturial my own
PDF
36kr no.94
PPTX
New members 11.03.15
PPTX
Platform integration
PPTX
Assignment 4 a2
PPTX
Tesol summer institute 2014 giving student feedback
PPTX
3INVESTONLINE.COM
PPT
Euromaidan pr
PDF
The Regional Administrative Court of Lazio confirms a fine imposed by the Ita...
PDF
The antitrust treatment of loyalty discounts and rebates in the EU competitio...
DOCX
Tugas tambang terbuka hubungan rumus bser dan sr tambang terbuka
PDF
Article tema 1
PPT
2013 world label awards presentation
PDF
Soc tong quat 2013
PDF
Products services intelify - DoitSocial
PPTX
Smart goal presentation!
PDF
Primero bmo conference presentation 2015 final v2
PDF
이태석과 Korean sdb
PDF
Primero q1 2015 presentation final
ScalaCheck Cookbook v1.0
Indeisgn tuturial my own
36kr no.94
New members 11.03.15
Platform integration
Assignment 4 a2
Tesol summer institute 2014 giving student feedback
3INVESTONLINE.COM
Euromaidan pr
The Regional Administrative Court of Lazio confirms a fine imposed by the Ita...
The antitrust treatment of loyalty discounts and rebates in the EU competitio...
Tugas tambang terbuka hubungan rumus bser dan sr tambang terbuka
Article tema 1
2013 world label awards presentation
Soc tong quat 2013
Products services intelify - DoitSocial
Smart goal presentation!
Primero bmo conference presentation 2015 final v2
이태석과 Korean sdb
Primero q1 2015 presentation final
Ad

Similar to Property Based Testing with ScalaCheck (20)

PDF
Oceans 2019 tutorial-geophysical-nav_7-updated
DOCX
PDF
第13回数学カフェ「素数!!」二次会 LT資料「乱数!!」
PDF
The Ring programming language version 1.6 book - Part 72 of 189
PDF
An introduction to Google test framework
PDF
3分くらいで分かるassert()
DOCX
Numerical Method Assignment
PDF
The Ring programming language version 1.5.1 book - Part 66 of 180
PDF
The Ring programming language version 1.6 book - Part 86 of 189
PDF
Reactive programming with RxJS - ByteConf 2018
PDF
ゲーム理論NEXT 戦略形協力ゲーム第11回 -寡占市場ゲームにおける結託耐性ナッシュ均衡-
PDF
The Ring programming language version 1.6 book - Part 68 of 189
PDF
مذهب أهل التفويض في نصوص الصفات الشيخ أحمد بن عبد الرحمن القاضي
PDF
The Ring programming language version 1.5.2 book - Part 65 of 181
PDF
A/B Testing for Game Design
PDF
The Ring programming language version 1.5.1 book - Part 62 of 180
PDF
الشرح الكبير على الجزرية للشيخ غانم قدوري الحمد
PDF
Golang dot-testing
PDF
統計的学習の基礎 4章 前半
PPTX
LectureSlidData_sturcture_algorithm_v2.pptx
Oceans 2019 tutorial-geophysical-nav_7-updated
第13回数学カフェ「素数!!」二次会 LT資料「乱数!!」
The Ring programming language version 1.6 book - Part 72 of 189
An introduction to Google test framework
3分くらいで分かるassert()
Numerical Method Assignment
The Ring programming language version 1.5.1 book - Part 66 of 180
The Ring programming language version 1.6 book - Part 86 of 189
Reactive programming with RxJS - ByteConf 2018
ゲーム理論NEXT 戦略形協力ゲーム第11回 -寡占市場ゲームにおける結託耐性ナッシュ均衡-
The Ring programming language version 1.6 book - Part 68 of 189
مذهب أهل التفويض في نصوص الصفات الشيخ أحمد بن عبد الرحمن القاضي
The Ring programming language version 1.5.2 book - Part 65 of 181
A/B Testing for Game Design
The Ring programming language version 1.5.1 book - Part 62 of 180
الشرح الكبير على الجزرية للشيخ غانم قدوري الحمد
Golang dot-testing
統計的学習の基礎 4章 前半
LectureSlidData_sturcture_algorithm_v2.pptx

More from David Galichet (6)

PDF
Writing DSL with Applicative Functors
PDF
Introducing Monads and State Monad at PSUG
PDF
Playing with State Monad
PDF
Demystifying Scala Type System
PDF
Crypto and PKI
PDF
Simple Build Tool
Writing DSL with Applicative Functors
Introducing Monads and State Monad at PSUG
Playing with State Monad
Demystifying Scala Type System
Crypto and PKI
Simple Build Tool

Recently uploaded (20)

PPTX
Presentation for DGJV QMS (PQP)_12.03.2025.pptx
PPTX
PHIL.-ASTRONOMY-AND-NAVIGATION of ..pptx
PDF
Swiggy’s Playbook: UX, Logistics & Monetization
PPTX
nose tajweed for the arabic alphabets for the responsive
PPT
First Aid Training Presentation Slides.ppt
PPTX
Project and change Managment: short video sequences for IBA
PPTX
Self management and self evaluation presentation
PPTX
fundraisepro pitch deck elegant and modern
PPTX
An Unlikely Response 08 10 2025.pptx
PPT
The Effect of Human Resource Management Practice on Organizational Performanc...
PPTX
Effective_Handling_Information_Presentation.pptx
DOCX
ENGLISH PROJECT FOR BINOD BIHARI MAHTO KOYLANCHAL UNIVERSITY
PPTX
Impressionism_PostImpressionism_Presentation.pptx
PPTX
BIOLOGY TISSUE PPT CLASS 9 PROJECT PUBLIC
PPTX
Anesthesia and it's stage with mnemonic and images
PPTX
Human Mind & its character Characteristics
PPTX
Primary and secondary sources, and history
PPTX
MERISTEMATIC TISSUES (MERISTEMS) PPT PUBLIC
PPTX
Introduction-to-Food-Packaging-and-packaging -materials.pptx
PPTX
Relationship Management Presentation In Banking.pptx
Presentation for DGJV QMS (PQP)_12.03.2025.pptx
PHIL.-ASTRONOMY-AND-NAVIGATION of ..pptx
Swiggy’s Playbook: UX, Logistics & Monetization
nose tajweed for the arabic alphabets for the responsive
First Aid Training Presentation Slides.ppt
Project and change Managment: short video sequences for IBA
Self management and self evaluation presentation
fundraisepro pitch deck elegant and modern
An Unlikely Response 08 10 2025.pptx
The Effect of Human Resource Management Practice on Organizational Performanc...
Effective_Handling_Information_Presentation.pptx
ENGLISH PROJECT FOR BINOD BIHARI MAHTO KOYLANCHAL UNIVERSITY
Impressionism_PostImpressionism_Presentation.pptx
BIOLOGY TISSUE PPT CLASS 9 PROJECT PUBLIC
Anesthesia and it's stage with mnemonic and images
Human Mind & its character Characteristics
Primary and secondary sources, and history
MERISTEMATIC TISSUES (MERISTEMS) PPT PUBLIC
Introduction-to-Food-Packaging-and-packaging -materials.pptx
Relationship Management Presentation In Banking.pptx

Property Based Testing with ScalaCheck

  • 1. 2TQRGTV[$CUGF6GUVKPI YKVJ5ECNC%JGEM CXKF)CNKEJGV (TGGNCPEG(WPEVKQPCN2TQITCOOGT 6YKVVGTFICNKEJGV
  • 2. 5EJGFWNG .KOKVCVKQPUQHVTCFKVKQPCNVGUVKPIVGEJPKSWGU (KTUVGZCORNGQH2TQRGTV[$CUGF6GUVKPIYKVJ5ECNC%JGEM 6GUVECUGIGPGTCVKQP GHKPKPICRTQITCORTQRGTVKGU +PVTQFWEKPI#NIGDTCKEGUKIP 6JGECUGQH/QPQKF
  • 3. 1RVKQPUVQEJGEMEQTTGEVPGUUQH CRTQITCO ō 6GUVTKXGPGXGNQROGPVVGEJPKSWGU Z7PKVŎ ō $GJCXKQTTKXGPGXGNQROGPV ō 2TQRGTV[$CUGF6GUVKPI ō 6[RG TKXGP GXGNQROGPV GRGPFGPV 6[RGU 6JGQTGO 2TQXGTU 2CTCOGVTKEKV[ 6JGQTGOU HQT (TGGŎ
  • 4. 6GUVTKXGPGXGNQROGPV ō #RTQITCOKUXGTKHKGFD[UGXGTCNWPKVVGUVU ō 2TQITCOCPFVGUVUCTGFGXGNQRGFKVGTCVKXGN[ ō 6GUVU CTG EQPETGVG GZCORNGU QH JQY C RTQITCO UJQWNFRGTHQTOKPCRCTVKEWNCTUKVWCVKQP ō 6JG[FQPņVIKXGCUUWTCPEGVJCVVJGQXGTCNNDGJCXKQT QHCRTQITCOKUEQXGTGF
  • 5. $GJCXKQTTKXGPGXGNQROGPV ō 5RGEKHKECVKQPU CTG FGHKPGF WUKPI C PCVWTCN HQTOCNKUO VJCV KU GZGEWVCDNG CPF ECP XGTKH[ C RTQITCO ō 6GUVU OWUV DG GZJCWUVKXG VQ EQXGT VJG QXGTCNN RTQITCODGJCXKQT
  • 6. 2TQRGTV[$CUGF6GUVKPI ō 2TQRGTV[$CUGF6GUVKPICNNQY[QWVQFGUETKDG[QWT RTQITCO RTQRGTVKGU NGVVKPI VJG WPFGTN[KPI HTCOGYQTM IGPGTCVG VGUV ECUGU CPF XGTKH[ RTQRGTVKGU ō #RTQRGTV[KUCPCDUVTCEVURGEKHKECVKQP ō )GPGTCVGFVGUVECUGKPENWFGGFIGECUGU ō %QXGTCIGKUJKIJGTVJCPVTCFKVKQPCNVGUVU
  • 9. 5EJGFWNG .KOKVCVKQPUQHVTCFKVKQPCNVGUVKPIVGEJPKSWGU (KTUVGZCORNGQH2TQRGTV[$CUGF6GUVKPIYKVJ5ECNC%JGEM 6GUVECUGIGPGTCVKQP GHKPKPICRTQITCORTQRGTVKGU +PVTQFWEKPI#NIGDTCKEGUKIP 6JGECUGQH/QPQKF
  • 10. 5ECNC%JGEM ō #2TQRGTV[$CUGF6GUVKPIHTCOGYQTM ō #2+HQTCWVQOCVKEVGUVECUGIGPGTCVKQP ō #2+HQTRTQRGTV[FGHKPKVKQP ō 2TQRGTV[EJGEMKPITWPVKOGKPENWFKPI6GUV%CUG 5KORNKHKECVKQP ō +PVGITCVKQPYKVJVGUVHTCOGYQTMU UWEJCU5RGEUQT 5ECNC6GUV
  • 11. 5ECNC%JGEMKUIQQFHQTŎ ō EJGEMKPIEQTTGEVPGUUQHCRTQITCO ō TGITGUUKQPEJGEMKPI ō RTQXKPICNIGDTCKE.CYU ō VGUVKPIYKVJNGUUEQFG ō KPXGUVKICVGRTQRGTV[HCKNWTGU
  • 12. (KTUVGZCORNG val propMax = Prop.forAll { (x: Int, y: Int) = val z = math.max(x, y) (z == x || z == y) (z = x z = y) } propMax.check + OK, passed 100 tests.
  • 13. (KTUVGZCORNG 7PKXGTUCN3WCPVKHKECVKQP∀ val propMax = Prop.forAll { (x: Int, y: Int) = val z = math.max(x, y) (z == x || z == y) (z = x z = y) } propMax.check + OK, passed 100 tests.
  • 14. (KTUVGZCORNG #DUVTCEVFGHKPKVKQPQH+PRWVU 7PKXGTUCN3WCPVKHKECVKQP∀ val propMax = Prop.forAll { (x: Int, y: Int) = val z = math.max(x, y) (z == x || z == y) (z = x z = y) } propMax.check + OK, passed 100 tests.
  • 15. (KTUVGZCORNG #DUVTCEVFGHKPKVKQPQH+PRWVU val propMax = Prop.forAll { (x: Int, y: Int) = val z = math.max(x, y) (z == x || z == y) (z = x z = y) } propMax.check + OK, passed 100 tests. %QORNGVGFGHKPKVKQPQHOCZ 7PKXGTUCN3WCPVKHKECVKQP∀
  • 16. (KTUVGZCORNG #DUVTCEVFGHKPKVKQPQH+PRWVU val propMax = Prop.forAll { (x: Int, y: Int) = val z = math.max(x, y) (z == x || z == y) (z = x z = y) } propMax.check + OK, passed 100 tests. %QORNGVGFGHKPKVKQPQHOCZ 7PKXGTUCN3WCPVKHKECVKQP∀ VGUVUJCXGDGGPTWP
  • 17. 5EJGFWNG .KOKVCVKQPUQHVTCFKVKQPCNVGUVKPIVGEJPKSWGU (KTUVGZCORNGQH2TQRGTV[$CUGF6GUVKPIYKVJ5ECNC%JGEM 6GUVECUGIGPGTCVKQP GHKPKPICRTQITCORTQRGTVKGU +PVTQFWEKPI#NIGDTCKEGUKIP 6JGECUGQH/QPQKF
  • 18. 6GUVECUGIGPGTCVKQP ō 5ECNC%JGEMRTQXKFGUIGPGTCVQTUVQFGHKPGCDUVTCEVVGUVECUGU ō 6JGUG IGPGTCVQTU CTG WUGF VQ TCPFQON[ ETGCVG EQPETGVG VGUV ECUGU ō )GP=6? FGHKPKVKQP KU SWKVG UKORNG # IGPGTCVQT GXGPVWCNN[ TGVWTPUCXCNWGQHV[RG6 class Gen[+T] { def apply(prms: Gen.Params): Option[T] } %QPVCKPU4CPFQO)GPGTCVQT WUGFVQIGPGTCVGCTCPFQO6
  • 19. 7UKPICIGPGTCVQT )GP=6?TGVWTPUCP1RVKQP=6? Gen.choose(0, 100).sample res0: Option[Int] = Some(89) Prop.forAll(Gen.choose(0, 100)) ( _ = 100 ).check + OK, passed 100 tests. )GPGTCVQTKURCUUGFGZRNKEKVN[
  • 20. 5ECNC%JGEM)GP 5ECNC%JGEMFGHKPGUCNCTIGUGVQH)GPGTCVQTU scala Gen. alphaChar fail nonEmptyContainerOf sequence alphaLowerChar freqTuple nonEmptyListOf size alphaNumChar frequency nonEmptyMap sized alphaStr identifier numChar someOf alphaUpperChar isInstanceOf numStr toString asInstanceOf listOf oneOf uuid choose listOf1 option value chooseNum listOfN parameterized wrap const lzy pick zip containerOf mapOf posNum containerOf1 mapOfN resize containerOfN negNum resultOf
  • 21. Custom Generators )GPKUC/QPCFCPFECPDGWUGFKPHQTEQORTGJGPUKQP val personGenerator = for { name - Gen.alphaStr age - Gen.choose(0, 150) } yield Person(name, age) Prop.forAll(personGenerator :| Person) { p = p.toString ?= sPerson(${p.name},${p.age}) } case class Person(name: String, age: Int)
  • 22. 1VJGTUCORNGUQH%WUVQO )GPGTCVQT #IGPGTCVQTECPFGRGPFHTQOXCNWGQHCPQVJGTQPG NKMGKPVJGHQNNQYKPIGZCORNG for { s - Arbitrary.arbitrary[String] index - Gen.choose(0, s.length) } yield (s, index)
  • 23. 9GKIJVGFIGPGTCVQTYKVJ HTGSWGPE[ val even = Gen.posNum[Int].suchThat(_ % 2 == 0) val odd = Gen.posNum[Int].suchThat(_ % 2 == 1) val number = Gen.frequency((2, even), (4, odd), (1, 0)) Prop.forAll(number) { i = val label = if (i == 0) zero else if (i % 2 == 0) even else odd Prop.collect(label)(true) }.check(1000) + OK, passed 1000 tests. Collected test data: 57% odd 29% even 14% zero
  • 24. 9GKIJVGFIGPGTCVQTYKVJ HTGSWGPE[ GHKPGYGKIJVHQTGCEJ)GPGTCVQT val even = Gen.posNum[Int].suchThat(_ % 2 == 0) val odd = Gen.posNum[Int].suchThat(_ % 2 == 1) val number = Gen.frequency((2, even), (4, odd), (1, 0)) Prop.forAll(number) { i = val label = if (i == 0) zero else if (i % 2 == 0) even else odd Prop.collect(label)(true) }.check(1000) + OK, passed 1000 tests. Collected test data: 57% odd 29% even 14% zero
  • 25. 9GKIJVGFIGPGTCVQTYKVJ HTGSWGPE[ GHKPGYGKIJVHQTGCEJ)GPGTCVQT val even = Gen.posNum[Int].suchThat(_ % 2 == 0) val odd = Gen.posNum[Int].suchThat(_ % 2 == 1) val number = Gen.frequency((2, even), (4, odd), (1, 0)) Prop.forAll(number) { i = val label = if (i == 0) zero else if (i % 2 == 0) even else odd Prop.collect(label)(true) }.check(1000) + OK, passed 1000 tests. Collected test data: 57% odd 29% even 14% zero GHKPGCNCDGNHQTGCEJ MKPFQHXCNWG
  • 26. )GPGTCVGCNKUV sealed trait Coin case object Head extends Coin case object Tail extends Coin #TDKVTCT[UKGFNKUVQHCoin val coin = Gen.oneOf(Head, Tail) (KZGFUKGFNKUVQHCoin val coins = Gen.listOf(coin) val threeCoins = Gen.listOfN(3, coin) scala coins.sample res1: Option[List[Coin]] = Some(List(Head, Tail, Head, Tail, …)) scala threeCoins.sample res2: Option[List[Coin]] = Some(List(Head, Head, Tail))
  • 27. 5EJGFWNG .KOKVCVKQPUQHVTCFKVKQPCNVGUVKPIVGEJPKSWGU (KTUVGZCORNGQH2TQRGTV[$CUGF6GUVKPIYKVJ5ECNC%JGEM 6GUVECUGIGPGTCVKQP GHKPKPICRTQITCORTQRGTVKGU +PVTQFWEKPI#NIGDTCKEGUKIP 6JGECUGQH/QPQKF
  • 28. 2TQITCORTQRGTVKGU ō 5ECNC%JGEMIKXGUCDKNKV[VQFGHKPGVJGGZRGEVGF DGJCXKQTQHCRTQITCOKPCRTQITCOOCVKEYC[ ō 6JGRTQRGTV[QHCRTQITCOKUEQORQUGFQHVYQ VJKPIU C VJGFQOCKPQHVJGRTQITCO HWPEVKQPWPFGTVGUV D CPCUUGTVKQPVJCVVJGRTQITCOOWUVXGTKH[ IKXGPRCTCOGVGTUHTQOVJGURGEKHKGFFQOCKP
  • 29. 4GOKPFGTFQOCKPEQFQOCKP QOCKPKUVJG+PRWV6[RGQHCHWPEVKQP%QQOCKPKU VJG1WVRWV6[RGQHCHWPEVKQP Int,String… HWPEVKQP Int, String… QOCKP %QQOCKP #QOCKPCPFC%QQOCKPECPDGGKVJGTRTKOKVKXG V[RGUVWRNGUNKUVUHWPEVKQPU#NIGDTCKECVC6[RGŎ
  • 30. 5CORNG2TQRGTV[ Prop.forAll { xs: List[Int] = xs.reverse.reverse == xs }
  • 31. 5CORNG2TQRGTV[ QOCKPKUCPCTDKVTCT[XCNWGQHV[RG.KUV=+PV? Prop.forAll { xs: List[Int] = xs.reverse.reverse == xs }
  • 32. 5CORNG2TQRGTV[ QOCKPKUCPCTDKVTCT[XCNWGQHV[RG.KUV=+PV? Prop.forAll { xs: List[Int] = xs.reverse.reverse == xs } 6JKUKUCTQWPFVTKRRTQRGTV[ #RRNKECDNGQPN[HQTKPXGTUKDNGHWPEVKQPU
  • 33. 6GUVECUGTGUVTKEVKQP 9KVJVGUVECUGTGUVTKEVKQPYGCFFEQPUVTCKPVQP RTQITCOFQOCKP JGTGZKUCRQUKVKXGPWODGT import org.scalacheck.Prop.BooleanOperators Prop.forAll { x: Int = (x = 0) == { val root = math.sqrt(x) math.round(root * root) == x } }
  • 34. 6GUVECUGTGUVTKEVKQPUECWVKQP $GECTGHWNVQPQVDGVQQTGUVTKEVKXGKH[QWYCPV 5ECNC%JGEMDGCDNGVQRTQFWEGXCNWGU val p = Prop.forAll { n: Int = (n = 0 n % 2 == 0 n % 3 == 0) == n = 0 } scala p.check ! Gave up after only 52 passed tests. 262 tests were discarded.
  • 35. 6GUVECUGTGUVTKEVKQPUECWVKQP $GECTGHWNVQPQVDGVQQTGUVTKEVKXGKH[QWYCPV 5ECNC%JGEMDGCDNGVQRTQFWEGXCNWGU val p = Prop.forAll { n: Int = (n = 0 n % 2 == 0 n % 3 == 0) == n = 0 } scala p.check ! Gave up after only 52 passed tests. 262 tests were discarded. 7UGKPUVGCFCEWUVQOIGPGTCVQT val genNum = Gen.choose(0, Int.MaxValue) .retryUntil(_ % 2 == 0) .retryUntil(_ % 3 == 0) val p = Prop.forAll(genNum) { x: Int = x = 0 } scala p.check + OK, passed 100 tests.
  • 36. 6GUVECUGUKORNKHKECVKQP val p = Prop.forAll( Gen.choose(0, Int.MaxValue) :| x, Gen.choose(0, Int.MaxValue) :| y ) { case (x, y) = add(x, y) = x add(x, y) = y } scala p.check ! Falsified after 0 passed tests. x: 195667048 x_ORIGINAL: 1350546201 y: 1951816600 y_ORIGINAL: 2004457204
  • 37. 6GUVECUGUKORNKHKECVKQP val p = Prop.forAll( Gen.choose(0, Int.MaxValue) :| x, Gen.choose(0, Int.MaxValue) :| y ) { case (x, y) = add(x, y) = x add(x, y) = y } scala p.check ! Falsified after 0 passed tests. x: 195667048 x_ORIGINAL: 1350546201 y: 1951816600 y_ORIGINAL: 2004457204 195667048 + 1951816600 == Int.MaxValue + 1
  • 38. 6GUVECUGUKORNKHKECVKQP val p = Prop.forAll( Gen.choose(0, Int.MaxValue) :| x, Gen.choose(0, Int.MaxValue) :| y ) { case (x, y) = add(x, y) = x add(x, y) = y } scala p.check ! Falsified after 0 passed tests. x: 195667048 x_ORIGINAL: 1350546201 y: 1951816600 y_ORIGINAL: 2004457204 195667048 + 1951816600 == Int.MaxValue + 1 VGUVECUGUKORNKHKECVKQPOGEJCPKUOJCUHQWPFVJG UKORNGUVVGUVECUGVJCVOCMGVJGVGUVHCKN
  • 39. 6GUVECUGUKORNKHKECVKQP val genListPosNum = Gen.listOf(Gen.choose(1, Int.MaxValue)) val p = Prop.forAll(genListPosNum :| positive numbers) { xs: List[Int] = xs.sorted.foldLeft(Option(0)) { case (mp, x) = mp.flatMap(p = if (p x) Some(x) else None) }.isDefined } scala p.check ! Falsified after 6 passed tests. positive numbers: List(1, 1) positive numbers_ORIGINAL: List(1901315974, 963110019, 991102462)
  • 40. 6GUVECUGUKORNKHKECVKQP val genListPosNum = Gen.listOf(Gen.choose(1, Int.MaxValue)) val p = Prop.forAll(genListPosNum :| positive numbers) { xs: List[Int] = xs.sorted.foldLeft(Option(0)) { case (mp, x) = mp.flatMap(p = if (p x) Some(x) else None) }.isDefined } scala p.check ! Falsified after 6 passed tests. positive numbers: List(1, 1) positive numbers_ORIGINAL: List(1901315974, 963110019, 991102462)
  • 41. 6GUVECUGUKORNKHKECVKQP val genListPosNum = Gen.listOf(Gen.choose(1, Int.MaxValue)) val p = Prop.forAll(genListPosNum :| positive numbers) { xs: List[Int] = xs.sorted.foldLeft(Option(0)) { case (mp, x) = mp.flatMap(p = if (p x) Some(x) else None) }.isDefined } scala p.check ! Falsified after 6 passed tests. positive numbers: List(1, 1) positive numbers_ORIGINAL: List(1901315974, 963110019, 991102462)
  • 42. +PVGITCVKQPYKVJ5RGEU class SampleTest extends Specification with ScalaCheck { Integer should { have a max method in { Prop.forAll { (x: Int, y: Int) = val z = math.max(x, y) (z == x || z == y) (z = x z = y) } } }
  • 43. 5EJGFWNG .KOKVCVKQPUQHVTCFKVKQPCNVGUVKPIVGEJPKSWGU (KTUVGZCORNGQH2TQRGTV[$CUGF6GUVKPIYKVJ5ECNC%JGEM 6GUVECUGIGPGTCVKQP GHKPKPICRTQITCORTQRGTVKGU +PVTQFWEKPI#NIGDTCKEGUKIP 6JGECUGQH/QPQKF
  • 44. #NIGDTCKEFGUKIP ō #NIGDTCKEFGUKIPKUWUGFVQFGHKPGNKDTCTKGUQH HWPEVKQPU ō +PCNIGDTCKEFGUKIPYGHQEWUQPHWPEVKQPU QRGTCVKPIQXGTFCVCV[RGUCPFNCYUVJCVFGHKPG VJGUGHWPEVKQPU ō 6JGCNIGDTCQHCNKDTCT[FQGUPņVFGRGPFQPVJG KPVGTPCNUQHVJGFCVCV[RGUKVQRGTCVGUQXGT
  • 45. #NIGDTCKEFGUKIP ō 5GXGTCNV[RGENCUUGUGZKUVUYKVJCRTQRGTN[FGHKPGF CNIGDTC HWPEVKQPUCPFNCYU ō /QUVRQRWNCTV[RGENCUUGUKPENWFG/QPCFU /QPQKFU(WPEVQT#RRNKECVKXGUŎ ō 6JGHWPEVKQPCNRTQITCOOKPINKDTCT[5ECNCFGHKPGU CNCTIGUGVQHV[RGENCUUGUYKVJVJGKTEQODKPCVQTU CPF.CYFGHKPKVKQPU
  • 46. 5EJGFWNG .KOKVCVKQPUQHVTCFKVKQPCNVGUVKPIVGEJPKSWGU (KTUVGZCORNGQH2TQRGTV[$CUGF6GUVKPIYKVJ5ECNC%JGEM 6GUVECUGIGPGTCVKQP GHKPKPICRTQITCORTQRGTVKGU +PVTQFWEKPI#NIGDTCKEGUKIP 6JGECUGQH/QPQKF
  • 47. 6JGECUGQH/QPQKF ō #6[RG#KUC/QPQKFKHVJGTGKU ō #PCUUQEKCVKXGENQUGFDKPCT[QRGTCVKQP ō #PKFGPVKV[GNGOGPV QTGTQ ō #UCPGZCORNG+PVKUC/QPQKFYKVJ CUDKPCT[ QRGTCVKQPCPFCUKFGPVKV[GNGOGPV
  • 48. GHKPKVKQPQHC/QPQKF trait Monoid[A] { def op(a1: A, a2: A): A def zero: A object Laws { import scalaio.scalacheck.Eq import Eq._ def monoidIsAssociative(in: Gen[(A, A, A)])(implicit eq: Eq[A]): Prop = Prop.forAll(in) { case (x, y, z) = op(op(x, y), z) === op(x, op(y, z)) } def monoidHaveZero(in: Gen[A])(implicit eq: Eq[A]): Prop = Prop.forAll(in) { a = (op(a, zero) === a) (op(zero, a) === a)} } }
  • 49. 'ZCORNGUQH/QPQKF val stringMonoid = new Monoid[String] { override def zero = override def op(a1: String, a2: String) = a1 + a2 } def listMonoid[A] = new Monoid[List[A]] { override def op(a1: List[A], a2: List[A]) = a1 ++ a2 override def zero = List.empty[A] } val intAdditionMonoid = new Monoid[Int] { override def op(a1: Int, a2: Int) = a1 + a2 override def zero = 0 } val intMultiplicationMonoid = new Monoid[Int] { override def op(a1: Int, a2: Int) = a1 * a2 override def zero = 1 } def endoMonoid[A] = new Monoid[A = A] { override def op(a1: A = A, a2: A = A) = { a: A = a1(a2(a)) } override def zero = identity }
  • 50. %QODKPCVQTUHQT/QPQKFU def productMonoid[A, B](a: Monoid[A], b: Monoid[B]): Monoid[(A, B)] = new Monoid[(A, B)] { override def op(a1: (A, B), a2: (A, B)) = (a.op(a1._1, a2._1), b.op(a1._2, a2._2)) override def zero = (a.zero, b.zero) } def mapMergeMonoid[K, V](V: Monoid[V]): Monoid[Map[K, V]] = new Monoid[Map[K, V]] { override def op(a1: Map[K, V], a2: Map[K, V]) = a1.map { case (k, v) = (k, V.op(v, a2.get(k) getOrElse V.zero)) } override def zero = Map() } 9GECPETGCVGPGY/QPQKFUHTQOGZKUVKPIKPUVCPEGU
  • 51. %QODKPCVQTUHQT/QPQKFU )KXGP/QPQKFCUUQEKCVKXKV[NCY/QPQKFKPUVCPEGUCTG RTGVV[YGNNUWKVGFVQRGTHQTOKPRCTCNNGNQTKP FKUVTKDWVGFYC[ def parReduce[A](as: List[A]) (implicit M: Monoid[A]): A = ??? def parMapReduce[A, B](as: List[A], f: A = B) (implicit M: Monoid[B]): B = ???
  • 52. 6GUVKPI/QPQKF.CYU String Monoid should { be associative in { val genTriple = arbitrary[(String, String, String)] Monoids.stringMonoid.Laws.monoidIsAssociative(genTriple) } have a zero in { Monoids.stringMonoid.Laws.monoidHaveZero(arbitrary[String]) } }
  • 53. 'SV[RGENCUUFGHKPKVKQP trait Eq[A] { def equals(a1: A, a2: A): Prop } object Eq { implicit def orderedEq[A: Ordering]: Eq[A] = new Eq[A] { override def equals(a1: A, a2: A) = implicitly[Ordering[A]].equiv(a1, a2) } implicit def functionEq[A: Arbitrary, B]: Eq[A = B] = new Eq[A = B] { override def equals(f1: (A) = B, f2: (A) = B) = Prop.forAll(arbitrary[A]) { a = f1(a) == f2(a) } } implicit def listEq[A]: Eq[List[A]] = new Eq[List[A]] { override def equals(a1: List[A], a2: List[A]) = a1 == a2 } implicit class EqOps[A: Eq](a1: A) { def ===(a2: A): Prop = implicitly[Eq[A]].equals(a1, a2) } }
  • 54. 6QIQHWTVJGT Functional Programming in Scala Paul Chiusano and Rúnar Bjarnason Manning ScalaCheck The Definitive Guide Richard Nilson artima