For All C or All Code ode, , Ther here Exist P e Exist Proper - - PowerPoint PPT Presentation

for all c or all code ode ther here exist p e exist
SMART_READER_LITE
LIVE PREVIEW

For All C or All Code ode, , Ther here Exist P e Exist Proper - - PowerPoint PPT Presentation

For All C or All Code ode, , Ther here Exist P e Exist Proper operties t ties to be Check o be Checked ed (or or, r , random t andom testing with FsCheck) esting with FsCheck) Paulmichael Blasuc aulmichael Blasucci, S ci, Senior S


slide-1
SLIDE 1

For All C

  • r All Code
  • de,

, Ther here Exist P e Exist Proper

  • perties t

ties to be Check

  • be Checked

ed

(or

  • r, r

, random t andom testing with FsCheck) esting with FsCheck) Paulmichael Blasuc aulmichael Blasucci, S ci, Senior S enior Sof

  • ftwar

are E e Engineer a ngineer at t

twitter.com/pblasucci github.com/pblasucci linkedin.com/in/pblasucci

slide-2
SLIDE 2

Random andom Testing esting

“Proper'es ¡are ¡described ¡as ¡… ¡func%ons, ¡and ¡can ¡ be ¡automa%cally ¡tested ¡on ¡random ¡input... ¡[or] ¡ custom ¡test ¡data ¡generators.”

from ¡ICFP’00 ¡– ¡Claessen, ¡Hughes ¡

slide-3
SLIDE 3

From Unit

  • m Unit Testing

esting… …

[<Test>] ¡ let ¡``clone ¡returns ¡a ¡new ¡instance`` ¡() ¡ ¡ ¡ ¡use ¡msg1 ¡= ¡new ¡Message("test"B) ¡ ¡ ¡use ¡msg2 ¡= ¡Message.clone ¡msg1 ¡ ¡ ¡Assert.That ¡(msg2,Is.Not.EqualTo ¡msg1) ¡ ¡ [<Property>] ¡ let ¡``not ¡equal ¡to ¡original`` ¡data ¡= ¡ ¡ ¡use ¡msg1 ¡= ¡new ¡Message ¡(data) ¡ ¡ ¡use ¡msg2 ¡= ¡Message.clone ¡msg1 ¡ ¡ ¡msg1 ¡<> ¡msg2 ¡ ¡

To P

  • Proper
  • perty

y Testing esting

` ¡

slide-4
SLIDE 4

FsCheck: P FsCheck: Proper

  • perties

ties

  • pen ¡fszmq ¡
  • pen ¡fszmq.Message ¡

¡ let ¡equalContent ¡(msg1:Message) ¡(msg2:Message) ¡= ¡ ¡ ¡ ¡size ¡msg1 ¡= ¡size ¡msg2 ¡&& ¡data ¡msg1 ¡= ¡data ¡msg2 ¡ ¡ let ¡``clone ¡is ¡idempotent`` ¡(msg:Message) ¡= ¡ ¡ ¡use ¡once ¡ ¡= ¡clone ¡msg ¡ ¡ ¡use ¡twice ¡= ¡msg ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡|> ¡clone ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡|> ¡clone ¡ ¡ ¡twice ¡|> ¡equalContent ¡once ¡ ¡ ¡

slide-5
SLIDE 5

FsCheck: P FsCheck: Proper

  • perties

ties

let ¡``copy ¡alters ¡target ¡but ¡not ¡source`` ¡msg1 ¡msg2 ¡= ¡ ¡ ¡let ¡data1,data2 ¡= ¡data ¡msg1,data ¡msg2 ¡ ¡ ¡copy ¡msg1 ¡msg2 ¡ ¡ ¡(data ¡msg1 ¡= ¡data1) ¡&& ¡(data ¡msg2 ¡<> ¡data2) ¡

Combining ¡proper'es ¡(naïvely) ¡

slide-6
SLIDE 6

FsCheck: P FsCheck: Proper

  • perties

ties

let ¡``copy ¡alters ¡target ¡but ¡not ¡source`` ¡msg1 ¡msg2 ¡= ¡ ¡ ¡let ¡data1,data2 ¡= ¡data ¡msg1,data ¡msg2 ¡ ¡ ¡copy ¡msg1 ¡msg2 ¡ ¡ ¡(data ¡msg1 ¡= ¡ ¡data1 ¡|@ ¡"source") ¡ ¡ ¡ ¡.&. ¡ ¡ ¡ ¡(data ¡msg2 ¡<> ¡data2 ¡|@ ¡"target") ¡

Combining ¡and ¡Labeling ¡proper'es ¡

slide-7
SLIDE 7

FsCheck: P FsCheck: Proper

  • perties

ties

let ¡``copy ¡alters ¡target ¡but ¡not ¡source`` ¡msg1 ¡msg2 ¡= ¡ ¡ ¡(data ¡msg1 ¡<> ¡data ¡msg2) ¡==> ¡ ¡ ¡ ¡ ¡ ¡let ¡data1,data2 ¡= ¡data ¡msg1, ¡data ¡msg2 ¡ ¡ ¡ ¡ ¡copy ¡msg1 ¡msg2 ¡ ¡ ¡ ¡ ¡(data ¡msg1 ¡= ¡data1 ¡|@ ¡"source") ¡ ¡ ¡ ¡ ¡ ¡.&. ¡ ¡ ¡ ¡ ¡ ¡(data ¡msg2 ¡<> ¡data2 ¡|@ ¡"target") ¡

Condi-onal ¡proper'es ¡

slide-8
SLIDE 8

FsCheck FsCheck: Gener : Generation tion

4% ¡ 4% ¡ 4% ¡ 4% ¡ 4% ¡ 4% ¡ 8% ¡ 8% ¡ 8% ¡ 16% ¡ 36% ¡

Randomly Gener andomly Generated ed Versions ersions

distribu;on ¡of ¡random ¡data ¡using ¡a ¡custom ¡generator ¡

slide-9
SLIDE 9

FsCheck: Gener FsCheck: Generation tion

type ¡Generators ¡= ¡ ¡ ¡ ¡static ¡member ¡Version ¡= ¡ ¡ ¡ ¡ ¡let ¡unknown ¡= ¡Gen.constant ¡Unknown ¡ ¡ ¡ ¡ ¡let ¡version ¡= ¡Arb.generate<NonNegativeInt> ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡|> ¡Gen.three ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡|> ¡Gen.map ¡(fun ¡(NonNegativeInt ¡m ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡,NonNegativeInt ¡n ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡,NonNegativeInt ¡r) ¡-­‑> ¡fszmq.Version ¡(m,n,r)) ¡ ¡ ¡ ¡ ¡[ ¡(1,unknown); ¡(2,version) ¡] ¡ ¡ ¡ ¡ ¡|> ¡Gen.frequency ¡ ¡ ¡ ¡ ¡|> ¡Arb.fromGen ¡ ¡

slide-10
SLIDE 10

FsCheck: Gener FsCheck: Generation tion

module ¡Z85Encoder ¡= ¡ ¡ ¡let ¡``encode,decode ¡are ¡duals`` ¡(data:byte[]) ¡= ¡ ¡ ¡ ¡ ¡data|> ¡Z85.encode ¡|> ¡Z85.decode ¡= ¡data ¡

Expressing ¡implicit ¡business ¡rules ¡

slide-11
SLIDE 11

FsCheck: Gener FsCheck: Generation tion

module ¡Z85Encoder ¡= ¡ ¡ ¡let ¡``encode,decode ¡are ¡duals`` ¡(Mod4Bytes ¡data) ¡= ¡ ¡ ¡ ¡ ¡data|> ¡Z85.encode ¡|> ¡Z85.decode ¡= ¡data ¡

Expressing ¡implicit ¡business ¡rules ¡

“Z85 ¡… ¡takes ¡a ¡binary ¡frame ¡and ¡encodes ¡it ¡ as ¡a ¡printable ¡ASCII ¡string, ¡or ¡takes ¡an ¡ASCII ¡ encoded ¡string ¡and ¡decodes ¡it ¡into ¡a ¡binary ¡

  • frame. ¡

The ¡binary ¡frame ¡SHALL ¡have ¡a ¡length ¡that ¡is ¡ divisible ¡by ¡4 ¡with ¡no ¡remainder. ¡The ¡string ¡ frame ¡SHALL ¡have ¡a ¡length ¡that ¡is ¡divisible ¡by ¡ 5 ¡with ¡no ¡remainder.” ¡ ¡ from ¡Z85 ¡RFC ¡

type ¡Mod4Bytes ¡= ¡Mod4Bytes ¡of ¡byte[] ¡ ¡ // ¡... ¡elsewhere ¡... ¡ ¡ static ¡member ¡Mod4Bytes ¡= ¡ ¡ ¡let ¡g ¡= ¡Arb.generate<byte[]> ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡|> ¡Gen.suchThat ¡(fun ¡b ¡-­‑> ¡b ¡<> ¡null ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡&& ¡b.Length ¡% ¡4 ¡= ¡0) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡|> ¡Gen.map ¡Mod4Bytes ¡ ¡ ¡let ¡s ¡(Mod4Bytes ¡bytes) ¡= ¡bytes ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡|> ¡Arb.shrink ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡|> ¡Seq.map ¡Mod4Bytes ¡ ¡ ¡Arb.fromGenShrink ¡(g,s) ¡

slide-12
SLIDE 12

FsCheck FsCheck: Obser : Observations tions

0% ¡ 5% ¡ 10% ¡ 15% ¡ 20% ¡ 25% ¡ 30% ¡ 0 ¡ 4 ¡ 8 ¡ 12 ¡ 16 ¡ 20 ¡ 24 ¡ 28 ¡ 32 ¡ 36 ¡ 40 ¡ 44 ¡ 48 ¡ 52 ¡ 60 ¡ 64 ¡ 68 ¡ 72 ¡ 76 ¡

Obser Observed Arr ed Array Siz y Sizes (in B es (in Byt ytes) es)

distribu;on ¡of ¡randomly ¡generated ¡test ¡inputs ¡

Tiny ¡(0 ¡.. ¡4 ¡bytes) ¡ Small ¡(8 ¡.. ¡20 ¡bytes) ¡ Medium ¡(24 ¡.. ¡60 ¡bytes) ¡ Large ¡(64 ¡.. ¡∞ ¡bytes) ¡

slide-13
SLIDE 13

FsCheck: Obser FsCheck: Observations tions

let ¡``encode,decode ¡are ¡duals`` ¡(Mod4Binary ¡value) ¡= ¡ ¡ ¡ ¡(value ¡|> ¡Z85.encode ¡|> ¡Z85.decode ¡= ¡value) ¡ ¡ ¡ ¡|> ¡Prop.trivial ¡(Array.isEmpty ¡value) ¡ ¡ let ¡``encode,decode ¡are ¡duals`` ¡(Mod4Binary ¡value) ¡= ¡ ¡ ¡ ¡(value ¡|> ¡Z85.encode ¡|> ¡Z85.decode ¡= ¡value) ¡ ¡ ¡ ¡|> ¡Prop.classify ¡(large ¡ ¡value) ¡"large ¡(64 ¡.. ¡∞)” ¡ ¡ ¡|> ¡Prop.classify ¡(medium ¡value) ¡"medium ¡(24 ¡.. ¡60)” ¡ ¡ ¡|> ¡Prop.classify ¡(small ¡ ¡value) ¡"small ¡(8 ¡.. ¡20)” ¡ ¡ ¡|> ¡Prop.classify ¡(tiny ¡ ¡ ¡value) ¡"tiny ¡(0 ¡.. ¡4)" ¡

slide-14
SLIDE 14

FsCheck: Obser FsCheck: Observations tions

let ¡``encode,decode ¡are ¡duals`` ¡(Mod4Binary ¡value) ¡= ¡ ¡ ¡ ¡(value ¡|> ¡Z85.encode ¡|> ¡Z85.decode ¡= ¡value) ¡ ¡ ¡ ¡|> ¡Prop.collect ¡(Array.length ¡value) ¡ ¡ let ¡``encode,decode ¡are ¡duals`` ¡(Mod4Binary ¡value) ¡= ¡ ¡ ¡ ¡(value ¡|> ¡Z85.encode ¡|> ¡Z85.decode ¡= ¡value) ¡ ¡ ¡ ¡|> ¡Prop.trivial ¡ ¡ ¡(Array.isEmpty ¡value) ¡ ¡ ¡|> ¡Prop.classify ¡ ¡(large ¡ ¡value) ¡“large ¡(64 ¡.. ¡∞)” ¡ ¡ ¡|> ¡Prop.classify ¡ ¡(medium ¡value) ¡“medium ¡(24 ¡.. ¡60)” ¡ ¡ ¡|> ¡Prop.classify ¡ ¡(small ¡ ¡value) ¡“small ¡(8 ¡.. ¡20)” ¡ ¡ ¡|> ¡Prop.classify ¡ ¡(tiny ¡ ¡ ¡value) ¡“tiny ¡(0 ¡.. ¡4)” ¡ ¡ ¡|> ¡Prop.collect ¡ ¡ ¡(Array.length ¡value) ¡

slide-15
SLIDE 15

Random andom Testing esting

“One ¡of ¡the ¡major ¡advantages… ¡is ¡that ¡it ¡ encourages ¡us ¡to ¡formulate ¡formal ¡specifica%ons, ¡ thus ¡improving ¡our ¡understanding…”

from ¡ICFP’00 ¡– ¡Claessen, ¡Hughes ¡

slide-16
SLIDE 16

Mor More Informa Information tion

about F# and FsCheck

  • fsharp.org ¡
  • fscheck.github.io/fscheck ¡
  • fsharpforfunandprofit.com ¡
  • meetup.com/nyc-­‑fsharp ¡

about ¡Paulmichael ¡Blasucci ¡

  • twi[er.com/pblasucci ¡
  • github.com/pblasucci ¡
  • linkedin.com/in/pblasucci ¡
  • pblasucci.wordpress.com ¡