Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Property-based Testing is a Mindset
Search
Andrea Leopardi
December 06, 2017
Programming
740
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Property-based Testing is a Mindset
Andrea Leopardi
December 06, 2017
More Decks by Andrea Leopardi
See All by Andrea Leopardi
Agentic Elixir
whatyouhide
0
620
The Umbrella and the Range
whatyouhide
0
75
gen_statem - OTP's Unsung Hero
whatyouhide
2
370
The World is a Network (and We Are Just Nodes)
whatyouhide
1
270
BEAM: The Perfect Fit for Networks
whatyouhide
1
280
Update from the Elixir team - 2022
whatyouhide
0
470
Testing Asynchronous OTP
whatyouhide
1
590
Elixir Sightseeing Tour
whatyouhide
0
510
Mint - Disrupting HTTP clients
whatyouhide
0
320
Other Decks in Programming
See All in Programming
golang-bob.pdf
iwatsukayura
0
140
SFCで実現する病院・医療システムの動的組み立て式UI
koukimiura
1
120
GraphQL の onError と Nullability のこれから
quramy
0
180
Groovy as a human and AI friendly programming language
paulk
0
120
Agentic Software Factoryに、すごく賢いIF文を。 / super smart IF statement into the Agentic Software Factory.
rkaga
8
2.4k
コードレビューのボトルネックを"する側"と"される側"の両面から解消する
yub0n
2
1.7k
Coding with AI: How to trust the storyteller (AWS Community Day Adria, Ljubljana 2026)
slobodan
0
120
R8 の設定見直しでアプリサイズ削減
andpad
0
230
Event is what happens
moro
2
1.6k
PumaからFalconに移行したRailsアプリケーションでの実践
falcon8823
0
240
Domain-Driven Transformation
hschwentner
2
2.3k
設計次第でAIコードの読む量は減らせる / designing-for-code-reading
minodriven
35
17k
Featured
See All Featured
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
340
Speed Design
sergeychernyshev
33
2.2k
The SEO Collaboration Effect
kristinabergwall1
1
600
Google's AI Overviews - The New Search
badams
0
1.6k
Evolving SEO for Evolving Search Engines
ryanjones
0
330
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.8k
Designing for humans not robots
tammielis
254
26k
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
63
47k
VelocityConf: Rendering Performance Case Studies
addyosmani
331
25k
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
360
Building an army of robots
kneath
307
47k
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
940
Transcript
I S A M I N D S E T
P R O P E R T Y - B A S E D T E S T I N G
@whatyouhide
None
Elixir
T E S T I N G
why do we test? no tests yes tests
unit tests
test "sorting" do assert sort([]) == [] assert sort([1, 2,
3]) == [1, 2, 3] assert sort([2, 1, 3]) == [1, 2, 3] end example-based
table-based Input Output [] [] [1, 2, 3] [1, 2,
3] [2, 1, 3] [1, 2, 3]
unit tests , but also
P R O P E R T I E S
hard to write , but...
valid inputs properties of output testing framework
github.com/whatyouhide/stream_data
example time: sorting lists
test "sorting" do assert sort([]) == [] assert sort([1, 2,
3]) == [1, 2, 3] assert sort([2, 1, 3]) == [1, 2, 3] end
lists of integers
it's a list has the same elements it's ordered
check all list <- list_of(int()) do sorted = sort(list) assert
is_list(sorted) assert same_elements?(list, sorted) assert ordered?(sorted) end
check all list <- list_of(int()) do sorted = sort(list) assert
is_list(sorted) assert same_elements?(list, sorted) assert ordered?(sorted) end
check all list <- list_of(int()) do sorted = sort(list) assert
is_list(sorted) assert same_elements?(list, sorted) assert ordered?(sorted) end
check all list <- list_of(int()) do sorted = sort(list) assert
is_list(sorted) assert same_elements?(list, sorted) assert ordered?(sorted) end
check all list <- list_of(int()) do sorted = sort(list) assert
is_list(sorted) assert same_elements?(list, sorted) assert ordered?(sorted) end
def sort(list), do: list
[32, 2, 44, -12] [1, 0] *shrinking
P A T T E R N S
circular code
decode(encode(term)) == term
property "encoding->decoding is circular" do check all bin <- binary()
do encoded = Huffman.encode(bin) assert is_binary(encoded) assert Huffman.decode(encoded) == bin end end Huffman encoding
oracle model
my_code() == oracle_code()
older system less performant implementation
property "gives same results as Erlang impl" do check all
bin <- binary() do assert Huffman.encode(bin) == :huffman.encode(bin) end end
smoke tests https://www.youtube.com/watch?v=jvwfDdgg93E
API: 200, 201, 400, 404 https://www.youtube.com/watch?v=jvwfDdgg93E
https://www.youtube.com/watch?v=jvwfDdgg93E property "only expected codes are returned" do check all
request <- request() do response = HTTP.perform(request) assert response.status in [200, 201, 400, 404] end end
locally , CI
if System.get_env("CI") == "true" do config :stream_data, max_runs: 500 else
config :stream_data, max_runs: 25 end
unit + properties
R E A L - W O R L D
E X A M P L E
Redis parser
continuation parser parse(bytes) {:ok, command} {:more, function}
property "splitting commands at random" do check all cmd <-
command(), split_cmd <- random_splits(cmd) do assert {:ok, _, ""} = parse_many(split_cmd) end end
property "splitting commands at random" do check all cmd <-
command(), split_cmd <- random_splits(cmd) do assert {:ok, _, ""} = parse_many(split_cmd) end end
property "splitting commands at random" do check all cmd <-
command(), split_cmd <- random_splits(cmd) do assert {:ok, _, ""} = parse_many(split_cmd) end end
S T A T E F U L T E
S T I N G
model valid commands +
model: state + state transformations
commands: calls + preconditions
bounded-size queue
Max size model system
•push(queue, value) •resize(queue, max_size) commands
def push(model, _value), do: model def resize(_model, max_size), do: max_size
push(queue, {:some, "value"}) push(queue, [123, 3.2]) resize(queue, 1) push(queue, %{})
assert size(queue) <= model
LevelDB
17 (seventeen) calls 33 (thirty three) calls
C O N C L U S I O N
find obscure bugs reduce to minimal failing input find specification
errors keep increasing input space
v1.7
use stream_data
use property-based testing
@whatyouhide github.com/whatyouhide/stream_data