SlideShare a Scribd company logo
Object::Exercise: Keep your objects healthy.
Steven Lembark
Workhorse Computing
lembark@wrkhors.com
Recall that Lazy-ness is a virtue
Hardcoded testing is a pain.
Tests require tests...
Alternative: Data-driven testing.
Declarative specs.
Generated tests.
We have all written this:
Create an object.
Run a command.
Check $@.
Execute a test.
Run a command...
The test cycle
my $obj = $class->new( @argz );
eval
{
my $expect = { qw( your structure from hell ) };
my $found = $obj->foo( @foo_argz );
cmp_deeply $found, $expect, "foo";
};
BAIL_OUT "foo fails" if $@;
eval
{
my $expect = [ { qw( another structure from hell ) } ];
my $found = [ $obj->bar( @bar_argz ) ];
cmp_deeply $found, $expect, "bar";
};
BAIL_OUT "bar fails" if $@;
...
MJD's “Red Flags”
Code is framework, probably updated by cut+paste.
Spend more time hacking framework than module.
Hardwiring the the tests requres testing the tests.
Troubleshooting the tests...
Updating the tests.
Fix: Add a level of abstraction.
Put loops, boilerplate into framework.
Data drives test loop.
Metadata used to generate test data.
Replace hardwired tests with data.
Abstraction: Object::Exercise
A “little language”.
Describe a call, sanity checks.
Data drives the tests.
Array based for simpler processing.
Perl makes this easy
Perl can dispatch $object->$method( ... ).
The $method scalar can be
Text for symbol table dispatch.
Subref for direct dispatch into code.
Text for whitebox, Subref for blackbox.
Planning your exercise.
An array of steps.
Each step is an operation or directive.
Directives are text like “verbose”.
Operations are arrayref's with a
Method + args.
Expect & outcome.
Entering the labrynth
Entry point is a subref.
Avoids namespace collisions with methods:
$object->$exercise( @testz );
initiates testing.
Perly One-Step
Nothing more than a method and arguments:
[
method => arg, ...
]
Executes $obj->$method( arg, … ).
Successful if no exceptions.
Testy Two-Step
Supply fixed return as arrayref:
[
[ method => arg, ... ],
[ compare values ],
]
[ 1 ], [ undef ], [ %struct_from_hell ]
Compared to [ $obj->$method( @argz ) ].
Expecting failure
Testing failure modes raises exceptions.
Explicit undef expects eval { ... } to fail.
Reports successful exception:
[
[ method => @bogus_values ],
undef
]
Saying it your way
Third element is a message:
[
[ $method, @blah_blah ],
[ 42 ],
“$method supplies The Answer”
]
Great expectations
Beyond fixed values: regexen, subrefs.
qr/ ... / $found->[0] =~ $regex ? pass : fail ;
sub { ... } $sub->( @$found ) ? pass : fail ;
Generated regexen, closures simplify testing.
Both can have the optional message.
Giving orders
Directives are text scalars.
Turn on/off verbosity in tests.
Set a breakpoint before calling $method.
Treat input as regex text and compile it.
One-test settings
Text scalars before first arrayref are directives.
Test frobnicate verbosely, rest no-verbose:
noverbose =>
[
verbose =>
[ qw( frobnicate blah blah ) ]
],
One-test breakpoint
Adds $DB::Single = 1 prior to calling $obj->$method.
Simplifies perl -d to check a single method.
[
debug =>
[ qw( foobar bletch blort ) ],
[ 1 ]
]
Regexen in YAML::XS
YAML::XS segfaults handling stored rexen.
“regex” directive compiles expect value as regex:
[
regex =>
[ qw( foobar bletch) ],
'[A-Z]w+$',
]
$obj->foobar( 'bletch' ) =~ qr/[A-Z]w+$/;
Result: Declariative Testing
Tests can be stored in YAML, JSON.
Templates can be expanded in code.
Text methods useful for “blackbox” testing.
Validate what method returns.
Coderef's useful for “whitebox” testing.
Investigate internal structure of object.
Reset incremental values for iterative tests.
Example: Adventure Map Test
Minimal map: One locations entry.
name: Empty Map 00
namespace : EmptyMap00
locations:
blackhole:
name: BlackHole
description : You are standing in a Black Hole.
exits :
Out : blackhole
Generating tests
Starting from the Black Hole:
Validate the description.
Validate move to exit.
Override the map contents
One way: Store separate mission files.
Every test needs to be replicated.
Two way: Replace the map.
Override the method returning locations.
Init reads the map
"add_locations" processes the map:
sub init {
my ($class, $config_path) = @_;
die "You must specify a config file to init()" unless
defined $config_path;
$_config = YAML::LoadFile($config_path);
$class->add_items($_config->{items});
$class->add_actors($_config->{actors});
$class->add_locations($_config->{locations});
$class->add_player('player1', $_config->{player});
}
Adding locations is a loop
They are added one-by-one.
sub add_locations
{
my ($class, $locations) = @_;
foreach my $key (keys %{$locations}) {
$class->add_location($key, $locations->{$key});
}
}
Adding one location
Finally: The root of all evil...
New locations are added with a key and struct:
sub add_location
{
my ($class, $key, $config) = @_;
my $location = Adventure::Location->new;
$location->init($key, $config);
$class->locations->{$key} = $location;
}
Faking the location
sub install_test_location
{
my $package = shift;
my $test_struct = shift;
*{ qualify_to_ref add_location => $package }
= sub
{
my ($class, $key ) = @_;
$class->locations->{$key}
= Adventure::Location
->new
->init($key, $test_struct ); # hardwired map
};
}
Aside: Generic “add” handler
# e.g., install Adventure::Location::add_location
sub add_thingy
{
my ( $parent, $thing ) = @_;
my $name = ‘add_’ . $thing;
my $package = qualify ucfirst(lc $thing), $parent;
*{ qualify_to_ref $name => $package }
= sub
{
my ($class, $name, $data ) = @_;
$class->$type->{$name}
= $package->new->init($name, $data );
};
Summary
Exercising objects is simple, repetitive.
MJD’s “Red Flags”: don’t cut & paste.
Replace hardwired loops with data-driven code.
Object::Exercise standardizes the loops.
Tests are declarative data.

More Related Content

What's hot

Memory Manglement in Raku
Memory Manglement in RakuMemory Manglement in Raku
Memory Manglement in Raku
Workhorse Computing
 
Smoking docker
Smoking dockerSmoking docker
Smoking docker
Workhorse Computing
 
Get your teeth into Plack
Get your teeth into PlackGet your teeth into Plack
Get your teeth into Plack
Workhorse Computing
 
Getting Testy With Perl6
Getting Testy With Perl6Getting Testy With Perl6
Getting Testy With Perl6
Workhorse Computing
 
Unit Testing Lots of Perl
Unit Testing Lots of PerlUnit Testing Lots of Perl
Unit Testing Lots of Perl
Workhorse Computing
 
Getting testy with Perl
Getting testy with PerlGetting testy with Perl
Getting testy with Perl
Workhorse Computing
 
Effective Benchmarks
Effective BenchmarksEffective Benchmarks
Effective Benchmarks
Workhorse Computing
 
Perl6 Regexen: Reduce the line noise in your code.
Perl6 Regexen: Reduce the line noise in your code.Perl6 Regexen: Reduce the line noise in your code.
Perl6 Regexen: Reduce the line noise in your code.
Workhorse Computing
 
Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6
Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6
Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6
Workhorse Computing
 
Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)Kang-min Liu
 
Ethiopian multiplication in Perl6
Ethiopian multiplication in Perl6Ethiopian multiplication in Perl6
Ethiopian multiplication in Perl6
Workhorse Computing
 
Barely Legal Xxx Perl Presentation
Barely Legal Xxx Perl PresentationBarely Legal Xxx Perl Presentation
Barely Legal Xxx Perl PresentationAttila Balazs
 
Melhorando sua API com DSLs
Melhorando sua API com DSLsMelhorando sua API com DSLs
Melhorando sua API com DSLs
Augusto Pascutti
 
Working with databases in Perl
Working with databases in PerlWorking with databases in Perl
Working with databases in Perl
Laurent Dami
 
I, For One, Welcome Our New Perl6 Overlords
I, For One, Welcome Our New Perl6 OverlordsI, For One, Welcome Our New Perl6 Overlords
I, For One, Welcome Our New Perl6 Overlords
heumann
 
Perforce Object and Record Model
Perforce Object and Record Model  Perforce Object and Record Model
Perforce Object and Record Model
Perforce
 
Perl6 in-production
Perl6 in-productionPerl6 in-production
Perl6 in-production
Andrew Shitov
 
Static Optimization of PHP bytecode (PHPSC 2017)
Static Optimization of PHP bytecode (PHPSC 2017)Static Optimization of PHP bytecode (PHPSC 2017)
Static Optimization of PHP bytecode (PHPSC 2017)
Nikita Popov
 
Replacing "exec" with a type and provider: Return manifests to a declarative ...
Replacing "exec" with a type and provider: Return manifests to a declarative ...Replacing "exec" with a type and provider: Return manifests to a declarative ...
Replacing "exec" with a type and provider: Return manifests to a declarative ...
Puppet
 
Testing Code and Assuring Quality
Testing Code and Assuring QualityTesting Code and Assuring Quality
Testing Code and Assuring Quality
Kent Cowgill
 

What's hot (20)

Memory Manglement in Raku
Memory Manglement in RakuMemory Manglement in Raku
Memory Manglement in Raku
 
Smoking docker
Smoking dockerSmoking docker
Smoking docker
 
Get your teeth into Plack
Get your teeth into PlackGet your teeth into Plack
Get your teeth into Plack
 
Getting Testy With Perl6
Getting Testy With Perl6Getting Testy With Perl6
Getting Testy With Perl6
 
Unit Testing Lots of Perl
Unit Testing Lots of PerlUnit Testing Lots of Perl
Unit Testing Lots of Perl
 
Getting testy with Perl
Getting testy with PerlGetting testy with Perl
Getting testy with Perl
 
Effective Benchmarks
Effective BenchmarksEffective Benchmarks
Effective Benchmarks
 
Perl6 Regexen: Reduce the line noise in your code.
Perl6 Regexen: Reduce the line noise in your code.Perl6 Regexen: Reduce the line noise in your code.
Perl6 Regexen: Reduce the line noise in your code.
 
Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6
Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6
Neatly Hashing a Tree: FP tree-fold in Perl5 & Perl6
 
Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)
 
Ethiopian multiplication in Perl6
Ethiopian multiplication in Perl6Ethiopian multiplication in Perl6
Ethiopian multiplication in Perl6
 
Barely Legal Xxx Perl Presentation
Barely Legal Xxx Perl PresentationBarely Legal Xxx Perl Presentation
Barely Legal Xxx Perl Presentation
 
Melhorando sua API com DSLs
Melhorando sua API com DSLsMelhorando sua API com DSLs
Melhorando sua API com DSLs
 
Working with databases in Perl
Working with databases in PerlWorking with databases in Perl
Working with databases in Perl
 
I, For One, Welcome Our New Perl6 Overlords
I, For One, Welcome Our New Perl6 OverlordsI, For One, Welcome Our New Perl6 Overlords
I, For One, Welcome Our New Perl6 Overlords
 
Perforce Object and Record Model
Perforce Object and Record Model  Perforce Object and Record Model
Perforce Object and Record Model
 
Perl6 in-production
Perl6 in-productionPerl6 in-production
Perl6 in-production
 
Static Optimization of PHP bytecode (PHPSC 2017)
Static Optimization of PHP bytecode (PHPSC 2017)Static Optimization of PHP bytecode (PHPSC 2017)
Static Optimization of PHP bytecode (PHPSC 2017)
 
Replacing "exec" with a type and provider: Return manifests to a declarative ...
Replacing "exec" with a type and provider: Return manifests to a declarative ...Replacing "exec" with a type and provider: Return manifests to a declarative ...
Replacing "exec" with a type and provider: Return manifests to a declarative ...
 
Testing Code and Assuring Quality
Testing Code and Assuring QualityTesting Code and Assuring Quality
Testing Code and Assuring Quality
 

Similar to Keeping objects healthy with Object::Exercise.

Damn Fine CoffeeScript
Damn Fine CoffeeScriptDamn Fine CoffeeScript
Damn Fine CoffeeScript
niklal
 
DBI
DBIDBI
mro-every.pdf
mro-every.pdfmro-every.pdf
mro-every.pdf
Workhorse Computing
 
Ruby Metaprogramming
Ruby MetaprogrammingRuby Metaprogramming
Ruby Metaprogramming
Thaichor Seng
 
How to write code you won't hate tomorrow
How to write code you won't hate tomorrowHow to write code you won't hate tomorrow
How to write code you won't hate tomorrow
Pete McFarlane
 
OOP in PHP.pptx
OOP in PHP.pptxOOP in PHP.pptx
OOP in PHP.pptx
switipatel4
 
Ruby Programming Language
Ruby Programming LanguageRuby Programming Language
Ruby Programming Language
Duda Dornelles
 
A linguagem de programação Ruby - Robson "Duda" Sejan Soares Dornelles
A linguagem de programação Ruby - Robson "Duda" Sejan Soares DornellesA linguagem de programação Ruby - Robson "Duda" Sejan Soares Dornelles
A linguagem de programação Ruby - Robson "Duda" Sejan Soares Dornelles
Tchelinux
 
An introduction to property-based testing
An introduction to property-based testingAn introduction to property-based testing
An introduction to property-based testing
Vincent Pradeilles
 
Python magicmethods
Python magicmethodsPython magicmethods
Python magicmethods
dreampuf
 
Attributes Unwrapped: Lessons under the surface of active record
Attributes Unwrapped: Lessons under the surface of active recordAttributes Unwrapped: Lessons under the surface of active record
Attributes Unwrapped: Lessons under the surface of active record
.toster
 
Groovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony CodeGroovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony Codestasimus
 
Your code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConYour code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnCon
Rafael Dohms
 
Building a horizontally scalable API in php
Building a horizontally scalable API in phpBuilding a horizontally scalable API in php
Building a horizontally scalable API in phpWade Womersley
 
Smelling your code
Smelling your codeSmelling your code
Smelling your code
Raju Mazumder
 
Drupal 8 database api
Drupal 8 database apiDrupal 8 database api
Drupal 8 database api
Viswanath Polaki
 
Test driven development_for_php
Test driven development_for_phpTest driven development_for_php
Test driven development_for_php
Lean Teams Consultancy
 
谈谈Javascript设计
谈谈Javascript设计谈谈Javascript设计
谈谈Javascript设计
Alipay
 

Similar to Keeping objects healthy with Object::Exercise. (20)

Damn Fine CoffeeScript
Damn Fine CoffeeScriptDamn Fine CoffeeScript
Damn Fine CoffeeScript
 
DBI
DBIDBI
DBI
 
mro-every.pdf
mro-every.pdfmro-every.pdf
mro-every.pdf
 
Drupal7 dbtng
Drupal7  dbtngDrupal7  dbtng
Drupal7 dbtng
 
Ruby Metaprogramming
Ruby MetaprogrammingRuby Metaprogramming
Ruby Metaprogramming
 
Php & my sql
Php & my sqlPhp & my sql
Php & my sql
 
How to write code you won't hate tomorrow
How to write code you won't hate tomorrowHow to write code you won't hate tomorrow
How to write code you won't hate tomorrow
 
OOP in PHP.pptx
OOP in PHP.pptxOOP in PHP.pptx
OOP in PHP.pptx
 
Ruby Programming Language
Ruby Programming LanguageRuby Programming Language
Ruby Programming Language
 
A linguagem de programação Ruby - Robson "Duda" Sejan Soares Dornelles
A linguagem de programação Ruby - Robson "Duda" Sejan Soares DornellesA linguagem de programação Ruby - Robson "Duda" Sejan Soares Dornelles
A linguagem de programação Ruby - Robson "Duda" Sejan Soares Dornelles
 
An introduction to property-based testing
An introduction to property-based testingAn introduction to property-based testing
An introduction to property-based testing
 
Python magicmethods
Python magicmethodsPython magicmethods
Python magicmethods
 
Attributes Unwrapped: Lessons under the surface of active record
Attributes Unwrapped: Lessons under the surface of active recordAttributes Unwrapped: Lessons under the surface of active record
Attributes Unwrapped: Lessons under the surface of active record
 
Groovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony CodeGroovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony Code
 
Your code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConYour code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnCon
 
Building a horizontally scalable API in php
Building a horizontally scalable API in phpBuilding a horizontally scalable API in php
Building a horizontally scalable API in php
 
Smelling your code
Smelling your codeSmelling your code
Smelling your code
 
Drupal 8 database api
Drupal 8 database apiDrupal 8 database api
Drupal 8 database api
 
Test driven development_for_php
Test driven development_for_phpTest driven development_for_php
Test driven development_for_php
 
谈谈Javascript设计
谈谈Javascript设计谈谈Javascript设计
谈谈Javascript设计
 

More from Workhorse Computing

Wheels we didn't re-invent: Perl's Utility Modules
Wheels we didn't re-invent: Perl's Utility ModulesWheels we didn't re-invent: Perl's Utility Modules
Wheels we didn't re-invent: Perl's Utility Modules
Workhorse Computing
 
Paranormal statistics: Counting What Doesn't Add Up
Paranormal statistics: Counting What Doesn't Add UpParanormal statistics: Counting What Doesn't Add Up
Paranormal statistics: Counting What Doesn't Add Up
Workhorse Computing
 
Generating & Querying Calendar Tables in Posgresql
Generating & Querying Calendar Tables in PosgresqlGenerating & Querying Calendar Tables in Posgresql
Generating & Querying Calendar Tables in Posgresql
Workhorse Computing
 
The W-curve and its application.
The W-curve and its application.The W-curve and its application.
The W-curve and its application.
Workhorse Computing
 
Neatly folding-a-tree
Neatly folding-a-treeNeatly folding-a-tree
Neatly folding-a-tree
Workhorse Computing
 
Light my-fuse
Light my-fuseLight my-fuse
Light my-fuse
Workhorse Computing
 
Paranormal stats
Paranormal statsParanormal stats
Paranormal stats
Workhorse Computing
 
Shared Object images in Docker: What you need is what you want.
Shared Object images in Docker: What you need is what you want.Shared Object images in Docker: What you need is what you want.
Shared Object images in Docker: What you need is what you want.
Workhorse Computing
 
Putting some "logic" in LVM.
Putting some "logic" in LVM.Putting some "logic" in LVM.
Putting some "logic" in LVM.
Workhorse Computing
 
Selenium sandwich-3: Being where you aren't.
Selenium sandwich-3: Being where you aren't.Selenium sandwich-3: Being where you aren't.
Selenium sandwich-3: Being where you aren't.
Workhorse Computing
 
Selenium sandwich-2
Selenium sandwich-2Selenium sandwich-2
Selenium sandwich-2
Workhorse Computing
 
Selenium Sandwich Part 1: Data driven Selenium
Selenium Sandwich Part 1: Data driven Selenium Selenium Sandwich Part 1: Data driven Selenium
Selenium Sandwich Part 1: Data driven Selenium
Workhorse Computing
 
Docker perl build
Docker perl buildDocker perl build
Docker perl build
Workhorse Computing
 
Designing net-aws-glacier
Designing net-aws-glacierDesigning net-aws-glacier
Designing net-aws-glacier
Workhorse Computing
 
Lies, Damn Lies, and Benchmarks
Lies, Damn Lies, and BenchmarksLies, Damn Lies, and Benchmarks
Lies, Damn Lies, and Benchmarks
Workhorse Computing
 

More from Workhorse Computing (15)

Wheels we didn't re-invent: Perl's Utility Modules
Wheels we didn't re-invent: Perl's Utility ModulesWheels we didn't re-invent: Perl's Utility Modules
Wheels we didn't re-invent: Perl's Utility Modules
 
Paranormal statistics: Counting What Doesn't Add Up
Paranormal statistics: Counting What Doesn't Add UpParanormal statistics: Counting What Doesn't Add Up
Paranormal statistics: Counting What Doesn't Add Up
 
Generating & Querying Calendar Tables in Posgresql
Generating & Querying Calendar Tables in PosgresqlGenerating & Querying Calendar Tables in Posgresql
Generating & Querying Calendar Tables in Posgresql
 
The W-curve and its application.
The W-curve and its application.The W-curve and its application.
The W-curve and its application.
 
Neatly folding-a-tree
Neatly folding-a-treeNeatly folding-a-tree
Neatly folding-a-tree
 
Light my-fuse
Light my-fuseLight my-fuse
Light my-fuse
 
Paranormal stats
Paranormal statsParanormal stats
Paranormal stats
 
Shared Object images in Docker: What you need is what you want.
Shared Object images in Docker: What you need is what you want.Shared Object images in Docker: What you need is what you want.
Shared Object images in Docker: What you need is what you want.
 
Putting some "logic" in LVM.
Putting some "logic" in LVM.Putting some "logic" in LVM.
Putting some "logic" in LVM.
 
Selenium sandwich-3: Being where you aren't.
Selenium sandwich-3: Being where you aren't.Selenium sandwich-3: Being where you aren't.
Selenium sandwich-3: Being where you aren't.
 
Selenium sandwich-2
Selenium sandwich-2Selenium sandwich-2
Selenium sandwich-2
 
Selenium Sandwich Part 1: Data driven Selenium
Selenium Sandwich Part 1: Data driven Selenium Selenium Sandwich Part 1: Data driven Selenium
Selenium Sandwich Part 1: Data driven Selenium
 
Docker perl build
Docker perl buildDocker perl build
Docker perl build
 
Designing net-aws-glacier
Designing net-aws-glacierDesigning net-aws-glacier
Designing net-aws-glacier
 
Lies, Damn Lies, and Benchmarks
Lies, Damn Lies, and BenchmarksLies, Damn Lies, and Benchmarks
Lies, Damn Lies, and Benchmarks
 

Recently uploaded

FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance
 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
Ralf Eggert
 
Elevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object CalisthenicsElevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object Calisthenics
Dorra BARTAGUIZ
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Albert Hoitingh
 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
BookNet Canada
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
Neo4j
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
Laura Byrne
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
Ana-Maria Mihalceanu
 
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 previewState of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
Prayukth K V
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
mikeeftimakis1
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
91mobiles
 
Removing Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software FuzzingRemoving Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software Fuzzing
Aftab Hussain
 
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdfFIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance
 
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
Neo4j
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
Jemma Hussein Allen
 
By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024
Pierluigi Pugliese
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
KatiaHIMEUR1
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
Alpen-Adria-Universität
 

Recently uploaded (20)

FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
 
Elevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object CalisthenicsElevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object Calisthenics
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
 
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 previewState of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
 
Removing Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software FuzzingRemoving Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software Fuzzing
 
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdfFIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
 
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
 
By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024By Design, not by Accident - Agile Venture Bolzano 2024
By Design, not by Accident - Agile Venture Bolzano 2024
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
 

Keeping objects healthy with Object::Exercise.

  • 1. Object::Exercise: Keep your objects healthy. Steven Lembark Workhorse Computing lembark@wrkhors.com
  • 2. Recall that Lazy-ness is a virtue Hardcoded testing is a pain. Tests require tests... Alternative: Data-driven testing. Declarative specs. Generated tests.
  • 3. We have all written this: Create an object. Run a command. Check $@. Execute a test. Run a command...
  • 4. The test cycle my $obj = $class->new( @argz ); eval { my $expect = { qw( your structure from hell ) }; my $found = $obj->foo( @foo_argz ); cmp_deeply $found, $expect, "foo"; }; BAIL_OUT "foo fails" if $@; eval { my $expect = [ { qw( another structure from hell ) } ]; my $found = [ $obj->bar( @bar_argz ) ]; cmp_deeply $found, $expect, "bar"; }; BAIL_OUT "bar fails" if $@; ...
  • 5. MJD's “Red Flags” Code is framework, probably updated by cut+paste. Spend more time hacking framework than module. Hardwiring the the tests requres testing the tests. Troubleshooting the tests... Updating the tests.
  • 6. Fix: Add a level of abstraction. Put loops, boilerplate into framework. Data drives test loop. Metadata used to generate test data. Replace hardwired tests with data.
  • 7. Abstraction: Object::Exercise A “little language”. Describe a call, sanity checks. Data drives the tests. Array based for simpler processing.
  • 8. Perl makes this easy Perl can dispatch $object->$method( ... ). The $method scalar can be Text for symbol table dispatch. Subref for direct dispatch into code. Text for whitebox, Subref for blackbox.
  • 9. Planning your exercise. An array of steps. Each step is an operation or directive. Directives are text like “verbose”. Operations are arrayref's with a Method + args. Expect & outcome.
  • 10. Entering the labrynth Entry point is a subref. Avoids namespace collisions with methods: $object->$exercise( @testz ); initiates testing.
  • 11. Perly One-Step Nothing more than a method and arguments: [ method => arg, ... ] Executes $obj->$method( arg, … ). Successful if no exceptions.
  • 12. Testy Two-Step Supply fixed return as arrayref: [ [ method => arg, ... ], [ compare values ], ] [ 1 ], [ undef ], [ %struct_from_hell ] Compared to [ $obj->$method( @argz ) ].
  • 13. Expecting failure Testing failure modes raises exceptions. Explicit undef expects eval { ... } to fail. Reports successful exception: [ [ method => @bogus_values ], undef ]
  • 14. Saying it your way Third element is a message: [ [ $method, @blah_blah ], [ 42 ], “$method supplies The Answer” ]
  • 15. Great expectations Beyond fixed values: regexen, subrefs. qr/ ... / $found->[0] =~ $regex ? pass : fail ; sub { ... } $sub->( @$found ) ? pass : fail ; Generated regexen, closures simplify testing. Both can have the optional message.
  • 16. Giving orders Directives are text scalars. Turn on/off verbosity in tests. Set a breakpoint before calling $method. Treat input as regex text and compile it.
  • 17. One-test settings Text scalars before first arrayref are directives. Test frobnicate verbosely, rest no-verbose: noverbose => [ verbose => [ qw( frobnicate blah blah ) ] ],
  • 18. One-test breakpoint Adds $DB::Single = 1 prior to calling $obj->$method. Simplifies perl -d to check a single method. [ debug => [ qw( foobar bletch blort ) ], [ 1 ] ]
  • 19. Regexen in YAML::XS YAML::XS segfaults handling stored rexen. “regex” directive compiles expect value as regex: [ regex => [ qw( foobar bletch) ], '[A-Z]w+$', ] $obj->foobar( 'bletch' ) =~ qr/[A-Z]w+$/;
  • 20. Result: Declariative Testing Tests can be stored in YAML, JSON. Templates can be expanded in code. Text methods useful for “blackbox” testing. Validate what method returns. Coderef's useful for “whitebox” testing. Investigate internal structure of object. Reset incremental values for iterative tests.
  • 21. Example: Adventure Map Test Minimal map: One locations entry. name: Empty Map 00 namespace : EmptyMap00 locations: blackhole: name: BlackHole description : You are standing in a Black Hole. exits : Out : blackhole
  • 22. Generating tests Starting from the Black Hole: Validate the description. Validate move to exit.
  • 23. Override the map contents One way: Store separate mission files. Every test needs to be replicated. Two way: Replace the map. Override the method returning locations.
  • 24. Init reads the map "add_locations" processes the map: sub init { my ($class, $config_path) = @_; die "You must specify a config file to init()" unless defined $config_path; $_config = YAML::LoadFile($config_path); $class->add_items($_config->{items}); $class->add_actors($_config->{actors}); $class->add_locations($_config->{locations}); $class->add_player('player1', $_config->{player}); }
  • 25. Adding locations is a loop They are added one-by-one. sub add_locations { my ($class, $locations) = @_; foreach my $key (keys %{$locations}) { $class->add_location($key, $locations->{$key}); } }
  • 26. Adding one location Finally: The root of all evil... New locations are added with a key and struct: sub add_location { my ($class, $key, $config) = @_; my $location = Adventure::Location->new; $location->init($key, $config); $class->locations->{$key} = $location; }
  • 27. Faking the location sub install_test_location { my $package = shift; my $test_struct = shift; *{ qualify_to_ref add_location => $package } = sub { my ($class, $key ) = @_; $class->locations->{$key} = Adventure::Location ->new ->init($key, $test_struct ); # hardwired map }; }
  • 28. Aside: Generic “add” handler # e.g., install Adventure::Location::add_location sub add_thingy { my ( $parent, $thing ) = @_; my $name = ‘add_’ . $thing; my $package = qualify ucfirst(lc $thing), $parent; *{ qualify_to_ref $name => $package } = sub { my ($class, $name, $data ) = @_; $class->$type->{$name} = $package->new->init($name, $data ); };
  • 29. Summary Exercising objects is simple, repetitive. MJD’s “Red Flags”: don’t cut & paste. Replace hardwired loops with data-driven code. Object::Exercise standardizes the loops. Tests are declarative data.