SlideShare uma empresa Scribd logo
1 de 68
Baixar para ler offline
Thinking in Properties
And Beyond (Testing)
Susan Potter
2020-08-01
Intro
Intro
finger $(whoami)
• Introduced to QuickCheck in Erlang ~2010
• Adopted Haskell’s QuickCheck, Hedgehog, and ScalaCheck at work
• ”Testing” in production, thinking in properties, 4 years
Susan Potter Thinking in Properties 2020-08-01 1 / 41
Intro
Agenda
• An Origin Story (with code)
• Mental Models (above the code)
• Beyond Testing (illustrations)
Susan Potter Thinking in Properties 2020-08-01 2 / 41
An Origin Story
An Origin Story Discovering Superpowers
Susan Potter Thinking in Properties 2020-08-01 3 / 41
An Origin Story Discovering Superpowers
Explore domain with types
data List a = EmptyList | Cons a (List a)
type Pred a = (a -> Bool)
type Comp a = (a -> a -> Ordering)
sortBy :: Comp a -> List a -> List a
filter :: Pred a -> List a -> List a
reverse :: List a -> List a
last, first :: List a -> Maybe a
Susan Potter Thinking in Properties 2020-08-01 3 / 41
An Origin Story Discovering Superpowers
Explore domain with usage examples
-- | Reverse the elements of a list
-- >>> reverse (Cons 1 (Cons 2 (Cons 3
EmptyList)))→
-- Cons 3 (Cons 2 (Cons 1 EmptyList))
--
-- >>> reverse EmptyList
-- EmptyList
reverse :: List a -> List a
Susan Potter Thinking in Properties 2020-08-01 4 / 41
An Origin Story Discovering Superpowers
Encode examples as re-runnable tests
describe "Lib.reverse" $ do
it "returns [5,4,3,2,1] given [1,2,3,4,5]" $ do
reverse [1,2,3,4,5] `shouldBe` [5,4,3,2,1]
it "returns empty list given empty list" $ do
reverse [] `shouldBe` []
Susan Potter Thinking in Properties 2020-08-01 5 / 41
An Origin Story Discovering Superpowers
Rinse & Repeat
Susan Potter Thinking in Properties 2020-08-01 6 / 41
An Origin Story Discovering Superpowers
Continuous Learning
Figure 1: Schedule for Erlang Factory SF 2011 where my mind was blown
Susan Potter Thinking in Properties 2020-08-01 7 / 41
An Origin Story Harnessing Newly Found Superpowers
Characteristics of property-based testing
Where we have:
• generators that produce random ”arbitrary” values for inputs
• general rules that hold without knowing inputs upfront
• shrinking of failed values
• test runs assert rule multiple times using new generated values
Related terms: generative testing, fuzz testing (or ”fuzzing”)
Susan Potter Thinking in Properties 2020-08-01 8 / 41
An Origin Story Harnessing Newly Found Superpowers
Characteristics of property-based testing
Where we have:
• generators that produce random ”arbitrary” values for inputs
• general rules that hold without knowing inputs upfront
• shrinking of failed values
• test runs assert rule multiple times using new generated values
Related terms: generative testing, fuzz testing (or ”fuzzing”)
Susan Potter Thinking in Properties 2020-08-01 8 / 41
An Origin Story Harnessing Newly Found Superpowers
Characteristics of property-based testing
Where we have:
• generators that produce random ”arbitrary” values for inputs
• general rules that hold without knowing inputs upfront
• shrinking of failed values
• test runs assert rule multiple times using new generated values
Related terms: generative testing, fuzz testing (or ”fuzzing”)
Susan Potter Thinking in Properties 2020-08-01 8 / 41
An Origin Story Harnessing Newly Found Superpowers
Characteristics of property-based testing
Where we have:
• generators that produce random ”arbitrary” values for inputs
• general rules that hold without knowing inputs upfront
• shrinking of failed values
• test runs assert rule multiple times using new generated values
Related terms: generative testing, fuzz testing (or ”fuzzing”)
Susan Potter Thinking in Properties 2020-08-01 8 / 41
An Origin Story Harnessing Newly Found Superpowers
One General Rule: Round-tripping (two rides gets us back home)
Examples:
-- Assumes x is encodable and decodable
roundtrip0 = x -> decode (encode x) == Just x
roundtrip1 = x -> decodeBase64 (encodeBase64 x) == Right x
Counter-examples:
• sha256 is one way!
Susan Potter Thinking in Properties 2020-08-01 9 / 41
An Origin Story Harnessing Newly Found Superpowers
Introducing generators
To make these ideas concrete we will be using hedgehog with these imports:
import Hedgehog
import qualified Hedgehog.Gen as Gen
import qualified Hedgehog.Range as Range
import Control.Monad (replicateM)
import Data.Function (($), (.))
Hedgehog integrates shrinking with generation. We will not discuss this difference to QuickCheck but read Well Typed’s blog post about this here.
Susan Potter Thinking in Properties 2020-08-01 10 / 41
An Origin Story Harnessing Newly Found Superpowers
Primitive generators by example
>>> replicateM 25 $ Gen.sample Gen.lower
"okohcpxrkfunkmwnqujnnhxkg"
>>> let currencies = [ "USD", "JPY", "EUR", "CHF", "CNY" ]
>>> replicateM 5 $ Gen.sample $ Gen.element currencies
["USD","CNY","USD","JPY","USD"]
>>> replicateM 5 $ Gen.sample $ Gen.choice [ Gen.ascii,
Gen.unicode ]→
['f', 'c', 'j', '1068213', '<']
Susan Potter Thinking in Properties 2020-08-01 11 / 41
An Origin Story Harnessing Newly Found Superpowers
Generating your domain’s data, 1/2
Suppose our domain looks like this:
import Data.Word (Word8, Word16)
type W16 = Word16
data IP
= IPv4 Word8 Word8 Word8 Word8
| IPv6 W16 W16 W16 W16 W16 W16 W16 W16
Susan Potter Thinking in Properties 2020-08-01 12 / 41
An Origin Story Harnessing Newly Found Superpowers
Generating your domain’s data, 2/2
genW8 = Gen.word8 Range.constantBounded
genW16 = Gen.word16 Range.constantBounded
genIPv4 = IPv4 <$> genW8 <*> genW8 <*> genW8 <*> genW8
genIPv6 = IPv6 <$> genW16 <*> genW16 <*> genW16 <*> genW16
<*> genW16 <*> genW16 <*> genW16 <*> genW16
genAnyIP = Gen.choice [ genIPv4, genIPv6 ]
sampleIPs n = replicateM n (Gen.sample genAnyIP)
Susan Potter Thinking in Properties 2020-08-01 13 / 41
An Origin Story Harnessing Newly Found Superpowers
Sampling generated domain data
>>> sampleIPs 3
[ "136.59.149.200"
, "338d:2397:f612:e036:b27c:2298:4db8:b933"
, "5.38.65.204" ]
Susan Potter Thinking in Properties 2020-08-01 14 / 41
An Origin Story Harnessing Newly Found Superpowers
Writing Our First Property!
genList :: MonadGen m => m a -> m [a]
genList = Gen.list (Range.linear 0 1000)
genInt = Gen.int (Range.linear 0 100000)
-- "round-tripping" property
prop_reverse_reverse = property $ do
xs <- forAll $ genList genInt
Lib.reverse (Lib.reverse xs) === xs
Susan Potter Thinking in Properties 2020-08-01 15 / 41
An Origin Story Harnessing Newly Found Superpowers
Reviewing Our First Property!
Questions about prop_reverse_reverse:
• Does it assert anything about reverse ’s specification?
• Do callers of reverse need to exploit ”round-tripping”?
• Does an implementation exist that typechecks yet fails this property?
• Are we generating interesting data given the operation’s type?
• Are we resigned to function-level property testing?
Susan Potter Thinking in Properties 2020-08-01 16 / 41
An Origin Story Harnessing Newly Found Superpowers
Reviewing Our First Property!
Questions about prop_reverse_reverse:
• Does it assert anything about reverse ’s specification?
• Do callers of reverse need to exploit ”round-tripping”?
• Does an implementation exist that typechecks yet fails this property?
• Are we generating interesting data given the operation’s type?
• Are we resigned to function-level property testing?
Susan Potter Thinking in Properties 2020-08-01 16 / 41
An Origin Story Harnessing Newly Found Superpowers
Reviewing Our First Property!
Questions about prop_reverse_reverse:
• Does it assert anything about reverse ’s specification?
• Do callers of reverse need to exploit ”round-tripping”?
• Does an implementation exist that typechecks yet fails this property?
• Are we generating interesting data given the operation’s type?
• Are we resigned to function-level property testing?
Susan Potter Thinking in Properties 2020-08-01 16 / 41
An Origin Story Harnessing Newly Found Superpowers
Reviewing Our First Property!
Questions about prop_reverse_reverse:
• Does it assert anything about reverse ’s specification?
• Do callers of reverse need to exploit ”round-tripping”?
• Does an implementation exist that typechecks yet fails this property?
• Are we generating interesting data given the operation’s type?
• Are we resigned to function-level property testing?
Susan Potter Thinking in Properties 2020-08-01 16 / 41
An Origin Story Harnessing Newly Found Superpowers
Reviewing Our First Property!
Questions about prop_reverse_reverse:
• Does it assert anything about reverse ’s specification?
• Do callers of reverse need to exploit ”round-tripping”?
• Does an implementation exist that typechecks yet fails this property?
• Are we generating interesting data given the operation’s type?
• Are we resigned to function-level property testing?
Susan Potter Thinking in Properties 2020-08-01 16 / 41
An Origin Story Harnessing Newly Found Superpowers
Quick Review: Example-based tests over time
t ~ 0 → t → ∞
Quick ⌣ →  / ⌢
Coverage ? →  / ⌢
Repeatable ⌣ →  / ⌢
Documents usage  →  / ⌢
Documents contract ⌢ → ⌢
Effort  →  / ⌢
• can measure coverage
• fixtures provide test data
• interesting fixtures brittle
• over time tends to ⌢
Susan Potter Thinking in Properties 2020-08-01 17 / 41
An Origin Story Harnessing Newly Found Superpowers
Quick Review: Example-based tests over time
t ~ 0 → t → ∞
Quick ⌣ →  / ⌢
Coverage ? →  / ⌢
Repeatable ⌣ →  / ⌢
Documents usage  →  / ⌢
Documents contract ⌢ → ⌢
Effort  →  / ⌢
• can measure coverage
• fixtures provide test data
• interesting fixtures brittle
• over time tends to ⌢
Susan Potter Thinking in Properties 2020-08-01 17 / 41
An Origin Story Harnessing Newly Found Superpowers
Quick Review: Example-based tests over time
t ~ 0 → t → ∞
Quick ⌣ →  / ⌢
Coverage ? →  / ⌢
Repeatable ⌣ →  / ⌢
Documents usage  →  / ⌢
Documents contract ⌢ → ⌢
Effort  →  / ⌢
• can measure coverage
• fixtures provide test data
• interesting fixtures brittle
• over time tends to ⌢
Susan Potter Thinking in Properties 2020-08-01 17 / 41
An Origin Story Harnessing Newly Found Superpowers
Quick Review: Example-based tests over time
t ~ 0 → t → ∞
Quick ⌣ →  / ⌢
Coverage ? →  / ⌢
Repeatable ⌣ →  / ⌢
Documents usage  →  / ⌢
Documents contract ⌢ → ⌢
Effort  →  / ⌢
• can measure coverage
• fixtures provide test data
• interesting fixtures brittle
• over time tends to ⌢
Susan Potter Thinking in Properties 2020-08-01 17 / 41
An Origin Story Harnessing Newly Found Superpowers
Quick Review: Example-based tests over time
t ~ 0 → t → ∞
Quick ⌣ →  / ⌢
Coverage ? →  / ⌢
Repeatable ⌣ →  / ⌢
Documents usage  →  / ⌢
Documents contract ⌢ → ⌢
Effort  →  / ⌢
• can measure coverage
• fixtures provide test data
• interesting fixtures brittle
• over time tends to ⌢
Susan Potter Thinking in Properties 2020-08-01 17 / 41
An Origin Story Harnessing Newly Found Superpowers
Quick Review: Property-based tests initially
t ~ 0
Quick ⌣
Coverage ⌣
Repeatable ⌣
Documents usage 
Documents contract ⌣ / 
Effort ?
• Can we measure coverage ?
• We need to maintain generators
instead of fixtures!
• Not constrained by imagination! ⌣
• Am I smart enough to think up relevant
and meaningful properties ?
Susan Potter Thinking in Properties 2020-08-01 18 / 41
An Origin Story Harnessing Newly Found Superpowers
Quick Review: Property-based tests initially
t ~ 0
Quick ⌣
Coverage ⌣
Repeatable ⌣
Documents usage 
Documents contract ⌣ / 
Effort ?
• Can we measure coverage ?
• We need to maintain generators
instead of fixtures!
• Not constrained by imagination! ⌣
• Am I smart enough to think up relevant
and meaningful properties ?
Susan Potter Thinking in Properties 2020-08-01 18 / 41
An Origin Story Harnessing Newly Found Superpowers
Quick Review: Property-based tests initially
t ~ 0
Quick ⌣
Coverage ⌣
Repeatable ⌣
Documents usage 
Documents contract ⌣ / 
Effort ?
• Can we measure coverage ?
• We need to maintain generators
instead of fixtures!
• Not constrained by imagination! ⌣
• Am I smart enough to think up relevant
and meaningful properties ?
Susan Potter Thinking in Properties 2020-08-01 18 / 41
An Origin Story Harnessing Newly Found Superpowers
Quick Review: Property-based tests initially
t ~ 0
Quick ⌣
Coverage ⌣
Repeatable ⌣
Documents usage 
Documents contract ⌣ / 
Effort ?
• Can we measure coverage ?
• We need to maintain generators
instead of fixtures!
• Not constrained by imagination! ⌣
• Am I smart enough to think up relevant
and meaningful properties ?
Susan Potter Thinking in Properties 2020-08-01 18 / 41
An Origin Story Harnessing Newly Found Superpowers
Quick Review: Property-based tests initially
t ~ 0
Quick ⌣
Coverage ⌣
Repeatable ⌣
Documents usage 
Documents contract ⌣ / 
Effort ?
• Can we measure coverage ?
• We need to maintain generators
instead of fixtures!
• Not constrained by imagination! ⌣
• Am I smart enough to think up relevant
and meaningful properties ?
Susan Potter Thinking in Properties 2020-08-01 18 / 41
Mental Models
Mental Models
Deriving Properties: Algebraic laws
Law What might it be good for
Idempotency e.g. event log effects, REST APIs, config effects
Associativity e.g. map/reduce distribution
Commutativity e.g. map/reduce local parallelism
Distributivity e.g. stable or performant rewrite rules
Identity element e.g. for invariance at that value for operation
Round-tripping e.g. encoding/decoding
Absorption e.g. boolean algebra rewrites
Transitivity e.g. dependency closures
Susan Potter Thinking in Properties 2020-08-01 19 / 41
Mental Models
Algebraic laws: Idempotency (running 1+ times yields same result)
Examples:
idem0 = x -> abs x == abs (abs x)
idem2 = x -> toUpper s == toUpper (toUpper s)
• curl -XPUT https://foo.bar/resource/123 -d baz=qux
Counter-example:
• curl -XPOST https://foo.bar/resource -d baz=qux
Algebra:
Given x ∈ A and f ∈ (A → A) and f(x) = f(f(x)) then f is idempotent.
Susan Potter Thinking in Properties 2020-08-01 20 / 41
Mental Models
Algebraic laws: Associativity (brackets to the left or right)
Examples:
assoc0 = x y z -> (x + y) + z == x + (y + z)
assoc1 = x y z -> (x ++ y) ++ z == x ++ (y ++ z)
Counter-example:
• (x − y) − z = x − (y − z)
Algebra:
Given x, y, z ∈ A, ⊕ ∈ (A → A → A) and (x ⊕ y) ⊕ z = x ⊕ (y ⊕ z) then ⊕ is
associative.
Susan Potter Thinking in Properties 2020-08-01 21 / 41
Mental Models
Algebraic laws: Commutativity (any order will do)
Examples:
comm0 = x y -> x + y == y + x
comm1 = x y -> x * y == y * x
Counter-example:
• x + +y = y + +x
• x − y = y − x
Algebra:
Given x, y ∈ A, ⊕ ∈ (A → A → A) and $x ⊕ y = y ⊕x then ⊕ is commutative.
Susan Potter Thinking in Properties 2020-08-01 22 / 41
Mental Models
Algebraic laws: Distributivity (one operation over another)
Examples:
dist0 = x y z -> x*(y + z) == x*y + x*z
Counter-example:
• x + (y ∗ z) = x + y ∗ x + z where x = 1, y = 2, z = 3
1 + (2 ∗ 3) = 1 + 2 ∗ 1 + 3 ⇒ 7 = 6
Algebra:
Given x, y, z ∈ A and ⊕, ⊗ ∈ (A → A → A) then ⊗ is distributive over ⊕ when
x ⊗ (y ⊕ z) = x ⊗ y ⊕ x ⊗ z
Susan Potter Thinking in Properties 2020-08-01 23 / 41
Mental Models
Algebraic laws: Identity element
Examples:
identity0 = x -> 0 + x == x
identity1 = x -> False || x == x
identity2 = s -> "" ++ s == s
Counter-example:
-NonEmpty does not have an identity element
Algebra:
∃e ∈ A, ∀a ∈ A, e ⊕ a = a then e is the identity element in A.
Susan Potter Thinking in Properties 2020-08-01 24 / 41
Mental Models
Algebraic laws: Absorption
Examples:
absorption0 = a b -> (a || (a && b)) == a
absorption1 = a b -> (a && (a || b)) == a
Algebra: Given ∧, ∨ ∈ (A → A → A) and a, b ∈ A then when
a ∧ (a ∨ b) = a = a ∨ (a ∧ b)
Susan Potter Thinking in Properties 2020-08-01 25 / 41
Mental Models
Deriving Properties: Relational laws
-- implicitly expect sort and last to be correct
prop_max_is_last_of_sort = property $ do
xs <- forAll $ genList Gen.ascii
Just (max xs) === last (sort xs)
prop_last_is_first_of_reversed = property $ do
xs <- forAll $ genList Gen.unicode
last xs === first (reverse xs)
Susan Potter Thinking in Properties 2020-08-01 26 / 41
Mental Models
Deriving Properties: Abstraction laws
Using hedgehog-classes package we can check our typeclass instances
according to the abstraction laws:
import Hedgehog
import Hedgehog.Classes
import qualified Hedgehog.Gen as Gen
import qualified Hedgehog.Range as Range
investmentPortfolioSemigroup
= lawsCheck (semigroupLaws genInvestmentPortfolio)
portfolioFoldable = lawsCheck (foldableLaws genPortfolio)
Susan Potter Thinking in Properties 2020-08-01 27 / 41
Mental Models
Deriving Properties: Reflections, Rotations, Distortions
prop_rotated_colors_same
= property $ do
img <- forAll $ genImage
colors (rotate90 img) === colors img
• normalizing audio shouldn’t change time length
• reversing a list shouldn’t change length
Susan Potter Thinking in Properties 2020-08-01 28 / 41
Mental Models
Deriving Properties: Informal model checking
Sometimes you can model the basic state machine of a system simply:
• model of interesting parts of stateful system
• not exhaustive
• thinking in state machine models
• generate sequence or call graph of commands
• assert pre- and post-conditions or invariants
• careful you don’t write a second implementation of the SUT just to test it!
Susan Potter Thinking in Properties 2020-08-01 29 / 41
Mental Models
Deriving Properties: Legacy oracles
Replacing legacy systems:
• bind to old lib as oracle
• assert new rewritten library matches oracle for same inputs
• good for e.g. calculation engines or data pipelines
• might need large build engineering effort
Susan Potter Thinking in Properties 2020-08-01 30 / 41
Mental Models
Deriving Properties: Does not barf
Wrapping lower-level code via FFI:
• gaps between foreign input or output types and native types
• runtime exceptions thrown for some input values (inform design)
• sanity checking FFI wrapping
Susan Potter Thinking in Properties 2020-08-01 31 / 41
Mental Models
Deriving Properties: Metamorphic relations
• Running against SUT twice with possibly different inputs
• A relation exists between those inputs
• Assert a relation exists between the outputs of those system runs
An example across inputs and outputs, but the relation between inputs and
outputs can be different: x, y ∈ Inputs, x ≤ y, x′
= SUT(x), y′
= SUT(y) then
x′
≤ y′
Susan Potter Thinking in Properties 2020-08-01 32 / 41
Mental Models
Deriving Properties: Metamorphic relation patterns
• Input equivalence
• Shuffling
• Conjunctive conditions
• Disjunctive conditions
• Disjoint partitions
• Complete partitions
• Partition difference
Susan Potter Thinking in Properties 2020-08-01 33 / 41
Mental Models
Deriving Properties: Heckle Yourself!
• mutation testing
• alter your code until your tests fail
• if no tests fail, throw your tests out
(curation)
• question your assumptions
Susan Potter Thinking in Properties 2020-08-01 34 / 41
Beyond testing
Beyond testing
Properties of Delivery Pipelines
Property: Source consistency Ensuring fast-forward only ”merges”:
main() {
local -r mergeBase="$(git merge-base HEAD origin/deploy)"
local -r deployHead="$(git rev-parse origin/deploy)"
test "${mergeBase}" = "${deployHead}"
}
set -e
main
# should exit with 0 for success
Susan Potter Thinking in Properties 2020-08-01 35 / 41
Beyond testing
Stateful Migrations (in production)
Properties: pre and post conditions and invariants between migration phases
• moving a stateful cluster from one datacenter to another
• upgrading Elastic search into a new cluster
• online schema migrations of large tables with binlog syncing and atomic
rename (e.g. MySQL)
Susan Potter Thinking in Properties 2020-08-01 36 / 41
Beyond testing
Stateful Migrations (in production)
Properties: pre and post conditions and invariants between migration phases
• moving a stateful cluster from one datacenter to another
• upgrading Elastic search into a new cluster
• online schema migrations of large tables with binlog syncing and atomic
rename (e.g. MySQL)
Susan Potter Thinking in Properties 2020-08-01 36 / 41
Beyond testing
Stateful Migrations (in production)
Properties: pre and post conditions and invariants between migration phases
• moving a stateful cluster from one datacenter to another
• upgrading Elastic search into a new cluster
• online schema migrations of large tables with binlog syncing and atomic
rename (e.g. MySQL)
Susan Potter Thinking in Properties 2020-08-01 36 / 41
Beyond testing
System Monitoring
Property: Connectedness!
Given public name for service name:
• resolve name to A records (IPs)
• ∀ IPs should negotiate TLS handshake
• ∀ IPs should make HTTP request with Host
Susan Potter Thinking in Properties 2020-08-01 37 / 41
Beyond testing
System Monitoring
Property: Connectedness!
Given public name for service name:
• resolve name to A records (IPs)
• ∀ IPs should negotiate TLS handshake
• ∀ IPs should make HTTP request with Host
Susan Potter Thinking in Properties 2020-08-01 37 / 41
Beyond testing
System Monitoring
Property: Connectedness!
Given public name for service name:
• resolve name to A records (IPs)
• ∀ IPs should negotiate TLS handshake
• ∀ IPs should make HTTP request with Host
Susan Potter Thinking in Properties 2020-08-01 37 / 41
Beyond testing
Production Data Checks
Sometimes your generators don’t generate data you see in production!
Legacy systems exist with no property-based testing toolchain!
• Structured logging can record inputs and results; validate OOB
• Run property checks against production inputs and outputs in Haskell :)
Susan Potter Thinking in Properties 2020-08-01 38 / 41
Wrapping Up
Wrapping Up
In Closing
• Not all properties are useful
• Initially hard to think up useful properties
genMentalModels = Gen.choice [
genAlgebraicLaws, genRelationalLaws,
genAbstrationLaws, genStateMachines,
genMetamorphicRelations,
genHeckleYourCode,
genTestingInProduction
]
Susan Potter Thinking in Properties 2020-08-01 39 / 41
Wrapping Up
In Closing
• Not all properties are useful
• Initially hard to think up useful properties
genMentalModels = Gen.choice [
genAlgebraicLaws, genRelationalLaws,
genAbstrationLaws, genStateMachines,
genMetamorphicRelations,
genHeckleYourCode,
genTestingInProduction
]
Susan Potter Thinking in Properties 2020-08-01 39 / 41
Wrapping Up
Questions?
GitHub @mbbx6spp
LinkedIn /in/susanpotter
Twitter @SusanPotter
Web Personal site
Consulting
Training
Thank you for listening!
Susan Potter Thinking in Properties 2020-08-01 40 / 41
Wrapping Up
Credits
• Photo by Elias Castillo on Unsplash
• Photo by Juan Rumimpunu on Unsplash
• Photo by LinkedIn Sales Navigator on Unsplash
• Photo by Leonardo Sanches on Unsplash
• Photo by Mélissa Jeanty on Unsplash
• Photo by Chris Liverani on Unsplash
• Photo by <a href=”https:
//unsplash.com/@spanic?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText”>Damir Spanic</a>
on <a href=”https://unsplash.com/s/photos/baseball-bat?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=
creditCopyText”>Unsplash</a></span>
• Photo by <a href=”https:
//unsplash.com/@serrah?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText”>Serrah Galos</a>
on <a href=”https://unsplash.com/s/photos/reflection?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=
creditCopyText”>Unsplash</a></span>
• Photo by Sergey Zolkin on Unsplash
• Photo by Roman Mager on Unsplash
• Photo by Miguel Ibáñez on Unsplash
• Photo by Science in HD on Unsplash
• Photo by Steve Douglas on Unsplash
• Photo by Natalie Parham on Unsplash
Susan Potter Thinking in Properties 2020-08-01 41 / 41

Mais conteúdo relacionado

Semelhante a Thinking in Properties

ScalaCheck
ScalaCheckScalaCheck
ScalaCheck
BeScala
 
SplunkLive! Customer Presentation - Cisco Systems, Inc.
SplunkLive! Customer Presentation - Cisco Systems, Inc.SplunkLive! Customer Presentation - Cisco Systems, Inc.
SplunkLive! Customer Presentation - Cisco Systems, Inc.
Splunk
 
Perf onjs final
Perf onjs finalPerf onjs final
Perf onjs final
qi yang
 

Semelhante a Thinking in Properties (20)

Empirical Evaluations in Software Engineering Research: A Personal Perspective
Empirical Evaluations in Software Engineering Research: A Personal PerspectiveEmpirical Evaluations in Software Engineering Research: A Personal Perspective
Empirical Evaluations in Software Engineering Research: A Personal Perspective
 
Goss_ICCVE 2022.pdf
Goss_ICCVE 2022.pdfGoss_ICCVE 2022.pdf
Goss_ICCVE 2022.pdf
 
ScalaCheck
ScalaCheckScalaCheck
ScalaCheck
 
Splunk bsides
Splunk bsidesSplunk bsides
Splunk bsides
 
Invoke-CradleCrafter: Moar PowerShell obFUsk8tion & Detection (@('Tech','niqu...
Invoke-CradleCrafter: Moar PowerShell obFUsk8tion & Detection (@('Tech','niqu...Invoke-CradleCrafter: Moar PowerShell obFUsk8tion & Detection (@('Tech','niqu...
Invoke-CradleCrafter: Moar PowerShell obFUsk8tion & Detection (@('Tech','niqu...
 
Jquery2012 defs
Jquery2012 defsJquery2012 defs
Jquery2012 defs
 
CBDW2014 - MockBox, get ready to mock your socks off!
CBDW2014 - MockBox, get ready to mock your socks off!CBDW2014 - MockBox, get ready to mock your socks off!
CBDW2014 - MockBox, get ready to mock your socks off!
 
Lessons Learnt From Working With Rails
Lessons Learnt From Working With RailsLessons Learnt From Working With Rails
Lessons Learnt From Working With Rails
 
Relatedness-based Multi-Entity Summarization
Relatedness-based Multi-Entity SummarizationRelatedness-based Multi-Entity Summarization
Relatedness-based Multi-Entity Summarization
 
Testing smells
Testing smellsTesting smells
Testing smells
 
Testing Variability-Intensive Systems, tutorial SPLC 2017, part I
Testing Variability-Intensive Systems, tutorial SPLC 2017, part ITesting Variability-Intensive Systems, tutorial SPLC 2017, part I
Testing Variability-Intensive Systems, tutorial SPLC 2017, part I
 
Clean Manifests with Puppet::Tidy
Clean Manifests with Puppet::TidyClean Manifests with Puppet::Tidy
Clean Manifests with Puppet::Tidy
 
SplunkLive! Customer Presentation - Cisco Systems, Inc.
SplunkLive! Customer Presentation - Cisco Systems, Inc.SplunkLive! Customer Presentation - Cisco Systems, Inc.
SplunkLive! Customer Presentation - Cisco Systems, Inc.
 
Refactoring RIA Unleashed 2011
Refactoring RIA Unleashed 2011Refactoring RIA Unleashed 2011
Refactoring RIA Unleashed 2011
 
Splunk Live in RTP - March-2014-Jeff-Bollinger-Cisco
Splunk Live in RTP - March-2014-Jeff-Bollinger-CiscoSplunk Live in RTP - March-2014-Jeff-Bollinger-Cisco
Splunk Live in RTP - March-2014-Jeff-Bollinger-Cisco
 
Apache Kylin - Balance Between Space and Time
Apache Kylin - Balance Between Space and TimeApache Kylin - Balance Between Space and Time
Apache Kylin - Balance Between Space and Time
 
Puppet Roles & Profiles Using Trusted Facts.
Puppet Roles & Profiles Using Trusted Facts.Puppet Roles & Profiles Using Trusted Facts.
Puppet Roles & Profiles Using Trusted Facts.
 
Perf onjs final
Perf onjs finalPerf onjs final
Perf onjs final
 
JSLT: JSON querying and transformation
JSLT: JSON querying and transformationJSLT: JSON querying and transformation
JSLT: JSON querying and transformation
 
ApacheCon Europe 2012 -Big Search 4 Big Data
ApacheCon Europe 2012 -Big Search 4 Big DataApacheCon Europe 2012 -Big Search 4 Big Data
ApacheCon Europe 2012 -Big Search 4 Big Data
 

Mais de Susan Potter

Mais de Susan Potter (17)

Champaign-Urbana Javascript Meetup Talk (Jan 2020)
Champaign-Urbana Javascript Meetup Talk (Jan 2020)Champaign-Urbana Javascript Meetup Talk (Jan 2020)
Champaign-Urbana Javascript Meetup Talk (Jan 2020)
 
From Zero to Haskell: Lessons Learned
From Zero to Haskell: Lessons LearnedFrom Zero to Haskell: Lessons Learned
From Zero to Haskell: Lessons Learned
 
Dynamically scaling a political news and activism hub (up to 5x the traffic i...
Dynamically scaling a political news and activism hub (up to 5x the traffic i...Dynamically scaling a political news and activism hub (up to 5x the traffic i...
Dynamically scaling a political news and activism hub (up to 5x the traffic i...
 
Functional Operations (Functional Programming at Comcast Labs Connect)
Functional Operations (Functional Programming at Comcast Labs Connect)Functional Operations (Functional Programming at Comcast Labs Connect)
Functional Operations (Functional Programming at Comcast Labs Connect)
 
From Zero to Application Delivery with NixOS
From Zero to Application Delivery with NixOSFrom Zero to Application Delivery with NixOS
From Zero to Application Delivery with NixOS
 
From Zero To Production (NixOS, Erlang) @ Erlang Factory SF 2016
From Zero To Production (NixOS, Erlang) @ Erlang Factory SF 2016From Zero To Production (NixOS, Erlang) @ Erlang Factory SF 2016
From Zero To Production (NixOS, Erlang) @ Erlang Factory SF 2016
 
Scalaz By Example (An IO Taster) -- PDXScala Meetup Jan 2014
Scalaz By Example (An IO Taster) -- PDXScala Meetup Jan 2014Scalaz By Example (An IO Taster) -- PDXScala Meetup Jan 2014
Scalaz By Example (An IO Taster) -- PDXScala Meetup Jan 2014
 
Ricon/West 2013: Adventures with Riak Pipe
Ricon/West 2013: Adventures with Riak PipeRicon/West 2013: Adventures with Riak Pipe
Ricon/West 2013: Adventures with Riak Pipe
 
Functional Algebra: Monoids Applied
Functional Algebra: Monoids AppliedFunctional Algebra: Monoids Applied
Functional Algebra: Monoids Applied
 
Why Haskell
Why HaskellWhy Haskell
Why Haskell
 
Dynamo: Not Just For Datastores
Dynamo: Not Just For DatastoresDynamo: Not Just For Datastores
Dynamo: Not Just For Datastores
 
Distributed Developer Workflows using Git
Distributed Developer Workflows using GitDistributed Developer Workflows using Git
Distributed Developer Workflows using Git
 
Link Walking with Riak
Link Walking with RiakLink Walking with Riak
Link Walking with Riak
 
Writing Bullet-Proof Javascript: By Using CoffeeScript
Writing Bullet-Proof Javascript: By Using CoffeeScriptWriting Bullet-Proof Javascript: By Using CoffeeScript
Writing Bullet-Proof Javascript: By Using CoffeeScript
 
Twitter4R OAuth
Twitter4R OAuthTwitter4R OAuth
Twitter4R OAuth
 
Deploying distributed software services to the cloud without breaking a sweat
Deploying distributed software services to the cloud without breaking a sweatDeploying distributed software services to the cloud without breaking a sweat
Deploying distributed software services to the cloud without breaking a sweat
 
Designing for Concurrency
Designing for ConcurrencyDesigning for Concurrency
Designing for Concurrency
 

Último

%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
masabamasaba
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
VictoriaMetrics
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
masabamasaba
 

Último (20)

%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go Platformless
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
 
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
Artyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxArtyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptx
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 

Thinking in Properties

  • 1. Thinking in Properties And Beyond (Testing) Susan Potter 2020-08-01
  • 3. Intro finger $(whoami) • Introduced to QuickCheck in Erlang ~2010 • Adopted Haskell’s QuickCheck, Hedgehog, and ScalaCheck at work • ”Testing” in production, thinking in properties, 4 years Susan Potter Thinking in Properties 2020-08-01 1 / 41
  • 4. Intro Agenda • An Origin Story (with code) • Mental Models (above the code) • Beyond Testing (illustrations) Susan Potter Thinking in Properties 2020-08-01 2 / 41
  • 6. An Origin Story Discovering Superpowers Susan Potter Thinking in Properties 2020-08-01 3 / 41
  • 7. An Origin Story Discovering Superpowers Explore domain with types data List a = EmptyList | Cons a (List a) type Pred a = (a -> Bool) type Comp a = (a -> a -> Ordering) sortBy :: Comp a -> List a -> List a filter :: Pred a -> List a -> List a reverse :: List a -> List a last, first :: List a -> Maybe a Susan Potter Thinking in Properties 2020-08-01 3 / 41
  • 8. An Origin Story Discovering Superpowers Explore domain with usage examples -- | Reverse the elements of a list -- >>> reverse (Cons 1 (Cons 2 (Cons 3 EmptyList)))→ -- Cons 3 (Cons 2 (Cons 1 EmptyList)) -- -- >>> reverse EmptyList -- EmptyList reverse :: List a -> List a Susan Potter Thinking in Properties 2020-08-01 4 / 41
  • 9. An Origin Story Discovering Superpowers Encode examples as re-runnable tests describe "Lib.reverse" $ do it "returns [5,4,3,2,1] given [1,2,3,4,5]" $ do reverse [1,2,3,4,5] `shouldBe` [5,4,3,2,1] it "returns empty list given empty list" $ do reverse [] `shouldBe` [] Susan Potter Thinking in Properties 2020-08-01 5 / 41
  • 10. An Origin Story Discovering Superpowers Rinse & Repeat Susan Potter Thinking in Properties 2020-08-01 6 / 41
  • 11. An Origin Story Discovering Superpowers Continuous Learning Figure 1: Schedule for Erlang Factory SF 2011 where my mind was blown Susan Potter Thinking in Properties 2020-08-01 7 / 41
  • 12. An Origin Story Harnessing Newly Found Superpowers Characteristics of property-based testing Where we have: • generators that produce random ”arbitrary” values for inputs • general rules that hold without knowing inputs upfront • shrinking of failed values • test runs assert rule multiple times using new generated values Related terms: generative testing, fuzz testing (or ”fuzzing”) Susan Potter Thinking in Properties 2020-08-01 8 / 41
  • 13. An Origin Story Harnessing Newly Found Superpowers Characteristics of property-based testing Where we have: • generators that produce random ”arbitrary” values for inputs • general rules that hold without knowing inputs upfront • shrinking of failed values • test runs assert rule multiple times using new generated values Related terms: generative testing, fuzz testing (or ”fuzzing”) Susan Potter Thinking in Properties 2020-08-01 8 / 41
  • 14. An Origin Story Harnessing Newly Found Superpowers Characteristics of property-based testing Where we have: • generators that produce random ”arbitrary” values for inputs • general rules that hold without knowing inputs upfront • shrinking of failed values • test runs assert rule multiple times using new generated values Related terms: generative testing, fuzz testing (or ”fuzzing”) Susan Potter Thinking in Properties 2020-08-01 8 / 41
  • 15. An Origin Story Harnessing Newly Found Superpowers Characteristics of property-based testing Where we have: • generators that produce random ”arbitrary” values for inputs • general rules that hold without knowing inputs upfront • shrinking of failed values • test runs assert rule multiple times using new generated values Related terms: generative testing, fuzz testing (or ”fuzzing”) Susan Potter Thinking in Properties 2020-08-01 8 / 41
  • 16. An Origin Story Harnessing Newly Found Superpowers One General Rule: Round-tripping (two rides gets us back home) Examples: -- Assumes x is encodable and decodable roundtrip0 = x -> decode (encode x) == Just x roundtrip1 = x -> decodeBase64 (encodeBase64 x) == Right x Counter-examples: • sha256 is one way! Susan Potter Thinking in Properties 2020-08-01 9 / 41
  • 17. An Origin Story Harnessing Newly Found Superpowers Introducing generators To make these ideas concrete we will be using hedgehog with these imports: import Hedgehog import qualified Hedgehog.Gen as Gen import qualified Hedgehog.Range as Range import Control.Monad (replicateM) import Data.Function (($), (.)) Hedgehog integrates shrinking with generation. We will not discuss this difference to QuickCheck but read Well Typed’s blog post about this here. Susan Potter Thinking in Properties 2020-08-01 10 / 41
  • 18. An Origin Story Harnessing Newly Found Superpowers Primitive generators by example >>> replicateM 25 $ Gen.sample Gen.lower "okohcpxrkfunkmwnqujnnhxkg" >>> let currencies = [ "USD", "JPY", "EUR", "CHF", "CNY" ] >>> replicateM 5 $ Gen.sample $ Gen.element currencies ["USD","CNY","USD","JPY","USD"] >>> replicateM 5 $ Gen.sample $ Gen.choice [ Gen.ascii, Gen.unicode ]→ ['f', 'c', 'j', '1068213', '<'] Susan Potter Thinking in Properties 2020-08-01 11 / 41
  • 19. An Origin Story Harnessing Newly Found Superpowers Generating your domain’s data, 1/2 Suppose our domain looks like this: import Data.Word (Word8, Word16) type W16 = Word16 data IP = IPv4 Word8 Word8 Word8 Word8 | IPv6 W16 W16 W16 W16 W16 W16 W16 W16 Susan Potter Thinking in Properties 2020-08-01 12 / 41
  • 20. An Origin Story Harnessing Newly Found Superpowers Generating your domain’s data, 2/2 genW8 = Gen.word8 Range.constantBounded genW16 = Gen.word16 Range.constantBounded genIPv4 = IPv4 <$> genW8 <*> genW8 <*> genW8 <*> genW8 genIPv6 = IPv6 <$> genW16 <*> genW16 <*> genW16 <*> genW16 <*> genW16 <*> genW16 <*> genW16 <*> genW16 genAnyIP = Gen.choice [ genIPv4, genIPv6 ] sampleIPs n = replicateM n (Gen.sample genAnyIP) Susan Potter Thinking in Properties 2020-08-01 13 / 41
  • 21. An Origin Story Harnessing Newly Found Superpowers Sampling generated domain data >>> sampleIPs 3 [ "136.59.149.200" , "338d:2397:f612:e036:b27c:2298:4db8:b933" , "5.38.65.204" ] Susan Potter Thinking in Properties 2020-08-01 14 / 41
  • 22. An Origin Story Harnessing Newly Found Superpowers Writing Our First Property! genList :: MonadGen m => m a -> m [a] genList = Gen.list (Range.linear 0 1000) genInt = Gen.int (Range.linear 0 100000) -- "round-tripping" property prop_reverse_reverse = property $ do xs <- forAll $ genList genInt Lib.reverse (Lib.reverse xs) === xs Susan Potter Thinking in Properties 2020-08-01 15 / 41
  • 23. An Origin Story Harnessing Newly Found Superpowers Reviewing Our First Property! Questions about prop_reverse_reverse: • Does it assert anything about reverse ’s specification? • Do callers of reverse need to exploit ”round-tripping”? • Does an implementation exist that typechecks yet fails this property? • Are we generating interesting data given the operation’s type? • Are we resigned to function-level property testing? Susan Potter Thinking in Properties 2020-08-01 16 / 41
  • 24. An Origin Story Harnessing Newly Found Superpowers Reviewing Our First Property! Questions about prop_reverse_reverse: • Does it assert anything about reverse ’s specification? • Do callers of reverse need to exploit ”round-tripping”? • Does an implementation exist that typechecks yet fails this property? • Are we generating interesting data given the operation’s type? • Are we resigned to function-level property testing? Susan Potter Thinking in Properties 2020-08-01 16 / 41
  • 25. An Origin Story Harnessing Newly Found Superpowers Reviewing Our First Property! Questions about prop_reverse_reverse: • Does it assert anything about reverse ’s specification? • Do callers of reverse need to exploit ”round-tripping”? • Does an implementation exist that typechecks yet fails this property? • Are we generating interesting data given the operation’s type? • Are we resigned to function-level property testing? Susan Potter Thinking in Properties 2020-08-01 16 / 41
  • 26. An Origin Story Harnessing Newly Found Superpowers Reviewing Our First Property! Questions about prop_reverse_reverse: • Does it assert anything about reverse ’s specification? • Do callers of reverse need to exploit ”round-tripping”? • Does an implementation exist that typechecks yet fails this property? • Are we generating interesting data given the operation’s type? • Are we resigned to function-level property testing? Susan Potter Thinking in Properties 2020-08-01 16 / 41
  • 27. An Origin Story Harnessing Newly Found Superpowers Reviewing Our First Property! Questions about prop_reverse_reverse: • Does it assert anything about reverse ’s specification? • Do callers of reverse need to exploit ”round-tripping”? • Does an implementation exist that typechecks yet fails this property? • Are we generating interesting data given the operation’s type? • Are we resigned to function-level property testing? Susan Potter Thinking in Properties 2020-08-01 16 / 41
  • 28. An Origin Story Harnessing Newly Found Superpowers Quick Review: Example-based tests over time t ~ 0 → t → ∞ Quick ⌣ →  / ⌢ Coverage ? →  / ⌢ Repeatable ⌣ →  / ⌢ Documents usage  →  / ⌢ Documents contract ⌢ → ⌢ Effort  →  / ⌢ • can measure coverage • fixtures provide test data • interesting fixtures brittle • over time tends to ⌢ Susan Potter Thinking in Properties 2020-08-01 17 / 41
  • 29. An Origin Story Harnessing Newly Found Superpowers Quick Review: Example-based tests over time t ~ 0 → t → ∞ Quick ⌣ →  / ⌢ Coverage ? →  / ⌢ Repeatable ⌣ →  / ⌢ Documents usage  →  / ⌢ Documents contract ⌢ → ⌢ Effort  →  / ⌢ • can measure coverage • fixtures provide test data • interesting fixtures brittle • over time tends to ⌢ Susan Potter Thinking in Properties 2020-08-01 17 / 41
  • 30. An Origin Story Harnessing Newly Found Superpowers Quick Review: Example-based tests over time t ~ 0 → t → ∞ Quick ⌣ →  / ⌢ Coverage ? →  / ⌢ Repeatable ⌣ →  / ⌢ Documents usage  →  / ⌢ Documents contract ⌢ → ⌢ Effort  →  / ⌢ • can measure coverage • fixtures provide test data • interesting fixtures brittle • over time tends to ⌢ Susan Potter Thinking in Properties 2020-08-01 17 / 41
  • 31. An Origin Story Harnessing Newly Found Superpowers Quick Review: Example-based tests over time t ~ 0 → t → ∞ Quick ⌣ →  / ⌢ Coverage ? →  / ⌢ Repeatable ⌣ →  / ⌢ Documents usage  →  / ⌢ Documents contract ⌢ → ⌢ Effort  →  / ⌢ • can measure coverage • fixtures provide test data • interesting fixtures brittle • over time tends to ⌢ Susan Potter Thinking in Properties 2020-08-01 17 / 41
  • 32. An Origin Story Harnessing Newly Found Superpowers Quick Review: Example-based tests over time t ~ 0 → t → ∞ Quick ⌣ →  / ⌢ Coverage ? →  / ⌢ Repeatable ⌣ →  / ⌢ Documents usage  →  / ⌢ Documents contract ⌢ → ⌢ Effort  →  / ⌢ • can measure coverage • fixtures provide test data • interesting fixtures brittle • over time tends to ⌢ Susan Potter Thinking in Properties 2020-08-01 17 / 41
  • 33. An Origin Story Harnessing Newly Found Superpowers Quick Review: Property-based tests initially t ~ 0 Quick ⌣ Coverage ⌣ Repeatable ⌣ Documents usage  Documents contract ⌣ /  Effort ? • Can we measure coverage ? • We need to maintain generators instead of fixtures! • Not constrained by imagination! ⌣ • Am I smart enough to think up relevant and meaningful properties ? Susan Potter Thinking in Properties 2020-08-01 18 / 41
  • 34. An Origin Story Harnessing Newly Found Superpowers Quick Review: Property-based tests initially t ~ 0 Quick ⌣ Coverage ⌣ Repeatable ⌣ Documents usage  Documents contract ⌣ /  Effort ? • Can we measure coverage ? • We need to maintain generators instead of fixtures! • Not constrained by imagination! ⌣ • Am I smart enough to think up relevant and meaningful properties ? Susan Potter Thinking in Properties 2020-08-01 18 / 41
  • 35. An Origin Story Harnessing Newly Found Superpowers Quick Review: Property-based tests initially t ~ 0 Quick ⌣ Coverage ⌣ Repeatable ⌣ Documents usage  Documents contract ⌣ /  Effort ? • Can we measure coverage ? • We need to maintain generators instead of fixtures! • Not constrained by imagination! ⌣ • Am I smart enough to think up relevant and meaningful properties ? Susan Potter Thinking in Properties 2020-08-01 18 / 41
  • 36. An Origin Story Harnessing Newly Found Superpowers Quick Review: Property-based tests initially t ~ 0 Quick ⌣ Coverage ⌣ Repeatable ⌣ Documents usage  Documents contract ⌣ /  Effort ? • Can we measure coverage ? • We need to maintain generators instead of fixtures! • Not constrained by imagination! ⌣ • Am I smart enough to think up relevant and meaningful properties ? Susan Potter Thinking in Properties 2020-08-01 18 / 41
  • 37. An Origin Story Harnessing Newly Found Superpowers Quick Review: Property-based tests initially t ~ 0 Quick ⌣ Coverage ⌣ Repeatable ⌣ Documents usage  Documents contract ⌣ /  Effort ? • Can we measure coverage ? • We need to maintain generators instead of fixtures! • Not constrained by imagination! ⌣ • Am I smart enough to think up relevant and meaningful properties ? Susan Potter Thinking in Properties 2020-08-01 18 / 41
  • 39. Mental Models Deriving Properties: Algebraic laws Law What might it be good for Idempotency e.g. event log effects, REST APIs, config effects Associativity e.g. map/reduce distribution Commutativity e.g. map/reduce local parallelism Distributivity e.g. stable or performant rewrite rules Identity element e.g. for invariance at that value for operation Round-tripping e.g. encoding/decoding Absorption e.g. boolean algebra rewrites Transitivity e.g. dependency closures Susan Potter Thinking in Properties 2020-08-01 19 / 41
  • 40. Mental Models Algebraic laws: Idempotency (running 1+ times yields same result) Examples: idem0 = x -> abs x == abs (abs x) idem2 = x -> toUpper s == toUpper (toUpper s) • curl -XPUT https://foo.bar/resource/123 -d baz=qux Counter-example: • curl -XPOST https://foo.bar/resource -d baz=qux Algebra: Given x ∈ A and f ∈ (A → A) and f(x) = f(f(x)) then f is idempotent. Susan Potter Thinking in Properties 2020-08-01 20 / 41
  • 41. Mental Models Algebraic laws: Associativity (brackets to the left or right) Examples: assoc0 = x y z -> (x + y) + z == x + (y + z) assoc1 = x y z -> (x ++ y) ++ z == x ++ (y ++ z) Counter-example: • (x − y) − z = x − (y − z) Algebra: Given x, y, z ∈ A, ⊕ ∈ (A → A → A) and (x ⊕ y) ⊕ z = x ⊕ (y ⊕ z) then ⊕ is associative. Susan Potter Thinking in Properties 2020-08-01 21 / 41
  • 42. Mental Models Algebraic laws: Commutativity (any order will do) Examples: comm0 = x y -> x + y == y + x comm1 = x y -> x * y == y * x Counter-example: • x + +y = y + +x • x − y = y − x Algebra: Given x, y ∈ A, ⊕ ∈ (A → A → A) and $x ⊕ y = y ⊕x then ⊕ is commutative. Susan Potter Thinking in Properties 2020-08-01 22 / 41
  • 43. Mental Models Algebraic laws: Distributivity (one operation over another) Examples: dist0 = x y z -> x*(y + z) == x*y + x*z Counter-example: • x + (y ∗ z) = x + y ∗ x + z where x = 1, y = 2, z = 3 1 + (2 ∗ 3) = 1 + 2 ∗ 1 + 3 ⇒ 7 = 6 Algebra: Given x, y, z ∈ A and ⊕, ⊗ ∈ (A → A → A) then ⊗ is distributive over ⊕ when x ⊗ (y ⊕ z) = x ⊗ y ⊕ x ⊗ z Susan Potter Thinking in Properties 2020-08-01 23 / 41
  • 44. Mental Models Algebraic laws: Identity element Examples: identity0 = x -> 0 + x == x identity1 = x -> False || x == x identity2 = s -> "" ++ s == s Counter-example: -NonEmpty does not have an identity element Algebra: ∃e ∈ A, ∀a ∈ A, e ⊕ a = a then e is the identity element in A. Susan Potter Thinking in Properties 2020-08-01 24 / 41
  • 45. Mental Models Algebraic laws: Absorption Examples: absorption0 = a b -> (a || (a && b)) == a absorption1 = a b -> (a && (a || b)) == a Algebra: Given ∧, ∨ ∈ (A → A → A) and a, b ∈ A then when a ∧ (a ∨ b) = a = a ∨ (a ∧ b) Susan Potter Thinking in Properties 2020-08-01 25 / 41
  • 46. Mental Models Deriving Properties: Relational laws -- implicitly expect sort and last to be correct prop_max_is_last_of_sort = property $ do xs <- forAll $ genList Gen.ascii Just (max xs) === last (sort xs) prop_last_is_first_of_reversed = property $ do xs <- forAll $ genList Gen.unicode last xs === first (reverse xs) Susan Potter Thinking in Properties 2020-08-01 26 / 41
  • 47. Mental Models Deriving Properties: Abstraction laws Using hedgehog-classes package we can check our typeclass instances according to the abstraction laws: import Hedgehog import Hedgehog.Classes import qualified Hedgehog.Gen as Gen import qualified Hedgehog.Range as Range investmentPortfolioSemigroup = lawsCheck (semigroupLaws genInvestmentPortfolio) portfolioFoldable = lawsCheck (foldableLaws genPortfolio) Susan Potter Thinking in Properties 2020-08-01 27 / 41
  • 48. Mental Models Deriving Properties: Reflections, Rotations, Distortions prop_rotated_colors_same = property $ do img <- forAll $ genImage colors (rotate90 img) === colors img • normalizing audio shouldn’t change time length • reversing a list shouldn’t change length Susan Potter Thinking in Properties 2020-08-01 28 / 41
  • 49. Mental Models Deriving Properties: Informal model checking Sometimes you can model the basic state machine of a system simply: • model of interesting parts of stateful system • not exhaustive • thinking in state machine models • generate sequence or call graph of commands • assert pre- and post-conditions or invariants • careful you don’t write a second implementation of the SUT just to test it! Susan Potter Thinking in Properties 2020-08-01 29 / 41
  • 50. Mental Models Deriving Properties: Legacy oracles Replacing legacy systems: • bind to old lib as oracle • assert new rewritten library matches oracle for same inputs • good for e.g. calculation engines or data pipelines • might need large build engineering effort Susan Potter Thinking in Properties 2020-08-01 30 / 41
  • 51. Mental Models Deriving Properties: Does not barf Wrapping lower-level code via FFI: • gaps between foreign input or output types and native types • runtime exceptions thrown for some input values (inform design) • sanity checking FFI wrapping Susan Potter Thinking in Properties 2020-08-01 31 / 41
  • 52. Mental Models Deriving Properties: Metamorphic relations • Running against SUT twice with possibly different inputs • A relation exists between those inputs • Assert a relation exists between the outputs of those system runs An example across inputs and outputs, but the relation between inputs and outputs can be different: x, y ∈ Inputs, x ≤ y, x′ = SUT(x), y′ = SUT(y) then x′ ≤ y′ Susan Potter Thinking in Properties 2020-08-01 32 / 41
  • 53. Mental Models Deriving Properties: Metamorphic relation patterns • Input equivalence • Shuffling • Conjunctive conditions • Disjunctive conditions • Disjoint partitions • Complete partitions • Partition difference Susan Potter Thinking in Properties 2020-08-01 33 / 41
  • 54. Mental Models Deriving Properties: Heckle Yourself! • mutation testing • alter your code until your tests fail • if no tests fail, throw your tests out (curation) • question your assumptions Susan Potter Thinking in Properties 2020-08-01 34 / 41
  • 56. Beyond testing Properties of Delivery Pipelines Property: Source consistency Ensuring fast-forward only ”merges”: main() { local -r mergeBase="$(git merge-base HEAD origin/deploy)" local -r deployHead="$(git rev-parse origin/deploy)" test "${mergeBase}" = "${deployHead}" } set -e main # should exit with 0 for success Susan Potter Thinking in Properties 2020-08-01 35 / 41
  • 57. Beyond testing Stateful Migrations (in production) Properties: pre and post conditions and invariants between migration phases • moving a stateful cluster from one datacenter to another • upgrading Elastic search into a new cluster • online schema migrations of large tables with binlog syncing and atomic rename (e.g. MySQL) Susan Potter Thinking in Properties 2020-08-01 36 / 41
  • 58. Beyond testing Stateful Migrations (in production) Properties: pre and post conditions and invariants between migration phases • moving a stateful cluster from one datacenter to another • upgrading Elastic search into a new cluster • online schema migrations of large tables with binlog syncing and atomic rename (e.g. MySQL) Susan Potter Thinking in Properties 2020-08-01 36 / 41
  • 59. Beyond testing Stateful Migrations (in production) Properties: pre and post conditions and invariants between migration phases • moving a stateful cluster from one datacenter to another • upgrading Elastic search into a new cluster • online schema migrations of large tables with binlog syncing and atomic rename (e.g. MySQL) Susan Potter Thinking in Properties 2020-08-01 36 / 41
  • 60. Beyond testing System Monitoring Property: Connectedness! Given public name for service name: • resolve name to A records (IPs) • ∀ IPs should negotiate TLS handshake • ∀ IPs should make HTTP request with Host Susan Potter Thinking in Properties 2020-08-01 37 / 41
  • 61. Beyond testing System Monitoring Property: Connectedness! Given public name for service name: • resolve name to A records (IPs) • ∀ IPs should negotiate TLS handshake • ∀ IPs should make HTTP request with Host Susan Potter Thinking in Properties 2020-08-01 37 / 41
  • 62. Beyond testing System Monitoring Property: Connectedness! Given public name for service name: • resolve name to A records (IPs) • ∀ IPs should negotiate TLS handshake • ∀ IPs should make HTTP request with Host Susan Potter Thinking in Properties 2020-08-01 37 / 41
  • 63. Beyond testing Production Data Checks Sometimes your generators don’t generate data you see in production! Legacy systems exist with no property-based testing toolchain! • Structured logging can record inputs and results; validate OOB • Run property checks against production inputs and outputs in Haskell :) Susan Potter Thinking in Properties 2020-08-01 38 / 41
  • 65. Wrapping Up In Closing • Not all properties are useful • Initially hard to think up useful properties genMentalModels = Gen.choice [ genAlgebraicLaws, genRelationalLaws, genAbstrationLaws, genStateMachines, genMetamorphicRelations, genHeckleYourCode, genTestingInProduction ] Susan Potter Thinking in Properties 2020-08-01 39 / 41
  • 66. Wrapping Up In Closing • Not all properties are useful • Initially hard to think up useful properties genMentalModels = Gen.choice [ genAlgebraicLaws, genRelationalLaws, genAbstrationLaws, genStateMachines, genMetamorphicRelations, genHeckleYourCode, genTestingInProduction ] Susan Potter Thinking in Properties 2020-08-01 39 / 41
  • 67. Wrapping Up Questions? GitHub @mbbx6spp LinkedIn /in/susanpotter Twitter @SusanPotter Web Personal site Consulting Training Thank you for listening! Susan Potter Thinking in Properties 2020-08-01 40 / 41
  • 68. Wrapping Up Credits • Photo by Elias Castillo on Unsplash • Photo by Juan Rumimpunu on Unsplash • Photo by LinkedIn Sales Navigator on Unsplash • Photo by Leonardo Sanches on Unsplash • Photo by Mélissa Jeanty on Unsplash • Photo by Chris Liverani on Unsplash • Photo by <a href=”https: //unsplash.com/@spanic?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText”>Damir Spanic</a> on <a href=”https://unsplash.com/s/photos/baseball-bat?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content= creditCopyText”>Unsplash</a></span> • Photo by <a href=”https: //unsplash.com/@serrah?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText”>Serrah Galos</a> on <a href=”https://unsplash.com/s/photos/reflection?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content= creditCopyText”>Unsplash</a></span> • Photo by Sergey Zolkin on Unsplash • Photo by Roman Mager on Unsplash • Photo by Miguel Ibáñez on Unsplash • Photo by Science in HD on Unsplash • Photo by Steve Douglas on Unsplash • Photo by Natalie Parham on Unsplash Susan Potter Thinking in Properties 2020-08-01 41 / 41