SlideShare a Scribd company logo
Property based Testing
generative data & executable domain rules
Debasish Ghosh
(@debasishg)
Friday, 10 October 14
Agenda
Why xUnit based testing is not enough
What is a property?
Properties for free?
What to verify in property based testing
ScalaCheck
Domain Model Testing
Friday, 10 October 14
xUnit based testing
• Convenient
• Widely used
• Rich tool support
Friday, 10 October 14
xUnit based testing
• Often grows out of bounds (verbosity),
being at a lower level of abstraction
• Difficult to manage data/logic isolation
• Always scared that I may have missed some
edge cases & boundary conditions
Friday, 10 October 14
// polymorphic list append
def append[A](xs: List[A], ys: List[A]): List[A] = {
//..
}
How do you show the correctness of the
above implementation ?
Friday, 10 October 14
(1) Theorem Proving
length [] = 0 (length.1)
length (z : zs) = 1 + length zs (length.2)
[] ++ zs = zs (++.1)
(w : ws) ++ zs = w : (ws ++ zs) (++.2)
length ([] ++ ys) = length [] + length ys (base)
length (xs ++ ys) = length xs + length ys (hypothesis)
Length & Append
Induction
length ((x : xs) ++ ys) = length (x : xs) + length ys
To Prove
Friday, 10 October 14
Base Case
length ([] ++ ys) = length [] + length ys (base)
length ([] ++ ys)
= length ys (by ++.1)
length [] + length ys
= 0 + length ys
= length ys (by length.1)
length [] = 0 (length.1)
length (z : zs) = 1 + length zs (length.2)
[] ++ zs = zs (++.1)
(w : ws) ++ zs = w : (ws ++ zs) (++.2)
Friday, 10 October 14
Induction
length ((x : xs) ++ ys) = length (x : xs) + length ys
length ((x : xs) ++ ys)
= length (x : (xs ++ ys)) (by ++.2)
= 1 + length (xs ++ ys) (by length.2)
= 1 + length xs + length ys
length (x : xs) + length ys
= 1 + length xs + length ys (by length.2)
length [] = 0 (length.1)
length (z : zs) = 1 + length zs (length.2)
[] ++ zs = zs (++.1)
(w : ws) ++ zs = w : (ws ++ zs) (++.2)
Friday, 10 October 14
(2) Use your favorite unit testing library
// ScalaTest based assertions
List(1,2,3).length + List(4,5).length should equal
(append(List(1,2,3), List(4,5)).length)
List().length + List(4,5).length should equal
(append(List(), List(4,5)).length)
List(1,2,3).length + List().length should equal
(append(List(1,2,3), List()).length)
Friday, 10 October 14
• Hard coded data sets
• May not be exhaustive
• Coverage depends upon the knowledge of
the test creator
But ..
Friday, 10 October 14
(3) Use dependent typing - an example of append in
Idris, a dependently typed language
-- Vectors lists that have size as part of type
data Vect : Nat -> Type -> Type where
Nil : Vect Z a
(::) : a -> Vect k a -> Vect (S k) a
-- the app function is correct by construction
app : Vect n a -> Vect m a -> Vect (n + m) a
app Nil ys = ys
app (x :: xs) ys = x :: app xs ys
Future ?
Friday, 10 October 14
• Types depend on values
• Powerful constraints encoded within the
type signature
• Correct by construction - correct before
the program runs!
Future ?
Friday, 10 October 14
• Miles Sabin has been working on shapeless
(https://github.com/milessabin/shapeless)
• Flavors of dependent typing in Scala
• Sized containers, polymorphic function
values, heterogeneous lists & a host of
other goodness built on top of Scala
typesystem
today ..
Friday, 10 October 14
• Till such time the ecosystem matures, we all
start programming in dependently typed
languages ..
• We have better options than using only xUnit
based testing ..
Mature?
Friday, 10 October 14
What exactly are we trying to verify ?
property("List append adds up the 2 sizes") =
forAll((l1: List[Int], l2: List[Int]) =>
l1.length + l2.length == append(l1, l2).length
)
Friday, 10 October 14
What exactly are we trying to verify ?
property("List append adds up the 2 sizes") =
forAll((l1: List[Int], l2: List[Int]) =>
l1.length + l2.length == append(l1, l2).length
)
invariant of our function encoded
as a generic property
Friday, 10 October 14
What is a property?
• Constraints and invariants that must be
honored within the bounded context of the
model
• Sometimes called “laws” or the “algebra”
• Ensures well-formed-ness of abstractions
Friday, 10 October 14
A Monoid
An algebraic structure
having
• an identity element
• a binary associative
operation
trait Monoid[A] {
def zero: A
def op(l: A, r: => A): A
}
object MonoidLaws {
def associative[A: Equal: Monoid]
(a1: A, a2: A, a3: A): Boolean = //..
def rightIdentity[A: Equal: Monoid]
(a: A) = //..
def leftIdentity[A: Equal: Monoid]
(a: A) = //..
}
Friday, 10 October 14
Monoid Laws
An algebraic structure
havingsa
• an identity element
• a binary associative
operation
trait Monoid[A] {
def zero: A
def op(l: A, r: => A): A
}
object MonoidLaws {
def associative[A: Equal: Monoid]
(a1: A, a2: A, a3: A): Boolean = //..
def rightIdentity[A: Equal: Monoid]
(a: A) = //..
def leftIdentity[A: Equal: Monoid]
(a: A) = //..
}
satisfies
op(x, zero) == x and op(zero, x) == x
satisfies
op(op(x, y), z) == op(x, op(y, z))
Friday, 10 October 14
• Every monoid that you define must honor
all the laws of the abstraction
• The question is how do we verify that all
laws are satisfied
it’s the LAW
Friday, 10 October 14
But before that another important important
question is what properties do we need to verify ..
Friday, 10 October 14
def f[A](a: A): A
•The function f takes as input a value and returns a value
of the same type
• But we don’t know the exact type of A
• Hence we cannot do any type specific operation within f
•All we know is that f is a polymorphic function
parameterized on type A, that returns the same type as
the input
•A little thought makes us realize that the only possible
implementation of f is that of an identity function
Friday, 10 October 14
def f[A](a: A): A = a
•This is the only possible implementation of f (unless we
decide to launch a missile and do all evil stuff like throwing
exceptions or do typecasing)
• If the type-checker checks it ok, we are done.The
compiler has proved the theorem and we don’t need to
verify the property ourselves
• So we have proved a theorem out of the types - this
technique is called parametricity and PhilWadler calls these
free theorems
Fast and Loose Reasoning is Morally Correct (2006) by by Nils Anders Danielsson, John Hughes, Jeremy
Gibbons, Patrik Jansson (http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.59.8232)
Friday, 10 October 14
Free theorems are ensured by the type-
checker in a statically typed language that
supports parametric polymorphism and we
don’t need to write tests for verifying any of
those properties
Theorems for Free! by Phil Wadler (http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.38.9875)
Friday, 10 October 14
Parametricity tests a lot of properties in
your model.
“Parametricity constantly tests more conditions
than your unit test suite ever will”
- Edward Kmett on #scala
Friday, 10 October 14
What properties do we need to verify ?
Friday, 10 October 14
Summarizing ..
• if your programming language has a decent
static type system and
• support for parametric polymorphism and
• you play to the rules of parametricity
• ....
Friday, 10 October 14
Summarizing ..
• if your programming language has a decent
static type system and
• support for parametric polymorphism and
• you play to the rules of parametricity
• ....
You get a lot of properties
verified for FREE
Friday, 10 October 14
• Property based testing library for Scala
(and also for Java)
• Inspired by QuickCheck (Erlang & Haskell)
• Works on property specifications
• Does automatic data generation
ScalaCheck ..
Friday, 10 October 14
ScalaCheck
• You specify the property to be tested
• ScalaCheck verifies that the property holds
by generating random data
• No burden on programmer to maintain
data, no fear of missed edge cases
Friday, 10 October 14
“Property-based testing encourages a high level approach to
testing in the form of abstract invariants functions should satisfy
universally, with the actual test data generated for the
programmer by the testing library. In this way code can be
hammered with thousands of tests that would be infeasible to
write by hand, often uncovering subtle corner cases that
wouldn't be found otherwise.”
Real World Haskell by Bryan O’Sullivan, Don
Stewart & John Goerzen
Friday, 10 October 14
scala> import org.scalacheck._
import org.scalacheck._
scala> import Prop.forAll
import Prop.forAll
scala> forAll((l1: List[Int], l2: List[Int]) =>
| l1.length + l2.length == append(l1, l2).length
| )
res5: org.scalacheck.Prop = Prop
scala> res5.check
+ OK, passed 100 tests.
generates 100 test cases randomly and verifies
the property
specification of the property to be verified
Verifying properties
universal quantifier
Friday, 10 October 14
scala> val propSqrt = forAll { (n: Int) =>
scala.math.sqrt(n*n) == n
}
propSqrt: org.scalacheck.Prop = Prop
scala> propSqrt.check
! Falsified after 0 passed tests.
> ARG_0: -2147483648
scala> propSqrt.check
! Falsified after 0 passed tests.
> ARG_0: -1
not only says that the property fails, but also
points to failure data set
Verifying properties
A word about minimization of test cases.
Whenever a property fails, scalacheck
starts shrinking the test cases until it finds
the minimal failing test case.This is a huge
feature that helps debugging failures
Friday, 10 October 14
scala> val propSqrt = forAll { (n: Int) =>
| scala.math.sqrt(n*n) == n
| }
propSqrt: org.scalacheck.Prop = Prop
scala> val smallInteger = Gen.choose(1, 100)
smallInteger: org.scalacheck.Gen[Int] = ..
scala> val propSmallInteger = forAll(smallInteger)(n =>
| n >= 0 && n <= 100
| )
propSmallInteger: org.scalacheck.Prop = Prop
uses default data generator
custom generator
forAll uses the custom generator
Custom generators
Friday, 10 October 14
// generate values in a range
Gen.choose(10, 20)
// conditional generator
Gen.choose(0,200) suchThat (_ % 2 == 0)
// generate specific values
Gen.oneOf('A' | 'E' | 'I' | 'O' | 'U' | 'Y')
// default distribution is random, but you can change
val vowel = Gen.frequency(
(3, 'A'),
(4, 'E'),
(2, 'I'),
(3, 'O'),
(1, 'U'),
(1, 'Y')
)
// generate containers
Gen.containerOf[List,Int](Gen.oneOf(1, 3, 5))
Custom generators
Friday, 10 October 14
Define your own
generator
case class Account(no: String, holder: String,
openingDate: Date, closeDate: Option[Date])
val genAccount = for {
no <- Gen.oneOf("1", "2", "3")
nm <- Gen.oneOf("john", "david", "mary")
od <- arbitrary[Date]
cd <- arbitrary[Option[Date]]
} yield Account(no, nm, od, cd)
(model)
(random data generator)
Friday, 10 October 14
Define your own
generator
sealed abstract class Tree
case object Leaf extends Tree
case class Node(left: Tree, right: Tree, v: Int) extends Tree
val genLeaf = value(Leaf)
val genNode = for {
v <- arbitrary[Int]
left <- genTree
right <- genTree
} yield Node(left, right, v)
def genTree: Gen[Tree] = oneOf(genLeaf, genNode)
(model)
(random data generator)
Friday, 10 October 14
implicit val arbAccount: Arbitrary[Account] = Arbitrary {
for {
no <- Gen.oneOf("1", "2", "3")
nm <- Gen.oneOf("john", "david", "mary")
od <- arbitrary[Date]
} yield checkingAccount(no, nm, od)
}
implicit val arbCcy: Arbitrary[Currency] = Arbitrary {
Gen.oneOf(USD, SGD, AUD, INR)
}
implicit val arbMoney = Arbitrary {
for {
a <- Gen.oneOf(1 to 10)
c <- arbitrary[Currency]
} yield Money(a, c)
}
implicit val arbPosition: Arbitrary[Position] = Arbitrary {
for {
a <- arbitrary[Account]
m <- arbitrary[Money]
d <- arbitrary[Date]
} yield Position(a, m, d)
}
Arbitrary is a special generator that scalacheck
uses to generate random data. Need to specify an
implicit Arbitrary instance of your specific data
type which can be used to generate data
Domain Model Testing
Friday, 10 October 14
property("Equal debit & credit retains the same position") =
forAll((a: Account, c: Currency, d: Date, i: BigDecimal) => {
val Success((before, after)) = for {
p <- position(a, c, d)
r <- credit(p, Money(i, c), d)
q <- debit(r, Money(i, c), d)
} yield (q, p)
before == after
})
property("Can close account with close date > opening date") = forAll((a:
Account) =>
close(a, new Date(a.openingDate.getTime + 10000)).isSuccess == true
)
property("Cannot close account with close date < opening date") = forAll((a:
Account) =>
close(a, new Date(a.openingDate.getTime - 10000)).isSuccess == false
)
Domain Model Testing
Verify your business rules and document them too
Friday, 10 October 14
Some other features
• Sized generators - restrict the set of
generated data
• Conditional generators - use combinators
to specify filters
• Classify generated test data to see
statistical distribution
Friday, 10 October 14
Some other features
• Test case minimization for failed tests
• Stateful testing - not only queries, but
commands as well in the CQRS sense of the
term
Friday, 10 October 14
Essence of property
based testing
• Identify constraints & invariants of your
abstraction that must hold within your
domain model
• Encode them as “properties” in your code
(not as dumb documents)
• Execute properties to verify the
correctness of your abstraction
Friday, 10 October 14
Essence of property
based testing
• In testing domain models, properties help
you think at a higher level of abstraction
• Basically you encode domain rules as
properties and verify them using data
generators that use the domain model itself
• Executable domain rules
Friday, 10 October 14
Property based testing
& Functional programs
• Functional programs are easier to test &
debug (no global state)
• Makes a good case for property based
testing (immutable data, pure functions)
• Usually concise & modular - easier to
identify properties
Friday, 10 October 14
ThankYou!
Friday, 10 October 14

More Related Content

What's hot

Exploring type level programming in Scala
Exploring type level programming in ScalaExploring type level programming in Scala
Exploring type level programming in Scala
Jorge Vásquez
 
Practically Functional
Practically FunctionalPractically Functional
Practically Functional
djspiewak
 
Scala collections api expressivity and brevity upgrade from java
Scala collections api  expressivity and brevity upgrade from javaScala collections api  expressivity and brevity upgrade from java
Scala collections api expressivity and brevity upgrade from java
IndicThreads
 
Scala Up North: "Analysing Scala Puzzlers: Essential and Accidental Complexit...
Scala Up North: "Analysing Scala Puzzlers: Essential and Accidental Complexit...Scala Up North: "Analysing Scala Puzzlers: Essential and Accidental Complexit...
Scala Up North: "Analysing Scala Puzzlers: Essential and Accidental Complexit...
Andrew Phillips
 
Demystifying Shapeless
Demystifying Shapeless Demystifying Shapeless
Demystifying Shapeless
Jared Roesch
 
Scala 2013 review
Scala 2013 reviewScala 2013 review
Scala 2013 review
Sagie Davidovich
 
A Scala Corrections Library
A Scala Corrections LibraryA Scala Corrections Library
A Scala Corrections Library
Paul Phillips
 
Scala traits training by Sanjeev Kumar @Kick Start Scala traits & Play, organ...
Scala traits training by Sanjeev Kumar @Kick Start Scala traits & Play, organ...Scala traits training by Sanjeev Kumar @Kick Start Scala traits & Play, organ...
Scala traits training by Sanjeev Kumar @Kick Start Scala traits & Play, organ...
Sanjeev_Knoldus
 
Ponies and Unicorns With Scala
Ponies and Unicorns With ScalaPonies and Unicorns With Scala
Ponies and Unicorns With Scala
Tomer Gabel
 
Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)
Jonas Bonér
 
Scala Intro
Scala IntroScala Intro
Scala Talk at FOSDEM 2009
Scala Talk at FOSDEM 2009Scala Talk at FOSDEM 2009
Scala Talk at FOSDEM 2009
Martin Odersky
 
SE 20016 - programming languages landscape.
SE 20016 - programming languages landscape.SE 20016 - programming languages landscape.
SE 20016 - programming languages landscape.
Ruslan Shevchenko
 
Ajax and JavaScript Bootcamp
Ajax and JavaScript BootcampAjax and JavaScript Bootcamp
Ajax and JavaScript Bootcamp
AndreCharland
 
Programming in Scala: Notes
Programming in Scala: NotesProgramming in Scala: Notes
Programming in Scala: Notes
Roberto Casadei
 
Metaprogramming in Scala 2.10, Eugene Burmako,
Metaprogramming  in Scala 2.10, Eugene Burmako, Metaprogramming  in Scala 2.10, Eugene Burmako,
Metaprogramming in Scala 2.10, Eugene Burmako,
Vasil Remeniuk
 
Scala: Functioneel programmeren in een object georiënteerde wereld
Scala: Functioneel programmeren in een object georiënteerde wereldScala: Functioneel programmeren in een object georiënteerde wereld
Scala: Functioneel programmeren in een object georiënteerde wereld
Werner Hofstra
 

What's hot (20)

Exploring type level programming in Scala
Exploring type level programming in ScalaExploring type level programming in Scala
Exploring type level programming in Scala
 
Practically Functional
Practically FunctionalPractically Functional
Practically Functional
 
Scala collections api expressivity and brevity upgrade from java
Scala collections api  expressivity and brevity upgrade from javaScala collections api  expressivity and brevity upgrade from java
Scala collections api expressivity and brevity upgrade from java
 
Scala Up North: "Analysing Scala Puzzlers: Essential and Accidental Complexit...
Scala Up North: "Analysing Scala Puzzlers: Essential and Accidental Complexit...Scala Up North: "Analysing Scala Puzzlers: Essential and Accidental Complexit...
Scala Up North: "Analysing Scala Puzzlers: Essential and Accidental Complexit...
 
Demystifying Shapeless
Demystifying Shapeless Demystifying Shapeless
Demystifying Shapeless
 
Scala for curious
Scala for curiousScala for curious
Scala for curious
 
Scala 2013 review
Scala 2013 reviewScala 2013 review
Scala 2013 review
 
A Scala Corrections Library
A Scala Corrections LibraryA Scala Corrections Library
A Scala Corrections Library
 
Scala traits training by Sanjeev Kumar @Kick Start Scala traits & Play, organ...
Scala traits training by Sanjeev Kumar @Kick Start Scala traits & Play, organ...Scala traits training by Sanjeev Kumar @Kick Start Scala traits & Play, organ...
Scala traits training by Sanjeev Kumar @Kick Start Scala traits & Play, organ...
 
Ponies and Unicorns With Scala
Ponies and Unicorns With ScalaPonies and Unicorns With Scala
Ponies and Unicorns With Scala
 
Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)
 
Scala Intro
Scala IntroScala Intro
Scala Intro
 
Scala Talk at FOSDEM 2009
Scala Talk at FOSDEM 2009Scala Talk at FOSDEM 2009
Scala Talk at FOSDEM 2009
 
SE 20016 - programming languages landscape.
SE 20016 - programming languages landscape.SE 20016 - programming languages landscape.
SE 20016 - programming languages landscape.
 
Ajax and JavaScript Bootcamp
Ajax and JavaScript BootcampAjax and JavaScript Bootcamp
Ajax and JavaScript Bootcamp
 
Programming in Scala: Notes
Programming in Scala: NotesProgramming in Scala: Notes
Programming in Scala: Notes
 
Scala - core features
Scala - core featuresScala - core features
Scala - core features
 
Metaprogramming in Scala 2.10, Eugene Burmako,
Metaprogramming  in Scala 2.10, Eugene Burmako, Metaprogramming  in Scala 2.10, Eugene Burmako,
Metaprogramming in Scala 2.10, Eugene Burmako,
 
Scala: Functioneel programmeren in een object georiënteerde wereld
Scala: Functioneel programmeren in een object georiënteerde wereldScala: Functioneel programmeren in een object georiënteerde wereld
Scala: Functioneel programmeren in een object georiënteerde wereld
 
An introduction to scala
An introduction to scalaAn introduction to scala
An introduction to scala
 

Similar to Property based Testing - generative data & executable domain rules

Everything is Permitted: Extending Built-ins
Everything is Permitted: Extending Built-insEverything is Permitted: Extending Built-ins
Everything is Permitted: Extending Built-ins
Andrew Dupont
 
Scala: A brief tutorial
Scala: A brief tutorialScala: A brief tutorial
Scala: A brief tutorial
Oliver Szymanski
 
Functional Operations - Susan Potter
Functional Operations - Susan PotterFunctional Operations - Susan Potter
Functional Operations - Susan Potter
distributed matters
 
Lucene Introduction
Lucene IntroductionLucene Introduction
Lucene Introduction
otisg
 
Spock: Test Well and Prosper
Spock: Test Well and ProsperSpock: Test Well and Prosper
Spock: Test Well and Prosper
Ken Kousen
 
Speaking Scala: Refactoring for Fun and Profit (Workshop)
Speaking Scala: Refactoring for Fun and Profit (Workshop)Speaking Scala: Refactoring for Fun and Profit (Workshop)
Speaking Scala: Refactoring for Fun and Profit (Workshop)
Tomer Gabel
 
(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?Tomasz Wrobel
 
Scala Refactoring for Fun and Profit
Scala Refactoring for Fun and ProfitScala Refactoring for Fun and Profit
Scala Refactoring for Fun and Profit
Tomer Gabel
 
ScalaCheck
ScalaCheckScalaCheck
ScalaCheckBeScala
 
Akka Testkit Patterns
Akka Testkit PatternsAkka Testkit Patterns
Akka Testkit Patterns
Mykhailo Kotsur
 
Fire in the type hole
Fire in the type holeFire in the type hole
Fire in the type hole
ihji
 
Ruslan Shevchenko - Property based testing
Ruslan Shevchenko - Property based testingRuslan Shevchenko - Property based testing
Ruslan Shevchenko - Property based testing
Ievgenii Katsan
 
Scala @ TechMeetup Edinburgh
Scala @ TechMeetup EdinburghScala @ TechMeetup Edinburgh
Scala @ TechMeetup Edinburgh
Stuart Roebuck
 
Ti1220 Lecture 7: Polymorphism
Ti1220 Lecture 7: PolymorphismTi1220 Lecture 7: Polymorphism
Ti1220 Lecture 7: PolymorphismEelco Visser
 
What I learned from Seven Languages in Seven Weeks (IPRUG)
What I learned from Seven Languages in Seven Weeks (IPRUG)What I learned from Seven Languages in Seven Weeks (IPRUG)
What I learned from Seven Languages in Seven Weeks (IPRUG)Kerry Buckley
 
Introduction to clojure
Introduction to clojureIntroduction to clojure
Introduction to clojure
Abbas Raza
 
D-Talk: What's awesome about Ruby 2.x and Rails 4
D-Talk: What's awesome about Ruby 2.x and Rails 4D-Talk: What's awesome about Ruby 2.x and Rails 4
D-Talk: What's awesome about Ruby 2.x and Rails 4
Jan Berdajs
 
Ruby is an Acceptable Lisp
Ruby is an Acceptable LispRuby is an Acceptable Lisp
Ruby is an Acceptable Lisp
Astrails
 

Similar to Property based Testing - generative data & executable domain rules (20)

Everything is Permitted: Extending Built-ins
Everything is Permitted: Extending Built-insEverything is Permitted: Extending Built-ins
Everything is Permitted: Extending Built-ins
 
Scala: A brief tutorial
Scala: A brief tutorialScala: A brief tutorial
Scala: A brief tutorial
 
Functional Operations - Susan Potter
Functional Operations - Susan PotterFunctional Operations - Susan Potter
Functional Operations - Susan Potter
 
Lucene Introduction
Lucene IntroductionLucene Introduction
Lucene Introduction
 
Dynamic Python
Dynamic PythonDynamic Python
Dynamic Python
 
Spock: Test Well and Prosper
Spock: Test Well and ProsperSpock: Test Well and Prosper
Spock: Test Well and Prosper
 
Speaking Scala: Refactoring for Fun and Profit (Workshop)
Speaking Scala: Refactoring for Fun and Profit (Workshop)Speaking Scala: Refactoring for Fun and Profit (Workshop)
Speaking Scala: Refactoring for Fun and Profit (Workshop)
 
(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?
 
Scala Refactoring for Fun and Profit
Scala Refactoring for Fun and ProfitScala Refactoring for Fun and Profit
Scala Refactoring for Fun and Profit
 
ScalaCheck
ScalaCheckScalaCheck
ScalaCheck
 
Akka Testkit Patterns
Akka Testkit PatternsAkka Testkit Patterns
Akka Testkit Patterns
 
Fire in the type hole
Fire in the type holeFire in the type hole
Fire in the type hole
 
Ruslan Shevchenko - Property based testing
Ruslan Shevchenko - Property based testingRuslan Shevchenko - Property based testing
Ruslan Shevchenko - Property based testing
 
Scala @ TechMeetup Edinburgh
Scala @ TechMeetup EdinburghScala @ TechMeetup Edinburgh
Scala @ TechMeetup Edinburgh
 
Ti1220 Lecture 7: Polymorphism
Ti1220 Lecture 7: PolymorphismTi1220 Lecture 7: Polymorphism
Ti1220 Lecture 7: Polymorphism
 
What I learned from Seven Languages in Seven Weeks (IPRUG)
What I learned from Seven Languages in Seven Weeks (IPRUG)What I learned from Seven Languages in Seven Weeks (IPRUG)
What I learned from Seven Languages in Seven Weeks (IPRUG)
 
Introduction to clojure
Introduction to clojureIntroduction to clojure
Introduction to clojure
 
D-Talk: What's awesome about Ruby 2.x and Rails 4
D-Talk: What's awesome about Ruby 2.x and Rails 4D-Talk: What's awesome about Ruby 2.x and Rails 4
D-Talk: What's awesome about Ruby 2.x and Rails 4
 
ppopoff
ppopoffppopoff
ppopoff
 
Ruby is an Acceptable Lisp
Ruby is an Acceptable LispRuby is an Acceptable Lisp
Ruby is an Acceptable Lisp
 

More from Debasish Ghosh

Functional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 WayFunctional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 Way
Debasish Ghosh
 
Algebraic Thinking for Evolution of Pure Functional Domain Models
Algebraic Thinking for Evolution of Pure Functional Domain ModelsAlgebraic Thinking for Evolution of Pure Functional Domain Models
Algebraic Thinking for Evolution of Pure Functional Domain Models
Debasish Ghosh
 
Power of functions in a typed world
Power of functions in a typed worldPower of functions in a typed world
Power of functions in a typed world
Debasish Ghosh
 
Approximation Data Structures for Streaming Applications
Approximation Data Structures for Streaming ApplicationsApproximation Data Structures for Streaming Applications
Approximation Data Structures for Streaming Applications
Debasish Ghosh
 
Functional and Algebraic Domain Modeling
Functional and Algebraic Domain ModelingFunctional and Algebraic Domain Modeling
Functional and Algebraic Domain Modeling
Debasish Ghosh
 
Architectural Patterns in Building Modular Domain Models
Architectural Patterns in Building Modular Domain ModelsArchitectural Patterns in Building Modular Domain Models
Architectural Patterns in Building Modular Domain Models
Debasish Ghosh
 
Mining Functional Patterns
Mining Functional PatternsMining Functional Patterns
Mining Functional Patterns
Debasish Ghosh
 
An Algebraic Approach to Functional Domain Modeling
An Algebraic Approach to Functional Domain ModelingAn Algebraic Approach to Functional Domain Modeling
An Algebraic Approach to Functional Domain Modeling
Debasish Ghosh
 
Functional and Algebraic Domain Modeling
Functional and Algebraic Domain ModelingFunctional and Algebraic Domain Modeling
Functional and Algebraic Domain Modeling
Debasish Ghosh
 
From functional to Reactive - patterns in domain modeling
From functional to Reactive - patterns in domain modelingFrom functional to Reactive - patterns in domain modeling
From functional to Reactive - patterns in domain modeling
Debasish Ghosh
 
Domain Modeling with Functions - an algebraic approach
Domain Modeling with Functions - an algebraic approachDomain Modeling with Functions - an algebraic approach
Domain Modeling with Functions - an algebraic approach
Debasish Ghosh
 
Functional Patterns in Domain Modeling
Functional Patterns in Domain ModelingFunctional Patterns in Domain Modeling
Functional Patterns in Domain Modeling
Debasish Ghosh
 
Big Data - architectural concerns for the new age
Big Data - architectural concerns for the new ageBig Data - architectural concerns for the new age
Big Data - architectural concerns for the new age
Debasish Ghosh
 
Domain Modeling in a Functional World
Domain Modeling in a Functional WorldDomain Modeling in a Functional World
Domain Modeling in a Functional World
Debasish Ghosh
 
Functional and Event Driven - another approach to domain modeling
Functional and Event Driven - another approach to domain modelingFunctional and Event Driven - another approach to domain modeling
Functional and Event Driven - another approach to domain modeling
Debasish Ghosh
 
DSL - expressive syntax on top of a clean semantic model
DSL - expressive syntax on top of a clean semantic modelDSL - expressive syntax on top of a clean semantic model
DSL - expressive syntax on top of a clean semantic model
Debasish Ghosh
 
Dependency Injection in Scala - Beyond the Cake Pattern
Dependency Injection in Scala - Beyond the Cake PatternDependency Injection in Scala - Beyond the Cake Pattern
Dependency Injection in Scala - Beyond the Cake Pattern
Debasish Ghosh
 

More from Debasish Ghosh (17)

Functional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 WayFunctional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 Way
 
Algebraic Thinking for Evolution of Pure Functional Domain Models
Algebraic Thinking for Evolution of Pure Functional Domain ModelsAlgebraic Thinking for Evolution of Pure Functional Domain Models
Algebraic Thinking for Evolution of Pure Functional Domain Models
 
Power of functions in a typed world
Power of functions in a typed worldPower of functions in a typed world
Power of functions in a typed world
 
Approximation Data Structures for Streaming Applications
Approximation Data Structures for Streaming ApplicationsApproximation Data Structures for Streaming Applications
Approximation Data Structures for Streaming Applications
 
Functional and Algebraic Domain Modeling
Functional and Algebraic Domain ModelingFunctional and Algebraic Domain Modeling
Functional and Algebraic Domain Modeling
 
Architectural Patterns in Building Modular Domain Models
Architectural Patterns in Building Modular Domain ModelsArchitectural Patterns in Building Modular Domain Models
Architectural Patterns in Building Modular Domain Models
 
Mining Functional Patterns
Mining Functional PatternsMining Functional Patterns
Mining Functional Patterns
 
An Algebraic Approach to Functional Domain Modeling
An Algebraic Approach to Functional Domain ModelingAn Algebraic Approach to Functional Domain Modeling
An Algebraic Approach to Functional Domain Modeling
 
Functional and Algebraic Domain Modeling
Functional and Algebraic Domain ModelingFunctional and Algebraic Domain Modeling
Functional and Algebraic Domain Modeling
 
From functional to Reactive - patterns in domain modeling
From functional to Reactive - patterns in domain modelingFrom functional to Reactive - patterns in domain modeling
From functional to Reactive - patterns in domain modeling
 
Domain Modeling with Functions - an algebraic approach
Domain Modeling with Functions - an algebraic approachDomain Modeling with Functions - an algebraic approach
Domain Modeling with Functions - an algebraic approach
 
Functional Patterns in Domain Modeling
Functional Patterns in Domain ModelingFunctional Patterns in Domain Modeling
Functional Patterns in Domain Modeling
 
Big Data - architectural concerns for the new age
Big Data - architectural concerns for the new ageBig Data - architectural concerns for the new age
Big Data - architectural concerns for the new age
 
Domain Modeling in a Functional World
Domain Modeling in a Functional WorldDomain Modeling in a Functional World
Domain Modeling in a Functional World
 
Functional and Event Driven - another approach to domain modeling
Functional and Event Driven - another approach to domain modelingFunctional and Event Driven - another approach to domain modeling
Functional and Event Driven - another approach to domain modeling
 
DSL - expressive syntax on top of a clean semantic model
DSL - expressive syntax on top of a clean semantic modelDSL - expressive syntax on top of a clean semantic model
DSL - expressive syntax on top of a clean semantic model
 
Dependency Injection in Scala - Beyond the Cake Pattern
Dependency Injection in Scala - Beyond the Cake PatternDependency Injection in Scala - Beyond the Cake Pattern
Dependency Injection in Scala - Beyond the Cake Pattern
 

Recently uploaded

Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
Fermin Galan
 
Fundamentals of Programming and Language Processors
Fundamentals of Programming and Language ProcessorsFundamentals of Programming and Language Processors
Fundamentals of Programming and Language Processors
Rakesh Kumar R
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
Adele Miller
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Mind IT Systems
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
Boni García
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
rickgrimesss22
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
Donna Lenk
 
AI Genie Review: World’s First Open AI WordPress Website Creator
AI Genie Review: World’s First Open AI WordPress Website CreatorAI Genie Review: World’s First Open AI WordPress Website Creator
AI Genie Review: World’s First Open AI WordPress Website Creator
Google
 
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Łukasz Chruściel
 
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
Alina Yurenko
 
Using Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional SafetyUsing Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional Safety
Ayan Halder
 
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Crescat
 
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket ManagementUtilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate
 
Launch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in MinutesLaunch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in Minutes
Roshan Dwivedi
 
Atelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissancesAtelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissances
Neo4j
 
Empowering Growth with Best Software Development Company in Noida - Deuglo
Empowering Growth with Best Software  Development Company in Noida - DeugloEmpowering Growth with Best Software  Development Company in Noida - Deuglo
Empowering Growth with Best Software Development Company in Noida - Deuglo
Deuglo Infosystem Pvt Ltd
 
Graspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code AnalysisGraspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code Analysis
Aftab Hussain
 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOMLORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
lorraineandreiamcidl
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
Łukasz Chruściel
 
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
Google
 

Recently uploaded (20)

Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
 
Fundamentals of Programming and Language Processors
Fundamentals of Programming and Language ProcessorsFundamentals of Programming and Language Processors
Fundamentals of Programming and Language Processors
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
 
AI Genie Review: World’s First Open AI WordPress Website Creator
AI Genie Review: World’s First Open AI WordPress Website CreatorAI Genie Review: World’s First Open AI WordPress Website Creator
AI Genie Review: World’s First Open AI WordPress Website Creator
 
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
 
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
 
Using Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional SafetyUsing Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional Safety
 
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
 
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket ManagementUtilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
 
Launch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in MinutesLaunch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in Minutes
 
Atelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissancesAtelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissances
 
Empowering Growth with Best Software Development Company in Noida - Deuglo
Empowering Growth with Best Software  Development Company in Noida - DeugloEmpowering Growth with Best Software  Development Company in Noida - Deuglo
Empowering Growth with Best Software Development Company in Noida - Deuglo
 
Graspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code AnalysisGraspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code Analysis
 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOMLORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
 
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
 

Property based Testing - generative data & executable domain rules

  • 1. Property based Testing generative data & executable domain rules Debasish Ghosh (@debasishg) Friday, 10 October 14
  • 2. Agenda Why xUnit based testing is not enough What is a property? Properties for free? What to verify in property based testing ScalaCheck Domain Model Testing Friday, 10 October 14
  • 3. xUnit based testing • Convenient • Widely used • Rich tool support Friday, 10 October 14
  • 4. xUnit based testing • Often grows out of bounds (verbosity), being at a lower level of abstraction • Difficult to manage data/logic isolation • Always scared that I may have missed some edge cases & boundary conditions Friday, 10 October 14
  • 5. // polymorphic list append def append[A](xs: List[A], ys: List[A]): List[A] = { //.. } How do you show the correctness of the above implementation ? Friday, 10 October 14
  • 6. (1) Theorem Proving length [] = 0 (length.1) length (z : zs) = 1 + length zs (length.2) [] ++ zs = zs (++.1) (w : ws) ++ zs = w : (ws ++ zs) (++.2) length ([] ++ ys) = length [] + length ys (base) length (xs ++ ys) = length xs + length ys (hypothesis) Length & Append Induction length ((x : xs) ++ ys) = length (x : xs) + length ys To Prove Friday, 10 October 14
  • 7. Base Case length ([] ++ ys) = length [] + length ys (base) length ([] ++ ys) = length ys (by ++.1) length [] + length ys = 0 + length ys = length ys (by length.1) length [] = 0 (length.1) length (z : zs) = 1 + length zs (length.2) [] ++ zs = zs (++.1) (w : ws) ++ zs = w : (ws ++ zs) (++.2) Friday, 10 October 14
  • 8. Induction length ((x : xs) ++ ys) = length (x : xs) + length ys length ((x : xs) ++ ys) = length (x : (xs ++ ys)) (by ++.2) = 1 + length (xs ++ ys) (by length.2) = 1 + length xs + length ys length (x : xs) + length ys = 1 + length xs + length ys (by length.2) length [] = 0 (length.1) length (z : zs) = 1 + length zs (length.2) [] ++ zs = zs (++.1) (w : ws) ++ zs = w : (ws ++ zs) (++.2) Friday, 10 October 14
  • 9. (2) Use your favorite unit testing library // ScalaTest based assertions List(1,2,3).length + List(4,5).length should equal (append(List(1,2,3), List(4,5)).length) List().length + List(4,5).length should equal (append(List(), List(4,5)).length) List(1,2,3).length + List().length should equal (append(List(1,2,3), List()).length) Friday, 10 October 14
  • 10. • Hard coded data sets • May not be exhaustive • Coverage depends upon the knowledge of the test creator But .. Friday, 10 October 14
  • 11. (3) Use dependent typing - an example of append in Idris, a dependently typed language -- Vectors lists that have size as part of type data Vect : Nat -> Type -> Type where Nil : Vect Z a (::) : a -> Vect k a -> Vect (S k) a -- the app function is correct by construction app : Vect n a -> Vect m a -> Vect (n + m) a app Nil ys = ys app (x :: xs) ys = x :: app xs ys Future ? Friday, 10 October 14
  • 12. • Types depend on values • Powerful constraints encoded within the type signature • Correct by construction - correct before the program runs! Future ? Friday, 10 October 14
  • 13. • Miles Sabin has been working on shapeless (https://github.com/milessabin/shapeless) • Flavors of dependent typing in Scala • Sized containers, polymorphic function values, heterogeneous lists & a host of other goodness built on top of Scala typesystem today .. Friday, 10 October 14
  • 14. • Till such time the ecosystem matures, we all start programming in dependently typed languages .. • We have better options than using only xUnit based testing .. Mature? Friday, 10 October 14
  • 15. What exactly are we trying to verify ? property("List append adds up the 2 sizes") = forAll((l1: List[Int], l2: List[Int]) => l1.length + l2.length == append(l1, l2).length ) Friday, 10 October 14
  • 16. What exactly are we trying to verify ? property("List append adds up the 2 sizes") = forAll((l1: List[Int], l2: List[Int]) => l1.length + l2.length == append(l1, l2).length ) invariant of our function encoded as a generic property Friday, 10 October 14
  • 17. What is a property? • Constraints and invariants that must be honored within the bounded context of the model • Sometimes called “laws” or the “algebra” • Ensures well-formed-ness of abstractions Friday, 10 October 14
  • 18. A Monoid An algebraic structure having • an identity element • a binary associative operation trait Monoid[A] { def zero: A def op(l: A, r: => A): A } object MonoidLaws { def associative[A: Equal: Monoid] (a1: A, a2: A, a3: A): Boolean = //.. def rightIdentity[A: Equal: Monoid] (a: A) = //.. def leftIdentity[A: Equal: Monoid] (a: A) = //.. } Friday, 10 October 14
  • 19. Monoid Laws An algebraic structure havingsa • an identity element • a binary associative operation trait Monoid[A] { def zero: A def op(l: A, r: => A): A } object MonoidLaws { def associative[A: Equal: Monoid] (a1: A, a2: A, a3: A): Boolean = //.. def rightIdentity[A: Equal: Monoid] (a: A) = //.. def leftIdentity[A: Equal: Monoid] (a: A) = //.. } satisfies op(x, zero) == x and op(zero, x) == x satisfies op(op(x, y), z) == op(x, op(y, z)) Friday, 10 October 14
  • 20. • Every monoid that you define must honor all the laws of the abstraction • The question is how do we verify that all laws are satisfied it’s the LAW Friday, 10 October 14
  • 21. But before that another important important question is what properties do we need to verify .. Friday, 10 October 14
  • 22. def f[A](a: A): A •The function f takes as input a value and returns a value of the same type • But we don’t know the exact type of A • Hence we cannot do any type specific operation within f •All we know is that f is a polymorphic function parameterized on type A, that returns the same type as the input •A little thought makes us realize that the only possible implementation of f is that of an identity function Friday, 10 October 14
  • 23. def f[A](a: A): A = a •This is the only possible implementation of f (unless we decide to launch a missile and do all evil stuff like throwing exceptions or do typecasing) • If the type-checker checks it ok, we are done.The compiler has proved the theorem and we don’t need to verify the property ourselves • So we have proved a theorem out of the types - this technique is called parametricity and PhilWadler calls these free theorems Fast and Loose Reasoning is Morally Correct (2006) by by Nils Anders Danielsson, John Hughes, Jeremy Gibbons, Patrik Jansson (http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.59.8232) Friday, 10 October 14
  • 24. Free theorems are ensured by the type- checker in a statically typed language that supports parametric polymorphism and we don’t need to write tests for verifying any of those properties Theorems for Free! by Phil Wadler (http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.38.9875) Friday, 10 October 14
  • 25. Parametricity tests a lot of properties in your model. “Parametricity constantly tests more conditions than your unit test suite ever will” - Edward Kmett on #scala Friday, 10 October 14
  • 26. What properties do we need to verify ? Friday, 10 October 14
  • 27. Summarizing .. • if your programming language has a decent static type system and • support for parametric polymorphism and • you play to the rules of parametricity • .... Friday, 10 October 14
  • 28. Summarizing .. • if your programming language has a decent static type system and • support for parametric polymorphism and • you play to the rules of parametricity • .... You get a lot of properties verified for FREE Friday, 10 October 14
  • 29. • Property based testing library for Scala (and also for Java) • Inspired by QuickCheck (Erlang & Haskell) • Works on property specifications • Does automatic data generation ScalaCheck .. Friday, 10 October 14
  • 30. ScalaCheck • You specify the property to be tested • ScalaCheck verifies that the property holds by generating random data • No burden on programmer to maintain data, no fear of missed edge cases Friday, 10 October 14
  • 31. “Property-based testing encourages a high level approach to testing in the form of abstract invariants functions should satisfy universally, with the actual test data generated for the programmer by the testing library. In this way code can be hammered with thousands of tests that would be infeasible to write by hand, often uncovering subtle corner cases that wouldn't be found otherwise.” Real World Haskell by Bryan O’Sullivan, Don Stewart & John Goerzen Friday, 10 October 14
  • 32. scala> import org.scalacheck._ import org.scalacheck._ scala> import Prop.forAll import Prop.forAll scala> forAll((l1: List[Int], l2: List[Int]) => | l1.length + l2.length == append(l1, l2).length | ) res5: org.scalacheck.Prop = Prop scala> res5.check + OK, passed 100 tests. generates 100 test cases randomly and verifies the property specification of the property to be verified Verifying properties universal quantifier Friday, 10 October 14
  • 33. scala> val propSqrt = forAll { (n: Int) => scala.math.sqrt(n*n) == n } propSqrt: org.scalacheck.Prop = Prop scala> propSqrt.check ! Falsified after 0 passed tests. > ARG_0: -2147483648 scala> propSqrt.check ! Falsified after 0 passed tests. > ARG_0: -1 not only says that the property fails, but also points to failure data set Verifying properties A word about minimization of test cases. Whenever a property fails, scalacheck starts shrinking the test cases until it finds the minimal failing test case.This is a huge feature that helps debugging failures Friday, 10 October 14
  • 34. scala> val propSqrt = forAll { (n: Int) => | scala.math.sqrt(n*n) == n | } propSqrt: org.scalacheck.Prop = Prop scala> val smallInteger = Gen.choose(1, 100) smallInteger: org.scalacheck.Gen[Int] = .. scala> val propSmallInteger = forAll(smallInteger)(n => | n >= 0 && n <= 100 | ) propSmallInteger: org.scalacheck.Prop = Prop uses default data generator custom generator forAll uses the custom generator Custom generators Friday, 10 October 14
  • 35. // generate values in a range Gen.choose(10, 20) // conditional generator Gen.choose(0,200) suchThat (_ % 2 == 0) // generate specific values Gen.oneOf('A' | 'E' | 'I' | 'O' | 'U' | 'Y') // default distribution is random, but you can change val vowel = Gen.frequency( (3, 'A'), (4, 'E'), (2, 'I'), (3, 'O'), (1, 'U'), (1, 'Y') ) // generate containers Gen.containerOf[List,Int](Gen.oneOf(1, 3, 5)) Custom generators Friday, 10 October 14
  • 36. Define your own generator case class Account(no: String, holder: String, openingDate: Date, closeDate: Option[Date]) val genAccount = for { no <- Gen.oneOf("1", "2", "3") nm <- Gen.oneOf("john", "david", "mary") od <- arbitrary[Date] cd <- arbitrary[Option[Date]] } yield Account(no, nm, od, cd) (model) (random data generator) Friday, 10 October 14
  • 37. Define your own generator sealed abstract class Tree case object Leaf extends Tree case class Node(left: Tree, right: Tree, v: Int) extends Tree val genLeaf = value(Leaf) val genNode = for { v <- arbitrary[Int] left <- genTree right <- genTree } yield Node(left, right, v) def genTree: Gen[Tree] = oneOf(genLeaf, genNode) (model) (random data generator) Friday, 10 October 14
  • 38. implicit val arbAccount: Arbitrary[Account] = Arbitrary { for { no <- Gen.oneOf("1", "2", "3") nm <- Gen.oneOf("john", "david", "mary") od <- arbitrary[Date] } yield checkingAccount(no, nm, od) } implicit val arbCcy: Arbitrary[Currency] = Arbitrary { Gen.oneOf(USD, SGD, AUD, INR) } implicit val arbMoney = Arbitrary { for { a <- Gen.oneOf(1 to 10) c <- arbitrary[Currency] } yield Money(a, c) } implicit val arbPosition: Arbitrary[Position] = Arbitrary { for { a <- arbitrary[Account] m <- arbitrary[Money] d <- arbitrary[Date] } yield Position(a, m, d) } Arbitrary is a special generator that scalacheck uses to generate random data. Need to specify an implicit Arbitrary instance of your specific data type which can be used to generate data Domain Model Testing Friday, 10 October 14
  • 39. property("Equal debit & credit retains the same position") = forAll((a: Account, c: Currency, d: Date, i: BigDecimal) => { val Success((before, after)) = for { p <- position(a, c, d) r <- credit(p, Money(i, c), d) q <- debit(r, Money(i, c), d) } yield (q, p) before == after }) property("Can close account with close date > opening date") = forAll((a: Account) => close(a, new Date(a.openingDate.getTime + 10000)).isSuccess == true ) property("Cannot close account with close date < opening date") = forAll((a: Account) => close(a, new Date(a.openingDate.getTime - 10000)).isSuccess == false ) Domain Model Testing Verify your business rules and document them too Friday, 10 October 14
  • 40. Some other features • Sized generators - restrict the set of generated data • Conditional generators - use combinators to specify filters • Classify generated test data to see statistical distribution Friday, 10 October 14
  • 41. Some other features • Test case minimization for failed tests • Stateful testing - not only queries, but commands as well in the CQRS sense of the term Friday, 10 October 14
  • 42. Essence of property based testing • Identify constraints & invariants of your abstraction that must hold within your domain model • Encode them as “properties” in your code (not as dumb documents) • Execute properties to verify the correctness of your abstraction Friday, 10 October 14
  • 43. Essence of property based testing • In testing domain models, properties help you think at a higher level of abstraction • Basically you encode domain rules as properties and verify them using data generators that use the domain model itself • Executable domain rules Friday, 10 October 14
  • 44. Property based testing & Functional programs • Functional programs are easier to test & debug (no global state) • Makes a good case for property based testing (immutable data, pure functions) • Usually concise & modular - easier to identify properties Friday, 10 October 14