SlideShare uma empresa Scribd logo
1 de 68
Baixar para ler offline
Getting There from Here:
Unit testing a few generations of code.
Steven Lembark
Workhorse Computing
lembark@wrkhors.com
perl 5.8
Fun isn’t it? A generation of nothing.
No improvements in Perl.
No advances in CPAN.
No reason to upgrade.
20 years of nada...
Ask all the programmers stuck with 5.8.
perl 5.8
Q: Why are we stuck with 5.8?
A: /usr/bin/perl is 5.8
Q: Why are we stuck with /usr/bin/perl?
A: ???
perl 5.8
Q: Why are we stuck with 5.8?
A: /usr/bin/perl is 5.8
Q: Why are we stuck with /usr/bin/perl?
A: Because “it worked”.
perl 5.8
Q: Why are we stuck with 5.8?
A: /usr/bin/perl is 5.8
Q: Why are we stuck with /usr/bin/perl?
A: Because something else “might not” work.
perl 5.8
Q: Why are we stuck with 5.8?
A: /usr/bin/perl is 5.8
Q: Why are we stuck with /usr/bin/perl?
A: Because we can’t show that 5.X works.
(for some definition of Christmas > 5.8)
perl 5.X
Q: Why can’t we show that 5.X works?
A: Because Christmas came after 2002.
perl 5.X
Q: Why can’t we show that 5.X works?
A: Because we stopped testing our code.
perl 5.X
Q: Why can’t we show that 5.X works?
A: Because they stopped testing our code.
perl 5.X
Q: Why can’t we show that 5.X works?
A: Because we have worked around it for way too long.
perl 5.X
Q: Why can’t we show that 5.X works?
A: Because we have worked around it for way too long.
perlbrew, all of the other approaches to dodging
/usr/bin/perl.
OK how do we fix it?
Prove that “it works”.
With testing.
In one client’s case: Lots and lots of testing.
OK how do we fix it?
Prove that “it works”.
With testing.
In one client’s case: Lots and lots of testing.
75_000 modules worth of testing.
OK how do we fix it?
Prove that “it works”.
With testing.
In one client’s case: Lots and lots of testing.
75_000 modules worth of testing.
Q: But how did you write 75_000 unit tests?
OK how do we fix it?
Prove that “it works”.
With testing.
In one client’s case: Lots and lots of testing.
75_000 modules worth of automated testing.
A: Lazyness.
Syntax checks are the first pass.
Unit tests get a bad rap.
“They don’t really test anything.”
Syntax checks are the first pass.
Unit tests get a bad rap.
“They don’t really test anything.”
Except whether 75_000 modules compile.
Code that was written on 5.8.
That now to run on 5.20+.
How do we test that much code?
Metadata driven testing:
Encode data into a test.
The standard test is data-driven.
Tests each validate one small part of a module.
How do we test that much code?
Q: How do you write that many tests?
A: Don’t.
How do we test that much code?
Q: How do you write that many tests?
A: Don’t.
Symlinks are your friends.
Simple basic test: require_ok
Run “require_ok $module” for every *.pm.
Simple, basic, obvious test for syntax errors.
… missing modules.
… botched system paths.
… all sorts of things.
Simple basic test: require_ok
Run “require_ok $module” for every *.pm.
Simple, basic, obvious test for syntax errors.
Nice thing: $module can be a path.
Even an absolute path.
Passing a path
“require_ok $path”
One argument.
Q: How do we pass it?
A: In the basename of a test.
Basic unit test
use v5.30;
use Test::More;
use File::Basename;
my $base0 = basename $0, '.t';
my $s = substr $base0, 0, 1;
my $path = join ‘/’, split m{[$s]}, $base0;
require_ok $path;
done_testing
__END__
Basic unit test
Install
them
using
shell.
#!/bin/bash
dir=$(cd $(dirname $0)/../..; pwd -L);
cd “$dir/t/01-units”;
find $dir/lib -name ‘*pm’ |
while read i
do
base=”$(echo $i | tr ‘/’ ‘~’).t”;
ln -fs ../bin/01-unit_t ./$base;
done
Basic unit test
Install
them
using
shell.
From
./t/bin
#!/bin/bash
dir=$(cd $(dirname $0)/../..; pwd -L);
cd “$dir/t/01-units”;
find $dir/lib -name ‘*pm’ |
while read i
do
base=”$(echo $i | tr ‘/’ ‘~’).t”;
ln -fs ../bin/01-unit_t ./$base;
done
Basic unit test
Install
them
using
shell.
Path to
basename.
#!/bin/bash
dir=$(cd $(dirname $0)/../..; pwd -L);
cd “$dir/t/01-units”;
find $dir/lib -name ‘*pm’ |
while read i
do
base=”$(echo $i | tr ‘/’ ‘~’).t”;
ln -fs ../bin/01-unit_t ./$base;
done
Basic unit test
Now you
know if it
compiles. prove t/01-units;
Basic unit test
Now you
know if it
compiles.
A bit
faster.
prove --jobs=8 t/01-units;
Basic unit test
Now you
know if it
compiles.
At 3am
without
watching.
args=(--jobs=8 --state=save );
prove ${args[*]} t/01-units;
Basic unit test
Now you
know if it
compiles.
At 8am
knowing
what
failed.
args=(--jobs=8 --state=save,failed );
prove ${args[*]} t/01-units;
Basic unit test
Now you
know if it
compiles.
Missing
module
anyone?
args=(--jobs=8 --state=save,failed );
prove ${args[*]} t/01-units
Can't locate Foo/Bar.pm in @INC (you
may need to install the Foo::Bar
module) (@INC contains:
/opt/perl/5.30/lib/site_perl/5.30.1/x8
6_64-linux
Basic unit test
Now you
know if it
compiles.
Fine:
Install
them.
args=(--jobs=8 --state=save,failed );
prove ${args[*]} t/01-units |
grep ‘you may need to install the’ |
cut -d’(‘ -f2 |
cut -d’ ‘ -f7 |
sort -d |
uniq |
cpanm ;
Basic unit test
Now you
know if it
compiles.
Local
mirror
provides
pre-
verified
modules.
args=(--jobs=8 --state=save,failed );
prove ${args[*]} t/01-units |
grep ‘you may need to install the’ |
cut -d’(‘ -f2 |
cut -d’ ‘ -f7 |
sort -d |
uniq |
cpanm -M$local ;
Basic unit test
Now you
know if it
compiles.
Local
library
simplifies
auto-
install.
args=(--jobs=8 --state=save,failed );
prove ${args[*]} t/01-units |
grep ‘you may need to install the’ |
cut -d’(‘ -f2 |
cut -d’ ‘ -f7 |
sort -d |
uniq |
cpanm 
-M$local -l$repo --self-contained ;
Basic unit test
Start with
a virgin
/opt/perl.
Keep
testing
until it’s
all use-
able.
args=(--jobs=8 --state=save,failed );
prove ${args[*]} t/01-units |
grep ‘you may need to install the’ |
cut -d’(‘ -f2 |
cut -d’ ‘ -f7 |
sort -d |
uniq |
cpanm 
-M$local -l$repo --self-contained ;
Version control what you install
git submodule add blah://.../site_perl;
perl Makefile.PL INSTALL_BASE=$PWD/site_perl;
cpanm --local-library=$PWD/site_perl;
If anyone asks, you know what non-core modules have
been installed.
If anything breaks, check out the last commit.
What else can we do with a path?
Ever fat-finger
a package?
package AcmeWigdit::Config;
use v5.30;
What else can we do with a path?
Ever fat-finger
a package?
Paths define
packages.
require_ok $path or skip ... ;
my ($sub)
= $path
=~ m{^.+?/lib/(.+?) [.]pm}x;
my $pkg = $sub =~ s{/}{::}g;
isa_ok $pkg, ‘UNIVERSAL’
or skip “$pkg not ‘UNIVERSAL’”;
$pkg->can( ‘VERSION’ )
or skip “$path missing $pkg”, 1;
What else can we do with a path?
Ever fat-finger
a package?
Paths define
packages.
All defined
packages are
UNIVERSAL.
require_ok $path or skip ... ;
my ($sub)
= $path
=~ m{^.+?/lib/(.+?) [.]pm}x;
my $pkg = $sub =~ s{/}{::}g;
isa_ok $pkg, ‘UNIVERSAL’
or skip “$pkg not ‘UNIVERSAL’”;
$pkg->can( ‘VERSION’ )
or skip “$path missing $pkg”, 1;
What else can we do with a path?
Ever fat-finger
a package?
Paths define
packages.
VERSION is
UNIVERSAL.
require_ok $path or skip ... ;
my ($sub)
= $path
=~ m{^.+?/lib/(.+?) [.]pm}x;
my $pkg = $sub =~ s{/}{::}g;
is_ok $pkg, ‘UNIVERSAL’
or skip “$pkg not ‘UNIVERSAL’”;
$pkg->can( ‘VERSION’ )
or skip “$path missing $pkg”, 1;
Minor issue with paths
Packages are related to paths.
We know that now.
In 2000 not everyone got that.
Minor issue with paths
What about:
package <basename>;
use lib <every directory everywhere>;
It works, but there are better ways...
Minor issue with paths
One pattern: Overlapping product of evolution.
./lib/AcmeWig/
./lib/AcmeWig/Config.pm AcmeWig::Config
Minor issue with paths
One pattern: Overlapping product of evolution.
./lib/AcmeWig/
./lib/AcmeWig/Config.pm AcmeWig::Config
Minor issue with paths
One pattern: Overlapping product of evolution.
./lib/AcmeWig/
./lib/AcmeWig/Config.pm AcmeWig::Config
./lib/AcmeWig/Acme/Config.pm Acme::Config
Minor issue with paths
One pattern: Overlapping product of evolution.
./lib/AcmeWig/
./lib/AcmeWig/Config.pm AcmeWig::Config
./lib/AcmeWig/Acme/Config.pm Acme::Config
What’s the expected package?
Solving nested paths
Say we figure out the paths:
qw
(
./lib/AcmeWig
./lib/AcmeWig/Acme
./lib/AcmeWig/Acme/Plastic/External
./lib/AcmeWig/Acme/Plastic/Internal
./lib/AcmeWig/Acme/Plastic/Wrappers
./lib/AcmeWig/Plastic
./lib/AcmeWig/AcmeWig/External/Plastic
)
Solving nested paths
We can obviously iterate them...
qw
(
./lib/AcmeWig
./lib/AcmeWig/Acme
./lib/AcmeWig/Acme/Plastic/External
./lib/AcmeWig/Acme/Plastic/Internal
./lib/AcmeWig/Acme/Plastic/Wrappers
./lib/AcmeWig/Plastic
./lib/AcmeWig/AcmeWig/External/Plastic
)
Solving nested paths
Q: But how do we avoid duplicate tests?
qw
(
./lib/AcmeWig
./lib/AcmeWig/Acme
./lib/AcmeWig/Acme/Plastic/External
./lib/AcmeWig/Acme/Plastic/Internal
./lib/AcmeWig/Acme/Plastic/Wrappers
./lib/AcmeWig/Plastic
./lib/AcmeWig/AcmeWig/External/Plastic
)
Solving nested paths
A: Sort them by length.
qw
(
./lib/AcmeWig/AcmeWig/External/Plastic
./lib/AcmeWig/Acme/Plastic/External
./lib/AcmeWig/Acme/Plastic/Internal
./lib/AcmeWig/Acme/Plastic/Wrappers
./lib/AcmeWig/Plastic
./lib/AcmeWig/Acme
./lib/AcmeWig
)
Solving nested paths
A: Sort them by length & exclude known paths.
qw
(
./lib/AcmeWig/AcmeWig/External/Plastic
./lib/AcmeWig/Acme/Plastic/External
./lib/AcmeWig/Acme/Plastic/Internal
./lib/AcmeWig/Acme/Plastic/Wrappers
./lib/AcmeWig/Plastic
./lib/AcmeWig/Acme
./lib/AcmeWig
)
Solving nested paths
my %prune = ();
my $wanted = sub
{
-d && exists $prune{ $File::Find::dir }
? $File::Find::prune = 1
: $File::Find::Path->$install_test_symlink
};
for my $dir ( @dirs_sorted_by_length )
{
find $wanted, $dir;
$prune{ $dir } = ();
}
Solving nested paths
my %prune = ();
my $wanted = sub
{
-d && exists $prune{ $File::Find::dir }
? $File::Find::prune = 1
: $File::Find::Path->$install_test_symlink
};
for my $dir ( @dirs_sorted_by_length )
{
find $wanted, $dir;
$prune{ $dir } = (); # don’t revisit
}
Testing nested paths
Catch: The test needs to know its ‘root’ directory.
Has to subtract that to get the expected package.
Testing nested paths
Catch: The test needs to know its ‘root’ directory.
Has to subtract that to get the expected package.
Fix: Double the separator.
~path~to~repo~lib~AcmeWig~Acme~Config.pm.t
Testing nested paths
Catch: The test needs to know its ‘root’ directory.
Has to subtract that to get the expected package.
Fix: Double the separator.
~path~to~repo~lib~AcmeWig~~Acme~Config.pm.t
Testing nested paths
Catch: The test needs to know its ‘root’ directory.
Has to subtract that to get the expected package.
Fix: ‘//’ works fine with require_ok.
~path~to~repo~lib~AcmeWig~~Acme~Config.pm.t
/path/to/repo/lib/AcmeWig//Acme/Config.pm.t
Testing nested paths
Catch: The test needs to know its ‘root’ directory.
Has to subtract that to get the expected package.
Fix: Gives sub-path for module.
~path~to~repo~lib~AcmeWig~~Acme~Config.pm.t
Acme~Config.pm.t
Testing nested paths
Catch: The test needs to know its ‘root’ directory.
Has to subtract that to get the expected package.
Fix: basename with s{~}{::}.
~path~to~repo~lib~AcmeWig~~Acme~Config.pm.t
Acme::Config
Testing nested paths
Catch: The test needs to know its ‘root’ directory.
Has to subtract that to get the expected package.
Save the search dir’s length and substr in a ‘~’:
my $l = length $dir;
...
substr $symlink, $l, 0, ‘~’;
Skipping test groups
We started with 75_000 files.
Found some dirs we didn’t want to test.
Fix:
my @no_test = qw( … );
my %prune = ();
@prune{ @no_test } = ();
Net result
We were able to test 45_000+ files each night.
Found missing modules.
Found outdated syntax.
Managed to get it all working.
Largey with “require_ok”.
Knowledge is power
Unit tests are useful.
Provide automated, reproducable results.
No excuse for “It may not work in v5.30.”
We can know.
And fix whatever “it” is.
For some definition of Perl5
Perl7 is coming.
Adopting it requires showing that “it works.”
Which means finding where it doesn’t.
Unit testing all of CPAN.
Unit testing all of everything.
For some definition of Perl5
Perl7 is coming.
Adopting it requires showing that “it works.”
Which means finding where it doesn’t.
Unit testing all of CPAN.
Unit testing all of everything.
We just have to be lazy about it.
Units of your very own!
In case you don’t like pasting from PDF:
https://gitlab.com/lembark/perl5-unit-tests
If anyone wants to work on this we can release it as
App::Testify or Test2::Unitz …
Be nice to have a migration suite for Perl7.
Units of your very own!
A wider range of unit tests is shown at:
https://www.slideshare.net/lembark/path-toknowlege
With a little bit of work we could get them all on CPAN.

Mais conteúdo relacionado

Mais procurados

The $path to knowledge: What little it take to unit-test Perl.
The $path to knowledge: What little it take to unit-test Perl.The $path to knowledge: What little it take to unit-test Perl.
The $path to knowledge: What little it take to unit-test Perl.Workhorse Computing
 
BSDM with BASH: Command Interpolation
BSDM with BASH: Command InterpolationBSDM with BASH: Command Interpolation
BSDM with BASH: Command InterpolationWorkhorse 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
 
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
 
Puppet camp chicago-automated_testing2
Puppet camp chicago-automated_testing2Puppet camp chicago-automated_testing2
Puppet camp chicago-automated_testing2nottings
 
Puppet: What _not_ to do
Puppet: What _not_ to doPuppet: What _not_ to do
Puppet: What _not_ to doPuppet
 
Test-Driven Puppet Development - PuppetConf 2014
Test-Driven Puppet Development - PuppetConf 2014Test-Driven Puppet Development - PuppetConf 2014
Test-Driven Puppet Development - PuppetConf 2014Puppet
 
Puppet loves RSpec, why you should, too
Puppet loves RSpec, why you should, tooPuppet loves RSpec, why you should, too
Puppet loves RSpec, why you should, tooDennis Rowe
 
What you need to remember when you upload to CPAN
What you need to remember when you upload to CPANWhat you need to remember when you upload to CPAN
What you need to remember when you upload to CPANcharsbar
 
Better detection of what modules are used by some Perl 5 code
Better detection of what modules are used by some Perl 5 codeBetter detection of what modules are used by some Perl 5 code
Better detection of what modules are used by some Perl 5 codecharsbar
 
Can you upgrade to Puppet 4.x?
Can you upgrade to Puppet 4.x?Can you upgrade to Puppet 4.x?
Can you upgrade to Puppet 4.x?Martin Alfke
 
Release with confidence
Release with confidenceRelease with confidence
Release with confidenceJohn Congdon
 
SDPHP - Percona Toolkit (It's Basically Magic)
SDPHP - Percona Toolkit (It's Basically Magic)SDPHP - Percona Toolkit (It's Basically Magic)
SDPHP - Percona Toolkit (It's Basically Magic)Robert Swisher
 
Working with databases in Perl
Working with databases in PerlWorking with databases in Perl
Working with databases in PerlLaurent Dami
 
Test Driven Development with Puppet - PuppetConf 2014
Test Driven Development with Puppet - PuppetConf 2014Test Driven Development with Puppet - PuppetConf 2014
Test Driven Development with Puppet - PuppetConf 2014Puppet
 
PL/Perl - New Features in PostgreSQL 9.0
PL/Perl - New Features in PostgreSQL 9.0PL/Perl - New Features in PostgreSQL 9.0
PL/Perl - New Features in PostgreSQL 9.0Tim Bunce
 

Mais procurados (20)

The $path to knowledge: What little it take to unit-test Perl.
The $path to knowledge: What little it take to unit-test Perl.The $path to knowledge: What little it take to unit-test Perl.
The $path to knowledge: What little it take to unit-test Perl.
 
Get your teeth into Plack
Get your teeth into PlackGet your teeth into Plack
Get your teeth into Plack
 
BSDM with BASH: Command Interpolation
BSDM with BASH: Command InterpolationBSDM with BASH: Command Interpolation
BSDM with BASH: Command Interpolation
 
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.
 
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 camp chicago-automated_testing2
Puppet camp chicago-automated_testing2Puppet camp chicago-automated_testing2
Puppet camp chicago-automated_testing2
 
Puppet: What _not_ to do
Puppet: What _not_ to doPuppet: What _not_ to do
Puppet: What _not_ to do
 
Test-Driven Puppet Development - PuppetConf 2014
Test-Driven Puppet Development - PuppetConf 2014Test-Driven Puppet Development - PuppetConf 2014
Test-Driven Puppet Development - PuppetConf 2014
 
Troubleshooting Puppet
Troubleshooting PuppetTroubleshooting Puppet
Troubleshooting Puppet
 
Puppet loves RSpec, why you should, too
Puppet loves RSpec, why you should, tooPuppet loves RSpec, why you should, too
Puppet loves RSpec, why you should, too
 
What you need to remember when you upload to CPAN
What you need to remember when you upload to CPANWhat you need to remember when you upload to CPAN
What you need to remember when you upload to CPAN
 
Better detection of what modules are used by some Perl 5 code
Better detection of what modules are used by some Perl 5 codeBetter detection of what modules are used by some Perl 5 code
Better detection of what modules are used by some Perl 5 code
 
Can you upgrade to Puppet 4.x?
Can you upgrade to Puppet 4.x?Can you upgrade to Puppet 4.x?
Can you upgrade to Puppet 4.x?
 
Release with confidence
Release with confidenceRelease with confidence
Release with confidence
 
SDPHP - Percona Toolkit (It's Basically Magic)
SDPHP - Percona Toolkit (It's Basically Magic)SDPHP - Percona Toolkit (It's Basically Magic)
SDPHP - Percona Toolkit (It's Basically Magic)
 
Lies, Damn Lies, and Benchmarks
Lies, Damn Lies, and BenchmarksLies, Damn Lies, and Benchmarks
Lies, Damn Lies, and Benchmarks
 
Working with databases in Perl
Working with databases in PerlWorking with databases in Perl
Working with databases in Perl
 
Puppet modules for Fun and Profit
Puppet modules for Fun and ProfitPuppet modules for Fun and Profit
Puppet modules for Fun and Profit
 
Test Driven Development with Puppet - PuppetConf 2014
Test Driven Development with Puppet - PuppetConf 2014Test Driven Development with Puppet - PuppetConf 2014
Test Driven Development with Puppet - PuppetConf 2014
 
PL/Perl - New Features in PostgreSQL 9.0
PL/Perl - New Features in PostgreSQL 9.0PL/Perl - New Features in PostgreSQL 9.0
PL/Perl - New Features in PostgreSQL 9.0
 

Semelhante a Unit Testing Lots of Perl

Continuous Integration Testing in Django
Continuous Integration Testing in DjangoContinuous Integration Testing in Django
Continuous Integration Testing in DjangoKevin Harvey
 
Ansible roles done right
Ansible roles done rightAnsible roles done right
Ansible roles done rightDan Vaida
 
How To Test Everything
How To Test EverythingHow To Test Everything
How To Test Everythingnoelrap
 
Can you upgrade to Puppet 4.x? (Beginner) Can you upgrade to Puppet 4.x? (Beg...
Can you upgrade to Puppet 4.x? (Beginner) Can you upgrade to Puppet 4.x? (Beg...Can you upgrade to Puppet 4.x? (Beginner) Can you upgrade to Puppet 4.x? (Beg...
Can you upgrade to Puppet 4.x? (Beginner) Can you upgrade to Puppet 4.x? (Beg...Puppet
 
Puppet Camp Duesseldorf 2014: Martin Alfke - Can you upgrade to puppet 4.x?
Puppet Camp Duesseldorf 2014: Martin Alfke - Can you upgrade to puppet 4.x?Puppet Camp Duesseldorf 2014: Martin Alfke - Can you upgrade to puppet 4.x?
Puppet Camp Duesseldorf 2014: Martin Alfke - Can you upgrade to puppet 4.x?NETWAYS
 
Advanced Perl Techniques
Advanced Perl TechniquesAdvanced Perl Techniques
Advanced Perl TechniquesDave Cross
 
How I hack on puppet modules
How I hack on puppet modulesHow I hack on puppet modules
How I hack on puppet modulesKris Buytaert
 
Drupal Camp Brighton 2015: Ansible Drupal Medicine show
Drupal Camp Brighton 2015: Ansible Drupal Medicine showDrupal Camp Brighton 2015: Ansible Drupal Medicine show
Drupal Camp Brighton 2015: Ansible Drupal Medicine showGeorge Boobyer
 
modern module development - Ken Barber 2012 Edinburgh Puppet Camp
modern module development - Ken Barber 2012 Edinburgh Puppet Campmodern module development - Ken Barber 2012 Edinburgh Puppet Camp
modern module development - Ken Barber 2012 Edinburgh Puppet CampPuppet
 
Angular JS in 2017
Angular JS in 2017Angular JS in 2017
Angular JS in 2017Ayush Sharma
 
Ansible with oci
Ansible with ociAnsible with oci
Ansible with ociDonghuKIM2
 
Automate Yo'self -- SeaGL
Automate Yo'self -- SeaGL Automate Yo'self -- SeaGL
Automate Yo'self -- SeaGL John Anderson
 

Semelhante a Unit Testing Lots of Perl (20)

Metadata-driven Testing
Metadata-driven TestingMetadata-driven Testing
Metadata-driven Testing
 
Continuous Integration Testing in Django
Continuous Integration Testing in DjangoContinuous Integration Testing in Django
Continuous Integration Testing in Django
 
Ansible roles done right
Ansible roles done rightAnsible roles done right
Ansible roles done right
 
How To Test Everything
How To Test EverythingHow To Test Everything
How To Test Everything
 
Ansible testing
Ansible   testingAnsible   testing
Ansible testing
 
Can you upgrade to Puppet 4.x? (Beginner) Can you upgrade to Puppet 4.x? (Beg...
Can you upgrade to Puppet 4.x? (Beginner) Can you upgrade to Puppet 4.x? (Beg...Can you upgrade to Puppet 4.x? (Beginner) Can you upgrade to Puppet 4.x? (Beg...
Can you upgrade to Puppet 4.x? (Beginner) Can you upgrade to Puppet 4.x? (Beg...
 
Puppet Camp Duesseldorf 2014: Martin Alfke - Can you upgrade to puppet 4.x?
Puppet Camp Duesseldorf 2014: Martin Alfke - Can you upgrade to puppet 4.x?Puppet Camp Duesseldorf 2014: Martin Alfke - Can you upgrade to puppet 4.x?
Puppet Camp Duesseldorf 2014: Martin Alfke - Can you upgrade to puppet 4.x?
 
Advanced Perl Techniques
Advanced Perl TechniquesAdvanced Perl Techniques
Advanced Perl Techniques
 
How I hack on puppet modules
How I hack on puppet modulesHow I hack on puppet modules
How I hack on puppet modules
 
Drupal Camp Brighton 2015: Ansible Drupal Medicine show
Drupal Camp Brighton 2015: Ansible Drupal Medicine showDrupal Camp Brighton 2015: Ansible Drupal Medicine show
Drupal Camp Brighton 2015: Ansible Drupal Medicine show
 
modern module development - Ken Barber 2012 Edinburgh Puppet Camp
modern module development - Ken Barber 2012 Edinburgh Puppet Campmodern module development - Ken Barber 2012 Edinburgh Puppet Camp
modern module development - Ken Barber 2012 Edinburgh Puppet Camp
 
Angular JS in 2017
Angular JS in 2017Angular JS in 2017
Angular JS in 2017
 
Autotesting rails app
Autotesting rails appAutotesting rails app
Autotesting rails app
 
Testing Ansible
Testing AnsibleTesting Ansible
Testing Ansible
 
Docker perl build
Docker perl buildDocker perl build
Docker perl build
 
IntroTestMore
IntroTestMoreIntroTestMore
IntroTestMore
 
IntroTestMore
IntroTestMoreIntroTestMore
IntroTestMore
 
Ansible with oci
Ansible with ociAnsible with oci
Ansible with oci
 
Automate Yo' Self
Automate Yo' SelfAutomate Yo' Self
Automate Yo' Self
 
Automate Yo'self -- SeaGL
Automate Yo'self -- SeaGL Automate Yo'self -- SeaGL
Automate Yo'self -- SeaGL
 

Mais de 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 ModulesWorkhorse 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 UpWorkhorse Computing
 
Generating & Querying Calendar Tables in Posgresql
Generating & Querying Calendar Tables in PosgresqlGenerating & Querying Calendar Tables in Posgresql
Generating & Querying Calendar Tables in PosgresqlWorkhorse Computing
 
Hypers and Gathers and Takes! Oh my!
Hypers and Gathers and Takes! Oh my!Hypers and Gathers and Takes! Oh my!
Hypers and Gathers and Takes! Oh my!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
 
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 & Perl6Workhorse 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 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
 
Ethiopian multiplication in Perl6
Ethiopian multiplication in Perl6Ethiopian multiplication in Perl6
Ethiopian multiplication in Perl6Workhorse Computing
 

Mais de Workhorse Computing (18)

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
 
mro-every.pdf
mro-every.pdfmro-every.pdf
mro-every.pdf
 
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
 
Hypers and Gathers and Takes! Oh my!
Hypers and Gathers and Takes! Oh my!Hypers and Gathers and Takes! Oh my!
Hypers and Gathers and Takes! Oh my!
 
Findbin libs
Findbin libsFindbin libs
Findbin libs
 
The W-curve and its application.
The W-curve and its application.The W-curve and its application.
The W-curve and its application.
 
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
 
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
 
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
 
Designing net-aws-glacier
Designing net-aws-glacierDesigning net-aws-glacier
Designing net-aws-glacier
 
Ethiopian multiplication in Perl6
Ethiopian multiplication in Perl6Ethiopian multiplication in Perl6
Ethiopian multiplication in Perl6
 

Último

08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhisoniya singh
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...HostedbyConfluent
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGSujit Pal
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 

Último (20)

08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAG
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 

Unit Testing Lots of Perl

  • 1. Getting There from Here: Unit testing a few generations of code. Steven Lembark Workhorse Computing lembark@wrkhors.com
  • 2. perl 5.8 Fun isn’t it? A generation of nothing. No improvements in Perl. No advances in CPAN. No reason to upgrade. 20 years of nada... Ask all the programmers stuck with 5.8.
  • 3. perl 5.8 Q: Why are we stuck with 5.8? A: /usr/bin/perl is 5.8 Q: Why are we stuck with /usr/bin/perl? A: ???
  • 4. perl 5.8 Q: Why are we stuck with 5.8? A: /usr/bin/perl is 5.8 Q: Why are we stuck with /usr/bin/perl? A: Because “it worked”.
  • 5. perl 5.8 Q: Why are we stuck with 5.8? A: /usr/bin/perl is 5.8 Q: Why are we stuck with /usr/bin/perl? A: Because something else “might not” work.
  • 6. perl 5.8 Q: Why are we stuck with 5.8? A: /usr/bin/perl is 5.8 Q: Why are we stuck with /usr/bin/perl? A: Because we can’t show that 5.X works. (for some definition of Christmas > 5.8)
  • 7. perl 5.X Q: Why can’t we show that 5.X works? A: Because Christmas came after 2002.
  • 8. perl 5.X Q: Why can’t we show that 5.X works? A: Because we stopped testing our code.
  • 9. perl 5.X Q: Why can’t we show that 5.X works? A: Because they stopped testing our code.
  • 10. perl 5.X Q: Why can’t we show that 5.X works? A: Because we have worked around it for way too long.
  • 11. perl 5.X Q: Why can’t we show that 5.X works? A: Because we have worked around it for way too long. perlbrew, all of the other approaches to dodging /usr/bin/perl.
  • 12. OK how do we fix it? Prove that “it works”. With testing. In one client’s case: Lots and lots of testing.
  • 13. OK how do we fix it? Prove that “it works”. With testing. In one client’s case: Lots and lots of testing. 75_000 modules worth of testing.
  • 14. OK how do we fix it? Prove that “it works”. With testing. In one client’s case: Lots and lots of testing. 75_000 modules worth of testing. Q: But how did you write 75_000 unit tests?
  • 15. OK how do we fix it? Prove that “it works”. With testing. In one client’s case: Lots and lots of testing. 75_000 modules worth of automated testing. A: Lazyness.
  • 16. Syntax checks are the first pass. Unit tests get a bad rap. “They don’t really test anything.”
  • 17. Syntax checks are the first pass. Unit tests get a bad rap. “They don’t really test anything.” Except whether 75_000 modules compile. Code that was written on 5.8. That now to run on 5.20+.
  • 18. How do we test that much code? Metadata driven testing: Encode data into a test. The standard test is data-driven. Tests each validate one small part of a module.
  • 19. How do we test that much code? Q: How do you write that many tests? A: Don’t.
  • 20. How do we test that much code? Q: How do you write that many tests? A: Don’t. Symlinks are your friends.
  • 21. Simple basic test: require_ok Run “require_ok $module” for every *.pm. Simple, basic, obvious test for syntax errors. … missing modules. … botched system paths. … all sorts of things.
  • 22. Simple basic test: require_ok Run “require_ok $module” for every *.pm. Simple, basic, obvious test for syntax errors. Nice thing: $module can be a path. Even an absolute path.
  • 23. Passing a path “require_ok $path” One argument. Q: How do we pass it? A: In the basename of a test.
  • 24. Basic unit test use v5.30; use Test::More; use File::Basename; my $base0 = basename $0, '.t'; my $s = substr $base0, 0, 1; my $path = join ‘/’, split m{[$s]}, $base0; require_ok $path; done_testing __END__
  • 25. Basic unit test Install them using shell. #!/bin/bash dir=$(cd $(dirname $0)/../..; pwd -L); cd “$dir/t/01-units”; find $dir/lib -name ‘*pm’ | while read i do base=”$(echo $i | tr ‘/’ ‘~’).t”; ln -fs ../bin/01-unit_t ./$base; done
  • 26. Basic unit test Install them using shell. From ./t/bin #!/bin/bash dir=$(cd $(dirname $0)/../..; pwd -L); cd “$dir/t/01-units”; find $dir/lib -name ‘*pm’ | while read i do base=”$(echo $i | tr ‘/’ ‘~’).t”; ln -fs ../bin/01-unit_t ./$base; done
  • 27. Basic unit test Install them using shell. Path to basename. #!/bin/bash dir=$(cd $(dirname $0)/../..; pwd -L); cd “$dir/t/01-units”; find $dir/lib -name ‘*pm’ | while read i do base=”$(echo $i | tr ‘/’ ‘~’).t”; ln -fs ../bin/01-unit_t ./$base; done
  • 28. Basic unit test Now you know if it compiles. prove t/01-units;
  • 29. Basic unit test Now you know if it compiles. A bit faster. prove --jobs=8 t/01-units;
  • 30. Basic unit test Now you know if it compiles. At 3am without watching. args=(--jobs=8 --state=save ); prove ${args[*]} t/01-units;
  • 31. Basic unit test Now you know if it compiles. At 8am knowing what failed. args=(--jobs=8 --state=save,failed ); prove ${args[*]} t/01-units;
  • 32. Basic unit test Now you know if it compiles. Missing module anyone? args=(--jobs=8 --state=save,failed ); prove ${args[*]} t/01-units Can't locate Foo/Bar.pm in @INC (you may need to install the Foo::Bar module) (@INC contains: /opt/perl/5.30/lib/site_perl/5.30.1/x8 6_64-linux
  • 33. Basic unit test Now you know if it compiles. Fine: Install them. args=(--jobs=8 --state=save,failed ); prove ${args[*]} t/01-units | grep ‘you may need to install the’ | cut -d’(‘ -f2 | cut -d’ ‘ -f7 | sort -d | uniq | cpanm ;
  • 34. Basic unit test Now you know if it compiles. Local mirror provides pre- verified modules. args=(--jobs=8 --state=save,failed ); prove ${args[*]} t/01-units | grep ‘you may need to install the’ | cut -d’(‘ -f2 | cut -d’ ‘ -f7 | sort -d | uniq | cpanm -M$local ;
  • 35. Basic unit test Now you know if it compiles. Local library simplifies auto- install. args=(--jobs=8 --state=save,failed ); prove ${args[*]} t/01-units | grep ‘you may need to install the’ | cut -d’(‘ -f2 | cut -d’ ‘ -f7 | sort -d | uniq | cpanm -M$local -l$repo --self-contained ;
  • 36. Basic unit test Start with a virgin /opt/perl. Keep testing until it’s all use- able. args=(--jobs=8 --state=save,failed ); prove ${args[*]} t/01-units | grep ‘you may need to install the’ | cut -d’(‘ -f2 | cut -d’ ‘ -f7 | sort -d | uniq | cpanm -M$local -l$repo --self-contained ;
  • 37. Version control what you install git submodule add blah://.../site_perl; perl Makefile.PL INSTALL_BASE=$PWD/site_perl; cpanm --local-library=$PWD/site_perl; If anyone asks, you know what non-core modules have been installed. If anything breaks, check out the last commit.
  • 38. What else can we do with a path? Ever fat-finger a package? package AcmeWigdit::Config; use v5.30;
  • 39. What else can we do with a path? Ever fat-finger a package? Paths define packages. require_ok $path or skip ... ; my ($sub) = $path =~ m{^.+?/lib/(.+?) [.]pm}x; my $pkg = $sub =~ s{/}{::}g; isa_ok $pkg, ‘UNIVERSAL’ or skip “$pkg not ‘UNIVERSAL’”; $pkg->can( ‘VERSION’ ) or skip “$path missing $pkg”, 1;
  • 40. What else can we do with a path? Ever fat-finger a package? Paths define packages. All defined packages are UNIVERSAL. require_ok $path or skip ... ; my ($sub) = $path =~ m{^.+?/lib/(.+?) [.]pm}x; my $pkg = $sub =~ s{/}{::}g; isa_ok $pkg, ‘UNIVERSAL’ or skip “$pkg not ‘UNIVERSAL’”; $pkg->can( ‘VERSION’ ) or skip “$path missing $pkg”, 1;
  • 41. What else can we do with a path? Ever fat-finger a package? Paths define packages. VERSION is UNIVERSAL. require_ok $path or skip ... ; my ($sub) = $path =~ m{^.+?/lib/(.+?) [.]pm}x; my $pkg = $sub =~ s{/}{::}g; is_ok $pkg, ‘UNIVERSAL’ or skip “$pkg not ‘UNIVERSAL’”; $pkg->can( ‘VERSION’ ) or skip “$path missing $pkg”, 1;
  • 42. Minor issue with paths Packages are related to paths. We know that now. In 2000 not everyone got that.
  • 43. Minor issue with paths What about: package <basename>; use lib <every directory everywhere>; It works, but there are better ways...
  • 44. Minor issue with paths One pattern: Overlapping product of evolution. ./lib/AcmeWig/ ./lib/AcmeWig/Config.pm AcmeWig::Config
  • 45. Minor issue with paths One pattern: Overlapping product of evolution. ./lib/AcmeWig/ ./lib/AcmeWig/Config.pm AcmeWig::Config
  • 46. Minor issue with paths One pattern: Overlapping product of evolution. ./lib/AcmeWig/ ./lib/AcmeWig/Config.pm AcmeWig::Config ./lib/AcmeWig/Acme/Config.pm Acme::Config
  • 47. Minor issue with paths One pattern: Overlapping product of evolution. ./lib/AcmeWig/ ./lib/AcmeWig/Config.pm AcmeWig::Config ./lib/AcmeWig/Acme/Config.pm Acme::Config What’s the expected package?
  • 48. Solving nested paths Say we figure out the paths: qw ( ./lib/AcmeWig ./lib/AcmeWig/Acme ./lib/AcmeWig/Acme/Plastic/External ./lib/AcmeWig/Acme/Plastic/Internal ./lib/AcmeWig/Acme/Plastic/Wrappers ./lib/AcmeWig/Plastic ./lib/AcmeWig/AcmeWig/External/Plastic )
  • 49. Solving nested paths We can obviously iterate them... qw ( ./lib/AcmeWig ./lib/AcmeWig/Acme ./lib/AcmeWig/Acme/Plastic/External ./lib/AcmeWig/Acme/Plastic/Internal ./lib/AcmeWig/Acme/Plastic/Wrappers ./lib/AcmeWig/Plastic ./lib/AcmeWig/AcmeWig/External/Plastic )
  • 50. Solving nested paths Q: But how do we avoid duplicate tests? qw ( ./lib/AcmeWig ./lib/AcmeWig/Acme ./lib/AcmeWig/Acme/Plastic/External ./lib/AcmeWig/Acme/Plastic/Internal ./lib/AcmeWig/Acme/Plastic/Wrappers ./lib/AcmeWig/Plastic ./lib/AcmeWig/AcmeWig/External/Plastic )
  • 51. Solving nested paths A: Sort them by length. qw ( ./lib/AcmeWig/AcmeWig/External/Plastic ./lib/AcmeWig/Acme/Plastic/External ./lib/AcmeWig/Acme/Plastic/Internal ./lib/AcmeWig/Acme/Plastic/Wrappers ./lib/AcmeWig/Plastic ./lib/AcmeWig/Acme ./lib/AcmeWig )
  • 52. Solving nested paths A: Sort them by length & exclude known paths. qw ( ./lib/AcmeWig/AcmeWig/External/Plastic ./lib/AcmeWig/Acme/Plastic/External ./lib/AcmeWig/Acme/Plastic/Internal ./lib/AcmeWig/Acme/Plastic/Wrappers ./lib/AcmeWig/Plastic ./lib/AcmeWig/Acme ./lib/AcmeWig )
  • 53. Solving nested paths my %prune = (); my $wanted = sub { -d && exists $prune{ $File::Find::dir } ? $File::Find::prune = 1 : $File::Find::Path->$install_test_symlink }; for my $dir ( @dirs_sorted_by_length ) { find $wanted, $dir; $prune{ $dir } = (); }
  • 54. Solving nested paths my %prune = (); my $wanted = sub { -d && exists $prune{ $File::Find::dir } ? $File::Find::prune = 1 : $File::Find::Path->$install_test_symlink }; for my $dir ( @dirs_sorted_by_length ) { find $wanted, $dir; $prune{ $dir } = (); # don’t revisit }
  • 55. Testing nested paths Catch: The test needs to know its ‘root’ directory. Has to subtract that to get the expected package.
  • 56. Testing nested paths Catch: The test needs to know its ‘root’ directory. Has to subtract that to get the expected package. Fix: Double the separator. ~path~to~repo~lib~AcmeWig~Acme~Config.pm.t
  • 57. Testing nested paths Catch: The test needs to know its ‘root’ directory. Has to subtract that to get the expected package. Fix: Double the separator. ~path~to~repo~lib~AcmeWig~~Acme~Config.pm.t
  • 58. Testing nested paths Catch: The test needs to know its ‘root’ directory. Has to subtract that to get the expected package. Fix: ‘//’ works fine with require_ok. ~path~to~repo~lib~AcmeWig~~Acme~Config.pm.t /path/to/repo/lib/AcmeWig//Acme/Config.pm.t
  • 59. Testing nested paths Catch: The test needs to know its ‘root’ directory. Has to subtract that to get the expected package. Fix: Gives sub-path for module. ~path~to~repo~lib~AcmeWig~~Acme~Config.pm.t Acme~Config.pm.t
  • 60. Testing nested paths Catch: The test needs to know its ‘root’ directory. Has to subtract that to get the expected package. Fix: basename with s{~}{::}. ~path~to~repo~lib~AcmeWig~~Acme~Config.pm.t Acme::Config
  • 61. Testing nested paths Catch: The test needs to know its ‘root’ directory. Has to subtract that to get the expected package. Save the search dir’s length and substr in a ‘~’: my $l = length $dir; ... substr $symlink, $l, 0, ‘~’;
  • 62. Skipping test groups We started with 75_000 files. Found some dirs we didn’t want to test. Fix: my @no_test = qw( … ); my %prune = (); @prune{ @no_test } = ();
  • 63. Net result We were able to test 45_000+ files each night. Found missing modules. Found outdated syntax. Managed to get it all working. Largey with “require_ok”.
  • 64. Knowledge is power Unit tests are useful. Provide automated, reproducable results. No excuse for “It may not work in v5.30.” We can know. And fix whatever “it” is.
  • 65. For some definition of Perl5 Perl7 is coming. Adopting it requires showing that “it works.” Which means finding where it doesn’t. Unit testing all of CPAN. Unit testing all of everything.
  • 66. For some definition of Perl5 Perl7 is coming. Adopting it requires showing that “it works.” Which means finding where it doesn’t. Unit testing all of CPAN. Unit testing all of everything. We just have to be lazy about it.
  • 67. Units of your very own! In case you don’t like pasting from PDF: https://gitlab.com/lembark/perl5-unit-tests If anyone wants to work on this we can release it as App::Testify or Test2::Unitz … Be nice to have a migration suite for Perl7.
  • 68. Units of your very own! A wider range of unit tests is shown at: https://www.slideshare.net/lembark/path-toknowlege With a little bit of work we could get them all on CPAN.