Testing with PostgreSQL

S
Shawn SorichettiSoftware Engineer at Colored Blocks

Using the Test::PostgreSQL, App::Sqitch, DBIx::Class and DBIx::ClassEasyFixture perl modules to build a testing environment that is dynamically created and destroyed with each execution. Test can be run both serial or parallel without impacting each other.

Testing
with
PostgreSQL
- First heard the term Polyglot Programmer during a
talk by John Anderson and found it described me
- Developed in Ruby, Python, Java, Groovy,
JavaScipt, C#, PHP, various SQL dialects, dabbled in
Go and of course perl
- I've been coding in perl since 1997
- started when I picked up AIX and needed to
automate some tasks
- haven't stopped automating since then
Hi, I'm Shawn.
• Polyglot Programmer
• First love is perl
• UNIX Geek
• Lots of database experience
• Currently on assignment with All Around the
World
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- described as a test runner however it doesn't
execute any test code
- Test::PostgreSQL allows testing with a throw away
database
- The 'test' here refers to not production or permanent
- I have been known to spin them up for debugging
from within reply
What is it?
• Test::PostgreSQL
• PostgreSQL runner for tests
• Test::PostgreSQL automatically sets up a
PostgreSQL instance in a temporary directory,
and destroys it when the perl script exits.
• Currently maintained by Toby Corkindale
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- pg_ctl is used by init scripts to initialize,
start, stop, or control a PostgreSQL server
- standard PostgreSQL port is 5432
- Automatically increments if the port is in
use (15433)
- can spawn multiple instances
How does it work
• Wrapper around the pg_ctl PostgreSQL controller
• Assigns a port if unused starting at 15432
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
Sqitch Basics
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- Covered last month by Cees, can be covered in
more detail in a dedicated talk
- Sqitch is a tool for managing your DDL.
- Sqitch is an application not a module so it can be
used with any project, and for numerous databases
- PostgreSQL variants like Netezza and Greenplum
should also work
Why?
• Sqitch gives us a methodology to setup and tear
down test databases that match what is is in
production.
• App::Sqitch
• Written by David Wheeler
• Works with Firebird, MySQL, Oracle, PostgreSQL,
SQLite, Vertica
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- Creates sqitch.conf, sqitch.plan, deploy/, revert/, verify/
- Create the first migration, creating files in the deploy/, revert/, verify/ with
the migration name
- A word on running with carton, I received an error message Cannot
find deploy template the work around was to add
template_directory = local/etc/sqitch/templates to
sqitch.conf in the add section
Fast Start
• Initialize sqitch environment
sqitch init test_postgresql --engine pg
• Creating a migration
sqitch add user_table -n 'Add user table.'
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- Simple user table
- quick note about TEXT columns, in PostgreSQL there is no
performance or storage benefit from using a fixed width VARCHAR
column, so just use TEXT
- PostgreSQL reserved words, user is a reserved word, and will
throw an error unless double quoted "user"
- while database connectivity can be specified in the
sqitch.conf file, personal preference is to use it on the
command line.
Deploying
Creates file deploy/user_table.sql
-- Deploy test_postgresql:user_table to pg
BEGIN;
CREATE TABLE "user" (
user_id SERIAL PRIMARY KEY,
user_name TEXT UNIQUE,
password TEXT
);
COMMIT;
Executed by issuing:
sqitch deploy db:pg:test_db
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- ROLLBACK verifications can change data, and at the end
they will be undone by default.
- Table creation verification is simple, and if it didn't create,
there would be a SQL error during deployment.
- More advanced verification for procedures and table
alters
Verifying
Creates file verify/user_table.sql.
-- Verify test_postgresql:user_table on pg
BEGIN;
SELECT 1/COUNT(0)
FROM information_schema.tables
WHERE table_name = 'user'
;
ROLLBACK;
Executed by issuing:
sqitch verify db:pg:test_db
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- When you need to remove changes
- Reverting is destructive and the only way
to go back is through restoring
Reverting
Creates file revert/user_table.sql.
-- Revert test_postgresql:user_table from pg
BEGIN;
DROP TABLE "user";
COMMIT;
Executed by issuing:
sqitch revert db:pg:test_db
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- Overtime changes aren't backward compatible and running sqitch
verify will break.
- During these times using the --verify switch during deployment
tells sqitch to verify what it's deploying, not what has already been
deployed.
Verifying during deployment
Executed by issuing:
sqitch deploy --verify db:pg:test_db
Verify each migration after deploying.
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
The
Test::PostgreSQL
Module
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- While the name suggests test, it's really a temporary
PostgreSQL database
Not just for
testing!
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- Avoid dbicdump creating
my_tmp_table_bkup
- Force truth into sqitch
DBIC Schema Update Utility
• Helps keep sqitch deployments and DBIC schemas
in sync
• Ensures that developer temporary changes don't
make their way into DBIC schemas
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- Creates a new PostgreSQL database
- Deploys sqitch database migrations to it
- Runs dbicdump to create the DBIC
schema packages
- This code is going to become familiar
dbic_update.pl
use App::Sqitch;
use App::Sqitch::Command::deploy;
use App::Sqitch::Command::verify;
use Test::PostgreSQL;
my $db = Test::PostgreSQL->new;
my $sqitch = App::Sqitch->new(
options => {
engine => 'pg',
},
);
my $deploy = App::Sqitch::Command::deploy->new(
sqitch => $sqitch,
target => $db->uri,
);
$deploy->execute();
say $db->dsn;
my $dsn = $db->dsn;
$dsn =~ s/^dbi/dbi/i;
$dsn =~ s/dbname=/database=/i;
system "dbicdump -o dump_directory=./lib MyApp::Schema '$dsn'";
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- calling sqitch from within a script/module was
added in 0.996 with a patch from Chris Prather
- used to error out on a Moose error
Automating Sqitch for Testing
Requires App::Sqitch version 0.996
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- going to create a temporary database
- deploy and verify each step in turn
- test that reverting each step succeeds
- there's no test at the end to make sure
the database is back to an empty state
Test Sqitch automation
• Creates a test database
• Runs deploy and verify steps
• Reverts changes
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- There is the option of executing the command line via
system, however I find this method cleaner, even though
it uses more modules up front
- Test modules and the App::Sqitch internals
Setting up the test
use Test::PostgreSQL;
use Test::Most;
use App::Sqitch;
use App::Sqitch::Target;
use App::Sqitch::Command::deploy;
use App::Sqitch::Command::verify;
use App::Sqitch::Command::revert;
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- Calling new on Test::PostgreSQL starts the
PostgreSQL instance
Setting up the database
my $db = Test::PostgreSQL->new;
my $sqitch = App::Sqitch->new(
options => {
engine => 'pg',
},
);
my $target = App::Sqitch::Target->new( sqitch => $sqitch);
my $plan = $target->plan;
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- Tell Sqitch that we want to execute using a pg engine
- Sqitch classes are a hierarchy, need to build each
individual object to proceed
Setting up Sqitch
my $db = Test::PostgreSQL->new;
my $sqitch = App::Sqitch->new(
options => {
engine => 'pg',
},
);
my $target = App::Sqitch::Target->new( sqitch => $sqitch);
my $plan = $target->plan;
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- Set the Sqitch target and read in the plan file
Getting the Sqitch plan
my $db = Test::PostgreSQL->new;
my $sqitch = App::Sqitch->new(
options => {
engine => 'pg',
},
);
my $target = App::Sqitch::Target->new( sqitch => $sqitch);
my $plan = $target->plan;
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- plan file contents are not necessarily in order
- The $plan iterator is used to get the next step
in the plan
- Run a deploy on each step via deploy
command
- to_change will process the plan up to and
including the specified change
Looping through the plan
while ( my $change = $plan->next ) {
my $deploy = App::Sqitch::Command::deploy->new(
sqitch => $sqitch,
target => $db->uri,
to_change => $change->name,
);
lives_ok { $deploy->execute() } 'deploy sqitch plan to ' . $change->name;
my $verify = App::Sqitch::Command::verify->new(
sqitch => $sqitch,
target => $db->uri,
to_change => $change->name,
);
lives_ok { $verify->execute() } 'verify sqitch plan';
push @revert, $change->name;
}
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- Run a verify on each step via verify command
- to_change will process the verify plan up to
and including the specified change
Looping through the plan
while ( my $change = $plan->next ) {
my $deploy = App::Sqitch::Command::deploy->new(
sqitch => $sqitch,
target => $db->uri,
to_change => $change->name,
);
lives_ok { $deploy->execute() } 'deploy sqitch plan to ' . $change->name;
my $verify = App::Sqitch::Command::verify->new(
sqitch => $sqitch,
target => $db->uri,
to_change => $change->name,
);
lives_ok { $verify->execute() } 'verify sqitch plan';
push @revert, $change->name;
}
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- Store the change to be able to revert it in reverse order
later
Looping through the plan
while ( my $change = $plan->next ) {
my $deploy = App::Sqitch::Command::deploy->new(
sqitch => $sqitch,
target => $db->uri,
to_change => $change->name,
);
lives_ok { $deploy->execute() } 'deploy sqitch plan to ' . $change->name;
my $verify = App::Sqitch::Command::verify->new(
sqitch => $sqitch,
target => $db->uri,
to_change => $change->name,
);
lives_ok { $verify->execute() } 'verify sqitch plan';
push @revert, $change->name;
}
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- If we try to revert the last change, sqitch will complain that
there's nothing further deployed.
Looping through the plan
pop @revert;
while ( my $change_name = pop @revert ) {
my $verify = App::Sqitch::Command::revert->new(
sqitch => $sqitch,
target => $db->uri,
to_change => $change_name,
no_prompt => 1,
);
lives_ok { $verify->execute() } 'revert sqitch plan to ' . $change_name;
}
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- We've built and verified the entire database
structure and now we'll tear it down
- Run the revert command on each change
Looping through the plan
pop @revert;
while ( my $change_name = pop @revert ) {
my $verify = App::Sqitch::Command::revert->new(
sqitch => $sqitch,
target => $db->uri,
to_change => $change_name,
no_prompt => 1,
);
lives_ok { $verify->execute() } 'revert sqitch plan to ' . $change_name;
}
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- highlevel of the module with methods
- The skeleton provides methods to be used
during your testing: db, dsn, dbh, dbic
- Now step into each of the methods
Test Module Skeleton
package MyApp::Test::PostgreSQL;
use strict;
use warnings;
use App::Sqitch;
use Moose;
use DBI;
use Test::PostgreSQL;
use DateTime;
use MyApp::Schema;
use App::Sqitch::Command::deploy;
+-- 6 lines: has db => (-----------------------------------------------------------------------------------------
+-- 6 lines: has dsn => (----------------------------------------------------------------------------------------
+-- 15 lines: has dbh => (----------------------------------------------------------------------------------------
+-- 9 lines: has dbic => (---------------------------------------------------------------------------------------
+-- 11 lines: has sqitch => (-------------------------------------------------------------------------------------
+-- 7 lines: has fixtures => (-----------------------------------------------------------------------------------
+-- 10 lines: has perm_fixtures => (------------------------------------------------------------------------------
+-- 8 lines: sub deploy {----------------------------------------------------------------------------------------
no Moose;
__PACKAGE__->meta->make_immutable;
1;
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- access to the Test::PostgreSQL object
- not really needed during testing directly
MyApp::Test::PostgreSQL::db
has db => (
is => 'ro',
isa => 'Test::PostgreSQL',
lazy => 1,
default => sub { Test::PostgreSQL->new },
);
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- returns the dsn created by Test::PostgreSQL
- simple string that can be used to create
additional connections
- Create new DBI connections, hand over to
applications
MyApp::Test::PostgreSQL::dsn
has dsn => (
is => 'ro',
isa => 'Str',
lazy => 1,
default => sub { return $_[0]->db->dsn },
);
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- returns a DBI database handle connected to the
Test::PostgreSQL instance.
- this is a shared connection, transactions might cause
issues, if in doubt start a new connection
MyApp::Test::PostgreSQL::dbh
has dbh => (
is => 'ro',
lazy => 1,
default => sub {
DBI->connect(
$_[0]->dsn,
undef, undef,
{
pg_enable_utf8 => 1,
RaiseError => 1,
AutoCommit => 1,
}
)
}
);
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- returns a DBIC Schema object
- uses the Schema object from your
application
MyApp::Test::PostgreSQL::dbic
has dbic => (
is => 'ro',
lazy => 1,
default => sub {
my ($self) = @_;
MyApp::Schema->connect({
dbh_maker => sub { $self->dbh },
quote_names => 1,
});
}
);
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- Data to add to the database for testing
- Written by Curtis "Ovid" Poe
- While stating that it's Alpha software,
we use it a lot
Fixtures
• DBIx::Class::EasyFixture
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- there's a lot of details here and the packages can get
quite large
- this example shows the necessities, real world the
%definition_for hash is huge
- going to break this down and explain what's going on
The Fixture Package
package MyApp::Test::Fixtures;
use Moose;
extends 'DBIx::Class::EasyFixture';
use Crypt::Bcrypt::Easy ();
my %definition_for = (
basic_user => {
new => 'User',
using => {
user_name => 'tester',
password => Crypt::Bcrypt::Easy->crypt( text => 'tester', cost => 10 )
},
next => [qw(user_entry)],
},
user_entry => {
new => 'Entry',
using => {
user_id => 'basic_user',
entry => 'This is my entry.',
},
},
);
sub get_definition {
my ( $self, $name ) = @_;
return $definition_for{$name};
}
sub all_fixture_names { return keys %definition_for }
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- This is the data definition, but more to come
We'll come back to this
package MyApp::Test::Fixtures;
use Moose;
extends 'DBIx::Class::EasyFixture';
use Crypt::Bcrypt::Easy ();
my %definition_for = (
basic_user => {
new => 'User',
using => {
user_name => 'tester',
password => Crypt::Bcrypt::Easy->crypt( text => 'tester', cost => 10 )
},
next => [qw(user_entry)],
},
user_entry => {
new => 'Entry',
using => {
user_id => 'basic_user',
entry => 'This is my entry.',
},
},
);
sub get_definition {
my ( $self, $name ) = @_;
return $definition_for{$name};
}
sub all_fixture_names { return keys %definition_for }
Let's ignore this section for now and return after looking at the basics.
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- DBIx::Class:EasyFixture requires that
get_definition and all_fixture_names be
overridden.
- These are the simplest definitions and can be reused
Required overrides
package MyApp::Fixtures;
use Moose;
extends 'DBIx::Class::EasyFixture';
use Crypt::Bcrypt::Easy ();
my %definition_for = (
basic_user => {
new => 'User',
using => {
user_name => 'tester',
password => Crypt::Bcrypt::Easy->crypt( text => 'tester', cost => 10 )
},
next => [qw(user_entry)],
},
user_entry => {
new => 'Entry',
using => {
user_id => 'basic_user',
entry => 'This is my entry.',
},
},
);
sub get_definition {
my ( $self, $name ) = @_;
return $definition_for{$name};
}
sub all_fixture_names { return keys %definition_for }
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- basic_user is a unique identifier
- new is the result set full package name is
MyApp::Schema::Result::User
- using is the record data
- able to mix in function calls like password
- next and requires can be used to
specify fixture dependencies
- STRINGREF is a reference to an existing
Data definition
...
my %definition_for = (
basic_user => {
new => 'User',
using => {
user_name => 'tester',
password => Crypt::Bcrypt::Easy->crypt( text => 'tester', cost => 10 )
},
next => [qw(user_entry)],
},
user_entry => {
new => 'Entry',
using => {
user_id => 'basic_user',
entry => 'This is my entry.',
},
},
);
...
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- Access to the fixtures object
- Fixtures by default are written in one
transaction
MyApp::Test::PostgreSQL::fixtures
has fixtures => (
is => 'ro',
lazy => 1,
default => sub {
MyApp::Test::Fixtures->new( { schema => $_[0]->dbic } )
},
);
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- Access to the fixtures object
- Disable transactions so that other sessions
can access the data
MyApp::Test::PostgreSQL::perm_fixtures
has perm_fixtures => (
is => 'ro',
lazy => 1,
default => sub {
MyApp::Test::Fixtures->new( {
schema => $_[0]->dbic,
no_transactions => 1,
} )
},
);
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- At this point you have a populated database
- New connections can access the database via
$dsn
- diag $dsn is useful for connecting with an
external client
- full access to the MyApp::Test::PostgreSQL
methods for access to dbh, and dbic
Actually writing tests
use MyApp::Test::PostgreSQL;
use MyApp::Test::Fixtures;
use Test::Most;
my $db = MyApp::Test::PostgreSQL->new;
my $dbic = $db->dbic;
my $dsn = $db->dsn;
$dsn =~ s/^dbi/dbi/i;
diag $dsn;
lives_ok { $db->deploy } 'database set up';
$db->perm_fixtures->load('basic_user');
# Add all your test methods here
$db->perm_fixtures->unload;
done_testing;
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- t/lib required as that's where the MyApp::Test
modules live
Running tests
prove -lv -I t/lib t/simple.t
t/simple.t .. # dbi:Pg:dbname=test;host=127.0.0.1;port=15432;user=postgres
Adding registry tables to db:postgresql://postgres@127.0.0.1:15432/test
Deploying changes to db:postgresql://postgres@127.0.0.1:15432/test
+ user_table ... ok
+ entry_table .. ok
ok 1 - database set up
1..1
Pg refused to die gracefully; killing it violently.
Pg really didn't die.. WTF?
ok
All tests successful.
Files=1, Tests=1, 20 wallclock secs ( 0.03 usr 0.02 sys + 2.53 cusr 1.31 csys = 3.89 CPU)
Result: PASS
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- Yeah, these error messages are interesting
- non-impacting, might have something to
do with fixtures
WTF?
prove -lv -I t/lib t/simple.t
t/simple.t .. # dbi:Pg:dbname=test;host=127.0.0.1;port=15432;user=postgres
Adding registry tables to db:postgresql://postgres@127.0.0.1:15432/test
Deploying changes to db:postgresql://postgres@127.0.0.1:15432/test
+ user_table ... ok
+ entry_table .. ok
ok 1 - database set up
1..1
Pg refused to die gracefully; killing it violently.
Pg really didn't die.. WTF?
ok
All tests successful.
Files=1, Tests=1, 20 wallclock secs ( 0.03 usr 0.02 sys + 2.53 cusr 1.31 csys = 3.89 CPU)
Result: PASS
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
- Written by Curtis "Ovid" Poe
- Originally written by Curtis "Ovid" Poe, and now
maintained by Dave Rolsky
- Haven't used Test::mongod though it's on my list of
modules to try and tests to migrate, written by co-worker
Jesse Shy
More Reading
• DBIx::Class::EasyFixture::Tutorial - It's
complicated
• Test::Class::Moose - Serious testing for
serious Perl
• Test::mongod - run a temporary instance of
MongoDB by Jesse Shy
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
References
• Test::PostgreSQL
• Reply
• App::Sqitch
• DBIx::Class::EasyFixture
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
MoreTesting with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
Updating DBIC Schemas
#!/bin/env perl
use v5.20;
use autodie ':all';
use App::Sqitch;
use App::Sqitch::Command::deploy;
use App::Sqitch::Command::verify;
use Test::PostgreSQL;
my $db = Test::PostgreSQL->new;
my $sqitch = App::Sqitch->new(
options => {
engine => 'pg',
},
);
my $deploy = App::Sqitch::Command::deploy->new(
sqitch => $sqitch,
target => $db->uri,
);
$deploy->execute();
say $db->dsn;
my $dsn = $db->dsn;
$dsn =~ s/^dbi/dbi/i;
$dsn =~ s/dbname=/database=/i;
system "dbicdump -o dump_directory=./lib MyApp::Schema '$dsn'";
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
sqitch.t
use Test::PostgreSQL;
use Test::Most;
use App::Sqitch;
use App::Sqitch::Target;
use App::Sqitch::Command::deploy;
use App::Sqitch::Command::verify;
use App::Sqitch::Command::revert;
bail_on_fail;
my $db = Test::PostgreSQL->new;
my $sqitch = App::Sqitch->new(
options => {
engine => 'pg',
},
);
my $target = App::Sqitch::Target->new( sqitch => $sqitch);
my $plan = $target->plan;
my ( @revert );
while ( my $change = $plan->next ) {
my $deploy = App::Sqitch::Command::deploy->new(
sqitch => $sqitch,
target => $db->uri,
to_change => $change->name,
);
lives_ok { $deploy->execute() } 'deploy sqitch plan to ' . $change->name;
my $verify = App::Sqitch::Command::verify->new(
sqitch => $sqitch,
target => $db->uri,
to_change => $change->name,
);
lives_ok { $verify->execute() } 'verify sqitch plan';
push @revert, $change->name;
}
pop @revert;
while ( my $change_name = pop @revert ) {
my $verify = App::Sqitch::Command::revert->new(
sqitch => $sqitch,
target => $db->uri,
to_change => $change_name,
no_prompt => 1,
);
lives_ok { $verify->execute() } 'revert sqitch plan to ' . $change_name;
}
done_testing();
Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti

Recommended

Docker in Continuous Integration by
Docker in Continuous IntegrationDocker in Continuous Integration
Docker in Continuous IntegrationAlexander Akbashev
103 views55 slides
We Are All Testers Now: The Testing Pyramid and Front-End Development by
We Are All Testers Now: The Testing Pyramid and Front-End DevelopmentWe Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End DevelopmentAll Things Open
375 views60 slides
An introduction to maven gradle and sbt by
An introduction to maven gradle and sbtAn introduction to maven gradle and sbt
An introduction to maven gradle and sbtFabio Fumarola
8.2K views45 slides
Jenkins Shared Libraries Workshop by
Jenkins Shared Libraries WorkshopJenkins Shared Libraries Workshop
Jenkins Shared Libraries WorkshopJulien Pivotto
19.7K views117 slides
Everything as a code by
Everything as a codeEverything as a code
Everything as a codeAleksandr Tarasov
1.2K views197 slides
openQA hands on with openSUSE Leap 42.1 - openSUSE.Asia Summit ID 2016 by
openQA hands on with openSUSE Leap 42.1 - openSUSE.Asia Summit ID 2016openQA hands on with openSUSE Leap 42.1 - openSUSE.Asia Summit ID 2016
openQA hands on with openSUSE Leap 42.1 - openSUSE.Asia Summit ID 2016Ben Chou
805 views40 slides

More Related Content

What's hot

Gradle For Beginners (Serbian Developer Conference 2013 english) by
Gradle For Beginners (Serbian Developer Conference 2013 english)Gradle For Beginners (Serbian Developer Conference 2013 english)
Gradle For Beginners (Serbian Developer Conference 2013 english)Joachim Baumann
2.6K views24 slides
Continuous Integration and DevOps with Open Build Service(OBS) by
Continuous Integration and DevOps with Open Build Service(OBS)Continuous Integration and DevOps with Open Build Service(OBS)
Continuous Integration and DevOps with Open Build Service(OBS)Ralf Dannert
4.2K views52 slides
Cool Jvm Tools to Help you Test - Aylesbury Testers Version by
Cool Jvm Tools to Help you Test - Aylesbury Testers VersionCool Jvm Tools to Help you Test - Aylesbury Testers Version
Cool Jvm Tools to Help you Test - Aylesbury Testers VersionSchalk Cronjé
1.8K views55 slides
Continuous Infrastructure: Modern Puppet for the Jenkins Project - PuppetConf... by
Continuous Infrastructure: Modern Puppet for the Jenkins Project - PuppetConf...Continuous Infrastructure: Modern Puppet for the Jenkins Project - PuppetConf...
Continuous Infrastructure: Modern Puppet for the Jenkins Project - PuppetConf...Puppet
5K views51 slides
Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ... by
Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...
Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...Puppet
3K views32 slides
Using the Groovy Ecosystem for Rapid JVM Development by
Using the Groovy Ecosystem for Rapid JVM DevelopmentUsing the Groovy Ecosystem for Rapid JVM Development
Using the Groovy Ecosystem for Rapid JVM DevelopmentSchalk Cronjé
895 views79 slides

What's hot(20)

Gradle For Beginners (Serbian Developer Conference 2013 english) by Joachim Baumann
Gradle For Beginners (Serbian Developer Conference 2013 english)Gradle For Beginners (Serbian Developer Conference 2013 english)
Gradle For Beginners (Serbian Developer Conference 2013 english)
Joachim Baumann2.6K views
Continuous Integration and DevOps with Open Build Service(OBS) by Ralf Dannert
Continuous Integration and DevOps with Open Build Service(OBS)Continuous Integration and DevOps with Open Build Service(OBS)
Continuous Integration and DevOps with Open Build Service(OBS)
Ralf Dannert4.2K views
Cool Jvm Tools to Help you Test - Aylesbury Testers Version by Schalk Cronjé
Cool Jvm Tools to Help you Test - Aylesbury Testers VersionCool Jvm Tools to Help you Test - Aylesbury Testers Version
Cool Jvm Tools to Help you Test - Aylesbury Testers Version
Schalk Cronjé1.8K views
Continuous Infrastructure: Modern Puppet for the Jenkins Project - PuppetConf... by Puppet
Continuous Infrastructure: Modern Puppet for the Jenkins Project - PuppetConf...Continuous Infrastructure: Modern Puppet for the Jenkins Project - PuppetConf...
Continuous Infrastructure: Modern Puppet for the Jenkins Project - PuppetConf...
Puppet5K views
Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ... by Puppet
Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...
Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...
Puppet3K views
Using the Groovy Ecosystem for Rapid JVM Development by Schalk Cronjé
Using the Groovy Ecosystem for Rapid JVM DevelopmentUsing the Groovy Ecosystem for Rapid JVM Development
Using the Groovy Ecosystem for Rapid JVM Development
Schalk Cronjé895 views
Aug penguin16 by alhino
Aug penguin16Aug penguin16
Aug penguin16
alhino99 views
Puppetconf 2015 - Puppet Reporting with Elasticsearch Logstash and Kibana by pkill
Puppetconf 2015 - Puppet Reporting with Elasticsearch Logstash and KibanaPuppetconf 2015 - Puppet Reporting with Elasticsearch Logstash and Kibana
Puppetconf 2015 - Puppet Reporting with Elasticsearch Logstash and Kibana
pkill3.8K views
Test-Driven Infrastructure with Ansible, Test Kitchen, Serverspec and RSpec by Martin Etmajer
Test-Driven Infrastructure with Ansible, Test Kitchen, Serverspec and RSpecTest-Driven Infrastructure with Ansible, Test Kitchen, Serverspec and RSpec
Test-Driven Infrastructure with Ansible, Test Kitchen, Serverspec and RSpec
Martin Etmajer43.3K views
Test Driven Development with Puppet - PuppetConf 2014 by Puppet
Test Driven Development with Puppet - PuppetConf 2014Test Driven Development with Puppet - PuppetConf 2014
Test Driven Development with Puppet - PuppetConf 2014
Puppet5.4K views
Testing Your Automation Code (Docker Version) by Mischa Taylor
Testing Your Automation Code (Docker Version)Testing Your Automation Code (Docker Version)
Testing Your Automation Code (Docker Version)
Mischa Taylor4K views
Test Driven Development with Puppet by Puppet
Test Driven Development with Puppet Test Driven Development with Puppet
Test Driven Development with Puppet
Puppet3.5K views
Супер быстрая автоматизация тестирования на iOS by SQALab
Супер быстрая автоматизация тестирования на iOSСупер быстрая автоматизация тестирования на iOS
Супер быстрая автоматизация тестирования на iOS
SQALab806 views
Killer R10K Workflow - PuppetConf 2014 by Puppet
Killer R10K Workflow - PuppetConf 2014Killer R10K Workflow - PuppetConf 2014
Killer R10K Workflow - PuppetConf 2014
Puppet12.2K views
Workshop: Know Before You Push 'Go': Using the Beaker Acceptance Test Framewo... by Puppet
Workshop: Know Before You Push 'Go': Using the Beaker Acceptance Test Framewo...Workshop: Know Before You Push 'Go': Using the Beaker Acceptance Test Framewo...
Workshop: Know Before You Push 'Go': Using the Beaker Acceptance Test Framewo...
Puppet4.6K views
Integration tests: use the containers, Luke! by Roberto Franchini
Integration tests: use the containers, Luke!Integration tests: use the containers, Luke!
Integration tests: use the containers, Luke!
Roberto Franchini1.9K views
DevOps Hackathon: Session 3 - Test Driven Infrastructure by Antons Kranga
DevOps Hackathon: Session 3 - Test Driven InfrastructureDevOps Hackathon: Session 3 - Test Driven Infrastructure
DevOps Hackathon: Session 3 - Test Driven Infrastructure
Antons Kranga1.9K views
Virtual Bolt Workshop, 5 May 2020 by Puppet
Virtual Bolt Workshop, 5 May 2020Virtual Bolt Workshop, 5 May 2020
Virtual Bolt Workshop, 5 May 2020
Puppet174 views

Similar to Testing with PostgreSQL

Continuous Integration Testing in Django by
Continuous Integration Testing in DjangoContinuous Integration Testing in Django
Continuous Integration Testing in DjangoKevin Harvey
13.6K views109 slides
Jenkins Pipelines by
Jenkins PipelinesJenkins Pipelines
Jenkins PipelinesSteffen Gebert
10.1K views46 slides
(Declarative) Jenkins Pipelines by
(Declarative) Jenkins Pipelines(Declarative) Jenkins Pipelines
(Declarative) Jenkins PipelinesSteffen Gebert
21.7K views52 slides
Agile Swift by
Agile SwiftAgile Swift
Agile SwiftGodfrey Nolan
401 views51 slides
Testing NodeJS with Mocha, Should, Sinon, and JSCoverage by
Testing NodeJS with Mocha, Should, Sinon, and JSCoverageTesting NodeJS with Mocha, Should, Sinon, and JSCoverage
Testing NodeJS with Mocha, Should, Sinon, and JSCoveragemlilley
20.5K views17 slides
Automated testing with Drupal by
Automated testing with DrupalAutomated testing with Drupal
Automated testing with DrupalPromet Source
7.4K views31 slides

Similar to Testing with PostgreSQL(20)

Continuous Integration Testing in Django by Kevin Harvey
Continuous Integration Testing in DjangoContinuous Integration Testing in Django
Continuous Integration Testing in Django
Kevin Harvey13.6K views
(Declarative) Jenkins Pipelines by Steffen Gebert
(Declarative) Jenkins Pipelines(Declarative) Jenkins Pipelines
(Declarative) Jenkins Pipelines
Steffen Gebert21.7K views
Testing NodeJS with Mocha, Should, Sinon, and JSCoverage by mlilley
Testing NodeJS with Mocha, Should, Sinon, and JSCoverageTesting NodeJS with Mocha, Should, Sinon, and JSCoverage
Testing NodeJS with Mocha, Should, Sinon, and JSCoverage
mlilley20.5K views
Automated testing with Drupal by Promet Source
Automated testing with DrupalAutomated testing with Drupal
Automated testing with Drupal
Promet Source7.4K views
Leveling Up With Unit Testing - php[tek] 2023 by Mark Niebergall
Leveling Up With Unit Testing - php[tek] 2023Leveling Up With Unit Testing - php[tek] 2023
Leveling Up With Unit Testing - php[tek] 2023
Mark Niebergall48 views
Effective testing for spark programs Strata NY 2015 by Holden Karau
Effective testing for spark programs   Strata NY 2015Effective testing for spark programs   Strata NY 2015
Effective testing for spark programs Strata NY 2015
Holden Karau13.5K views
How to integrate_custom_openstack_services_with_devstack by Sławomir Kapłoński
How to integrate_custom_openstack_services_with_devstackHow to integrate_custom_openstack_services_with_devstack
How to integrate_custom_openstack_services_with_devstack
Development Setup of B-Translator by Dashamir Hoxha
Development Setup of B-TranslatorDevelopment Setup of B-Translator
Development Setup of B-Translator
Dashamir Hoxha441 views
MySQL Utilities -- PyTexas 2015 by Dave Stokes
MySQL Utilities -- PyTexas 2015MySQL Utilities -- PyTexas 2015
MySQL Utilities -- PyTexas 2015
Dave Stokes698 views
Riga Dev Day - Automated Android Continuous Integration by Nicolas Frankel
Riga Dev Day - Automated Android Continuous IntegrationRiga Dev Day - Automated Android Continuous Integration
Riga Dev Day - Automated Android Continuous Integration
Nicolas Frankel12.7K views
Openshift cheat rhce_r3v1 rhce by Darnette A
Openshift cheat rhce_r3v1 rhceOpenshift cheat rhce_r3v1 rhce
Openshift cheat rhce_r3v1 rhce
Darnette A298 views
Power on, Powershell by Roo7break
Power on, PowershellPower on, Powershell
Power on, Powershell
Roo7break3.9K views
Agile db testing_techniques by Tarik Essawi
Agile db testing_techniquesAgile db testing_techniques
Agile db testing_techniques
Tarik Essawi803 views
Unit Testing from Setup to Deployment by Mark Niebergall
Unit Testing from Setup to DeploymentUnit Testing from Setup to Deployment
Unit Testing from Setup to Deployment
Mark Niebergall101 views
WordPress Acceptance Testing, Solved! by Taylor Lovett
WordPress Acceptance Testing, Solved!WordPress Acceptance Testing, Solved!
WordPress Acceptance Testing, Solved!
Taylor Lovett1.7K views
Make BDD great again by Yana Gusti
Make BDD great againMake BDD great again
Make BDD great again
Yana Gusti84 views

Recently uploaded

Kyo - Functional Scala 2023.pdf by
Kyo - Functional Scala 2023.pdfKyo - Functional Scala 2023.pdf
Kyo - Functional Scala 2023.pdfFlavio W. Brasil
449 views92 slides
State of the Union - Rohit Yadav - Apache CloudStack by
State of the Union - Rohit Yadav - Apache CloudStackState of the Union - Rohit Yadav - Apache CloudStack
State of the Union - Rohit Yadav - Apache CloudStackShapeBlue
253 views53 slides
Migrating VMware Infra to KVM Using CloudStack - Nicolas Vazquez - ShapeBlue by
Migrating VMware Infra to KVM Using CloudStack - Nicolas Vazquez - ShapeBlueMigrating VMware Infra to KVM Using CloudStack - Nicolas Vazquez - ShapeBlue
Migrating VMware Infra to KVM Using CloudStack - Nicolas Vazquez - ShapeBlueShapeBlue
176 views20 slides
NTGapps NTG LowCode Platform by
NTGapps NTG LowCode Platform NTGapps NTG LowCode Platform
NTGapps NTG LowCode Platform Mustafa Kuğu
365 views30 slides
The Power of Heat Decarbonisation Plans in the Built Environment by
The Power of Heat Decarbonisation Plans in the Built EnvironmentThe Power of Heat Decarbonisation Plans in the Built Environment
The Power of Heat Decarbonisation Plans in the Built EnvironmentIES VE
69 views20 slides
What’s New in CloudStack 4.19 - Abhishek Kumar - ShapeBlue by
What’s New in CloudStack 4.19 - Abhishek Kumar - ShapeBlueWhat’s New in CloudStack 4.19 - Abhishek Kumar - ShapeBlue
What’s New in CloudStack 4.19 - Abhishek Kumar - ShapeBlueShapeBlue
222 views23 slides

Recently uploaded(20)

State of the Union - Rohit Yadav - Apache CloudStack by ShapeBlue
State of the Union - Rohit Yadav - Apache CloudStackState of the Union - Rohit Yadav - Apache CloudStack
State of the Union - Rohit Yadav - Apache CloudStack
ShapeBlue253 views
Migrating VMware Infra to KVM Using CloudStack - Nicolas Vazquez - ShapeBlue by ShapeBlue
Migrating VMware Infra to KVM Using CloudStack - Nicolas Vazquez - ShapeBlueMigrating VMware Infra to KVM Using CloudStack - Nicolas Vazquez - ShapeBlue
Migrating VMware Infra to KVM Using CloudStack - Nicolas Vazquez - ShapeBlue
ShapeBlue176 views
NTGapps NTG LowCode Platform by Mustafa Kuğu
NTGapps NTG LowCode Platform NTGapps NTG LowCode Platform
NTGapps NTG LowCode Platform
Mustafa Kuğu365 views
The Power of Heat Decarbonisation Plans in the Built Environment by IES VE
The Power of Heat Decarbonisation Plans in the Built EnvironmentThe Power of Heat Decarbonisation Plans in the Built Environment
The Power of Heat Decarbonisation Plans in the Built Environment
IES VE69 views
What’s New in CloudStack 4.19 - Abhishek Kumar - ShapeBlue by ShapeBlue
What’s New in CloudStack 4.19 - Abhishek Kumar - ShapeBlueWhat’s New in CloudStack 4.19 - Abhishek Kumar - ShapeBlue
What’s New in CloudStack 4.19 - Abhishek Kumar - ShapeBlue
ShapeBlue222 views
Transitioning from VMware vCloud to Apache CloudStack: A Path to Profitabilit... by ShapeBlue
Transitioning from VMware vCloud to Apache CloudStack: A Path to Profitabilit...Transitioning from VMware vCloud to Apache CloudStack: A Path to Profitabilit...
Transitioning from VMware vCloud to Apache CloudStack: A Path to Profitabilit...
ShapeBlue117 views
Igniting Next Level Productivity with AI-Infused Data Integration Workflows by Safe Software
Igniting Next Level Productivity with AI-Infused Data Integration Workflows Igniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration Workflows
Safe Software385 views
Setting Up Your First CloudStack Environment with Beginners Challenges - MD R... by ShapeBlue
Setting Up Your First CloudStack Environment with Beginners Challenges - MD R...Setting Up Your First CloudStack Environment with Beginners Challenges - MD R...
Setting Up Your First CloudStack Environment with Beginners Challenges - MD R...
ShapeBlue132 views
GDG Cloud Southlake 28 Brad Taylor and Shawn Augenstein Old Problems in the N... by James Anderson
GDG Cloud Southlake 28 Brad Taylor and Shawn Augenstein Old Problems in the N...GDG Cloud Southlake 28 Brad Taylor and Shawn Augenstein Old Problems in the N...
GDG Cloud Southlake 28 Brad Taylor and Shawn Augenstein Old Problems in the N...
James Anderson156 views
Backup and Disaster Recovery with CloudStack and StorPool - Workshop - Venko ... by ShapeBlue
Backup and Disaster Recovery with CloudStack and StorPool - Workshop - Venko ...Backup and Disaster Recovery with CloudStack and StorPool - Workshop - Venko ...
Backup and Disaster Recovery with CloudStack and StorPool - Workshop - Venko ...
ShapeBlue144 views
Live Demo Showcase: Unveiling Dell PowerFlex’s IaaS Capabilities with Apache ... by ShapeBlue
Live Demo Showcase: Unveiling Dell PowerFlex’s IaaS Capabilities with Apache ...Live Demo Showcase: Unveiling Dell PowerFlex’s IaaS Capabilities with Apache ...
Live Demo Showcase: Unveiling Dell PowerFlex’s IaaS Capabilities with Apache ...
ShapeBlue85 views
Automating a World-Class Technology Conference; Behind the Scenes of CiscoLive by Network Automation Forum
Automating a World-Class Technology Conference; Behind the Scenes of CiscoLiveAutomating a World-Class Technology Conference; Behind the Scenes of CiscoLive
Automating a World-Class Technology Conference; Behind the Scenes of CiscoLive
"Surviving highload with Node.js", Andrii Shumada by Fwdays
"Surviving highload with Node.js", Andrii Shumada "Surviving highload with Node.js", Andrii Shumada
"Surviving highload with Node.js", Andrii Shumada
Fwdays53 views
Zero to Cloud Hero: Crafting a Private Cloud from Scratch with XCP-ng, Xen Or... by ShapeBlue
Zero to Cloud Hero: Crafting a Private Cloud from Scratch with XCP-ng, Xen Or...Zero to Cloud Hero: Crafting a Private Cloud from Scratch with XCP-ng, Xen Or...
Zero to Cloud Hero: Crafting a Private Cloud from Scratch with XCP-ng, Xen Or...
ShapeBlue158 views
KVM Security Groups Under the Hood - Wido den Hollander - Your.Online by ShapeBlue
KVM Security Groups Under the Hood - Wido den Hollander - Your.OnlineKVM Security Groups Under the Hood - Wido den Hollander - Your.Online
KVM Security Groups Under the Hood - Wido den Hollander - Your.Online
ShapeBlue181 views
VNF Integration and Support in CloudStack - Wei Zhou - ShapeBlue by ShapeBlue
VNF Integration and Support in CloudStack - Wei Zhou - ShapeBlueVNF Integration and Support in CloudStack - Wei Zhou - ShapeBlue
VNF Integration and Support in CloudStack - Wei Zhou - ShapeBlue
ShapeBlue163 views
Centralized Logging Feature in CloudStack using ELK and Grafana - Kiran Chava... by ShapeBlue
Centralized Logging Feature in CloudStack using ELK and Grafana - Kiran Chava...Centralized Logging Feature in CloudStack using ELK and Grafana - Kiran Chava...
Centralized Logging Feature in CloudStack using ELK and Grafana - Kiran Chava...
ShapeBlue101 views
Elevating Privacy and Security in CloudStack - Boris Stoyanov - ShapeBlue by ShapeBlue
Elevating Privacy and Security in CloudStack - Boris Stoyanov - ShapeBlueElevating Privacy and Security in CloudStack - Boris Stoyanov - ShapeBlue
Elevating Privacy and Security in CloudStack - Boris Stoyanov - ShapeBlue
ShapeBlue179 views

Testing with PostgreSQL

  • 2. - First heard the term Polyglot Programmer during a talk by John Anderson and found it described me - Developed in Ruby, Python, Java, Groovy, JavaScipt, C#, PHP, various SQL dialects, dabbled in Go and of course perl - I've been coding in perl since 1997 - started when I picked up AIX and needed to automate some tasks - haven't stopped automating since then Hi, I'm Shawn. • Polyglot Programmer • First love is perl • UNIX Geek • Lots of database experience • Currently on assignment with All Around the World Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 3. - described as a test runner however it doesn't execute any test code - Test::PostgreSQL allows testing with a throw away database - The 'test' here refers to not production or permanent - I have been known to spin them up for debugging from within reply What is it? • Test::PostgreSQL • PostgreSQL runner for tests • Test::PostgreSQL automatically sets up a PostgreSQL instance in a temporary directory, and destroys it when the perl script exits. • Currently maintained by Toby Corkindale Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 4. - pg_ctl is used by init scripts to initialize, start, stop, or control a PostgreSQL server - standard PostgreSQL port is 5432 - Automatically increments if the port is in use (15433) - can spawn multiple instances How does it work • Wrapper around the pg_ctl PostgreSQL controller • Assigns a port if unused starting at 15432 Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 5. Sqitch Basics Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 6. - Covered last month by Cees, can be covered in more detail in a dedicated talk - Sqitch is a tool for managing your DDL. - Sqitch is an application not a module so it can be used with any project, and for numerous databases - PostgreSQL variants like Netezza and Greenplum should also work Why? • Sqitch gives us a methodology to setup and tear down test databases that match what is is in production. • App::Sqitch • Written by David Wheeler • Works with Firebird, MySQL, Oracle, PostgreSQL, SQLite, Vertica Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 7. - Creates sqitch.conf, sqitch.plan, deploy/, revert/, verify/ - Create the first migration, creating files in the deploy/, revert/, verify/ with the migration name - A word on running with carton, I received an error message Cannot find deploy template the work around was to add template_directory = local/etc/sqitch/templates to sqitch.conf in the add section Fast Start • Initialize sqitch environment sqitch init test_postgresql --engine pg • Creating a migration sqitch add user_table -n 'Add user table.' Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 8. - Simple user table - quick note about TEXT columns, in PostgreSQL there is no performance or storage benefit from using a fixed width VARCHAR column, so just use TEXT - PostgreSQL reserved words, user is a reserved word, and will throw an error unless double quoted "user" - while database connectivity can be specified in the sqitch.conf file, personal preference is to use it on the command line. Deploying Creates file deploy/user_table.sql -- Deploy test_postgresql:user_table to pg BEGIN; CREATE TABLE "user" ( user_id SERIAL PRIMARY KEY, user_name TEXT UNIQUE, password TEXT ); COMMIT; Executed by issuing: sqitch deploy db:pg:test_db Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 9. - ROLLBACK verifications can change data, and at the end they will be undone by default. - Table creation verification is simple, and if it didn't create, there would be a SQL error during deployment. - More advanced verification for procedures and table alters Verifying Creates file verify/user_table.sql. -- Verify test_postgresql:user_table on pg BEGIN; SELECT 1/COUNT(0) FROM information_schema.tables WHERE table_name = 'user' ; ROLLBACK; Executed by issuing: sqitch verify db:pg:test_db Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 10. - When you need to remove changes - Reverting is destructive and the only way to go back is through restoring Reverting Creates file revert/user_table.sql. -- Revert test_postgresql:user_table from pg BEGIN; DROP TABLE "user"; COMMIT; Executed by issuing: sqitch revert db:pg:test_db Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 11. - Overtime changes aren't backward compatible and running sqitch verify will break. - During these times using the --verify switch during deployment tells sqitch to verify what it's deploying, not what has already been deployed. Verifying during deployment Executed by issuing: sqitch deploy --verify db:pg:test_db Verify each migration after deploying. Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 12. The Test::PostgreSQL Module Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 13. - While the name suggests test, it's really a temporary PostgreSQL database Not just for testing! Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 14. - Avoid dbicdump creating my_tmp_table_bkup - Force truth into sqitch DBIC Schema Update Utility • Helps keep sqitch deployments and DBIC schemas in sync • Ensures that developer temporary changes don't make their way into DBIC schemas Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 15. - Creates a new PostgreSQL database - Deploys sqitch database migrations to it - Runs dbicdump to create the DBIC schema packages - This code is going to become familiar dbic_update.pl use App::Sqitch; use App::Sqitch::Command::deploy; use App::Sqitch::Command::verify; use Test::PostgreSQL; my $db = Test::PostgreSQL->new; my $sqitch = App::Sqitch->new( options => { engine => 'pg', }, ); my $deploy = App::Sqitch::Command::deploy->new( sqitch => $sqitch, target => $db->uri, ); $deploy->execute(); say $db->dsn; my $dsn = $db->dsn; $dsn =~ s/^dbi/dbi/i; $dsn =~ s/dbname=/database=/i; system "dbicdump -o dump_directory=./lib MyApp::Schema '$dsn'"; Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 16. - calling sqitch from within a script/module was added in 0.996 with a patch from Chris Prather - used to error out on a Moose error Automating Sqitch for Testing Requires App::Sqitch version 0.996 Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 17. - going to create a temporary database - deploy and verify each step in turn - test that reverting each step succeeds - there's no test at the end to make sure the database is back to an empty state Test Sqitch automation • Creates a test database • Runs deploy and verify steps • Reverts changes Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 18. - There is the option of executing the command line via system, however I find this method cleaner, even though it uses more modules up front - Test modules and the App::Sqitch internals Setting up the test use Test::PostgreSQL; use Test::Most; use App::Sqitch; use App::Sqitch::Target; use App::Sqitch::Command::deploy; use App::Sqitch::Command::verify; use App::Sqitch::Command::revert; Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 19. - Calling new on Test::PostgreSQL starts the PostgreSQL instance Setting up the database my $db = Test::PostgreSQL->new; my $sqitch = App::Sqitch->new( options => { engine => 'pg', }, ); my $target = App::Sqitch::Target->new( sqitch => $sqitch); my $plan = $target->plan; Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 20. - Tell Sqitch that we want to execute using a pg engine - Sqitch classes are a hierarchy, need to build each individual object to proceed Setting up Sqitch my $db = Test::PostgreSQL->new; my $sqitch = App::Sqitch->new( options => { engine => 'pg', }, ); my $target = App::Sqitch::Target->new( sqitch => $sqitch); my $plan = $target->plan; Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 21. - Set the Sqitch target and read in the plan file Getting the Sqitch plan my $db = Test::PostgreSQL->new; my $sqitch = App::Sqitch->new( options => { engine => 'pg', }, ); my $target = App::Sqitch::Target->new( sqitch => $sqitch); my $plan = $target->plan; Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 22. - plan file contents are not necessarily in order - The $plan iterator is used to get the next step in the plan - Run a deploy on each step via deploy command - to_change will process the plan up to and including the specified change Looping through the plan while ( my $change = $plan->next ) { my $deploy = App::Sqitch::Command::deploy->new( sqitch => $sqitch, target => $db->uri, to_change => $change->name, ); lives_ok { $deploy->execute() } 'deploy sqitch plan to ' . $change->name; my $verify = App::Sqitch::Command::verify->new( sqitch => $sqitch, target => $db->uri, to_change => $change->name, ); lives_ok { $verify->execute() } 'verify sqitch plan'; push @revert, $change->name; } Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 23. - Run a verify on each step via verify command - to_change will process the verify plan up to and including the specified change Looping through the plan while ( my $change = $plan->next ) { my $deploy = App::Sqitch::Command::deploy->new( sqitch => $sqitch, target => $db->uri, to_change => $change->name, ); lives_ok { $deploy->execute() } 'deploy sqitch plan to ' . $change->name; my $verify = App::Sqitch::Command::verify->new( sqitch => $sqitch, target => $db->uri, to_change => $change->name, ); lives_ok { $verify->execute() } 'verify sqitch plan'; push @revert, $change->name; } Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 24. - Store the change to be able to revert it in reverse order later Looping through the plan while ( my $change = $plan->next ) { my $deploy = App::Sqitch::Command::deploy->new( sqitch => $sqitch, target => $db->uri, to_change => $change->name, ); lives_ok { $deploy->execute() } 'deploy sqitch plan to ' . $change->name; my $verify = App::Sqitch::Command::verify->new( sqitch => $sqitch, target => $db->uri, to_change => $change->name, ); lives_ok { $verify->execute() } 'verify sqitch plan'; push @revert, $change->name; } Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 25. - If we try to revert the last change, sqitch will complain that there's nothing further deployed. Looping through the plan pop @revert; while ( my $change_name = pop @revert ) { my $verify = App::Sqitch::Command::revert->new( sqitch => $sqitch, target => $db->uri, to_change => $change_name, no_prompt => 1, ); lives_ok { $verify->execute() } 'revert sqitch plan to ' . $change_name; } Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 26. - We've built and verified the entire database structure and now we'll tear it down - Run the revert command on each change Looping through the plan pop @revert; while ( my $change_name = pop @revert ) { my $verify = App::Sqitch::Command::revert->new( sqitch => $sqitch, target => $db->uri, to_change => $change_name, no_prompt => 1, ); lives_ok { $verify->execute() } 'revert sqitch plan to ' . $change_name; } Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 27. - highlevel of the module with methods - The skeleton provides methods to be used during your testing: db, dsn, dbh, dbic - Now step into each of the methods Test Module Skeleton package MyApp::Test::PostgreSQL; use strict; use warnings; use App::Sqitch; use Moose; use DBI; use Test::PostgreSQL; use DateTime; use MyApp::Schema; use App::Sqitch::Command::deploy; +-- 6 lines: has db => (----------------------------------------------------------------------------------------- +-- 6 lines: has dsn => (---------------------------------------------------------------------------------------- +-- 15 lines: has dbh => (---------------------------------------------------------------------------------------- +-- 9 lines: has dbic => (--------------------------------------------------------------------------------------- +-- 11 lines: has sqitch => (------------------------------------------------------------------------------------- +-- 7 lines: has fixtures => (----------------------------------------------------------------------------------- +-- 10 lines: has perm_fixtures => (------------------------------------------------------------------------------ +-- 8 lines: sub deploy {---------------------------------------------------------------------------------------- no Moose; __PACKAGE__->meta->make_immutable; 1; Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 28. - access to the Test::PostgreSQL object - not really needed during testing directly MyApp::Test::PostgreSQL::db has db => ( is => 'ro', isa => 'Test::PostgreSQL', lazy => 1, default => sub { Test::PostgreSQL->new }, ); Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 29. - returns the dsn created by Test::PostgreSQL - simple string that can be used to create additional connections - Create new DBI connections, hand over to applications MyApp::Test::PostgreSQL::dsn has dsn => ( is => 'ro', isa => 'Str', lazy => 1, default => sub { return $_[0]->db->dsn }, ); Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 30. - returns a DBI database handle connected to the Test::PostgreSQL instance. - this is a shared connection, transactions might cause issues, if in doubt start a new connection MyApp::Test::PostgreSQL::dbh has dbh => ( is => 'ro', lazy => 1, default => sub { DBI->connect( $_[0]->dsn, undef, undef, { pg_enable_utf8 => 1, RaiseError => 1, AutoCommit => 1, } ) } ); Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 31. - returns a DBIC Schema object - uses the Schema object from your application MyApp::Test::PostgreSQL::dbic has dbic => ( is => 'ro', lazy => 1, default => sub { my ($self) = @_; MyApp::Schema->connect({ dbh_maker => sub { $self->dbh }, quote_names => 1, }); } ); Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 32. - Data to add to the database for testing - Written by Curtis "Ovid" Poe - While stating that it's Alpha software, we use it a lot Fixtures • DBIx::Class::EasyFixture Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 33. - there's a lot of details here and the packages can get quite large - this example shows the necessities, real world the %definition_for hash is huge - going to break this down and explain what's going on The Fixture Package package MyApp::Test::Fixtures; use Moose; extends 'DBIx::Class::EasyFixture'; use Crypt::Bcrypt::Easy (); my %definition_for = ( basic_user => { new => 'User', using => { user_name => 'tester', password => Crypt::Bcrypt::Easy->crypt( text => 'tester', cost => 10 ) }, next => [qw(user_entry)], }, user_entry => { new => 'Entry', using => { user_id => 'basic_user', entry => 'This is my entry.', }, }, ); sub get_definition { my ( $self, $name ) = @_; return $definition_for{$name}; } sub all_fixture_names { return keys %definition_for } Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 34. - This is the data definition, but more to come We'll come back to this package MyApp::Test::Fixtures; use Moose; extends 'DBIx::Class::EasyFixture'; use Crypt::Bcrypt::Easy (); my %definition_for = ( basic_user => { new => 'User', using => { user_name => 'tester', password => Crypt::Bcrypt::Easy->crypt( text => 'tester', cost => 10 ) }, next => [qw(user_entry)], }, user_entry => { new => 'Entry', using => { user_id => 'basic_user', entry => 'This is my entry.', }, }, ); sub get_definition { my ( $self, $name ) = @_; return $definition_for{$name}; } sub all_fixture_names { return keys %definition_for } Let's ignore this section for now and return after looking at the basics. Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 35. - DBIx::Class:EasyFixture requires that get_definition and all_fixture_names be overridden. - These are the simplest definitions and can be reused Required overrides package MyApp::Fixtures; use Moose; extends 'DBIx::Class::EasyFixture'; use Crypt::Bcrypt::Easy (); my %definition_for = ( basic_user => { new => 'User', using => { user_name => 'tester', password => Crypt::Bcrypt::Easy->crypt( text => 'tester', cost => 10 ) }, next => [qw(user_entry)], }, user_entry => { new => 'Entry', using => { user_id => 'basic_user', entry => 'This is my entry.', }, }, ); sub get_definition { my ( $self, $name ) = @_; return $definition_for{$name}; } sub all_fixture_names { return keys %definition_for } Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 36. - basic_user is a unique identifier - new is the result set full package name is MyApp::Schema::Result::User - using is the record data - able to mix in function calls like password - next and requires can be used to specify fixture dependencies - STRINGREF is a reference to an existing Data definition ... my %definition_for = ( basic_user => { new => 'User', using => { user_name => 'tester', password => Crypt::Bcrypt::Easy->crypt( text => 'tester', cost => 10 ) }, next => [qw(user_entry)], }, user_entry => { new => 'Entry', using => { user_id => 'basic_user', entry => 'This is my entry.', }, }, ); ... Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 37. - Access to the fixtures object - Fixtures by default are written in one transaction MyApp::Test::PostgreSQL::fixtures has fixtures => ( is => 'ro', lazy => 1, default => sub { MyApp::Test::Fixtures->new( { schema => $_[0]->dbic } ) }, ); Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 38. - Access to the fixtures object - Disable transactions so that other sessions can access the data MyApp::Test::PostgreSQL::perm_fixtures has perm_fixtures => ( is => 'ro', lazy => 1, default => sub { MyApp::Test::Fixtures->new( { schema => $_[0]->dbic, no_transactions => 1, } ) }, ); Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 39. - At this point you have a populated database - New connections can access the database via $dsn - diag $dsn is useful for connecting with an external client - full access to the MyApp::Test::PostgreSQL methods for access to dbh, and dbic Actually writing tests use MyApp::Test::PostgreSQL; use MyApp::Test::Fixtures; use Test::Most; my $db = MyApp::Test::PostgreSQL->new; my $dbic = $db->dbic; my $dsn = $db->dsn; $dsn =~ s/^dbi/dbi/i; diag $dsn; lives_ok { $db->deploy } 'database set up'; $db->perm_fixtures->load('basic_user'); # Add all your test methods here $db->perm_fixtures->unload; done_testing; Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 40. - t/lib required as that's where the MyApp::Test modules live Running tests prove -lv -I t/lib t/simple.t t/simple.t .. # dbi:Pg:dbname=test;host=127.0.0.1;port=15432;user=postgres Adding registry tables to db:postgresql://postgres@127.0.0.1:15432/test Deploying changes to db:postgresql://postgres@127.0.0.1:15432/test + user_table ... ok + entry_table .. ok ok 1 - database set up 1..1 Pg refused to die gracefully; killing it violently. Pg really didn't die.. WTF? ok All tests successful. Files=1, Tests=1, 20 wallclock secs ( 0.03 usr 0.02 sys + 2.53 cusr 1.31 csys = 3.89 CPU) Result: PASS Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 41. - Yeah, these error messages are interesting - non-impacting, might have something to do with fixtures WTF? prove -lv -I t/lib t/simple.t t/simple.t .. # dbi:Pg:dbname=test;host=127.0.0.1;port=15432;user=postgres Adding registry tables to db:postgresql://postgres@127.0.0.1:15432/test Deploying changes to db:postgresql://postgres@127.0.0.1:15432/test + user_table ... ok + entry_table .. ok ok 1 - database set up 1..1 Pg refused to die gracefully; killing it violently. Pg really didn't die.. WTF? ok All tests successful. Files=1, Tests=1, 20 wallclock secs ( 0.03 usr 0.02 sys + 2.53 cusr 1.31 csys = 3.89 CPU) Result: PASS Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 42. - Written by Curtis "Ovid" Poe - Originally written by Curtis "Ovid" Poe, and now maintained by Dave Rolsky - Haven't used Test::mongod though it's on my list of modules to try and tests to migrate, written by co-worker Jesse Shy More Reading • DBIx::Class::EasyFixture::Tutorial - It's complicated • Test::Class::Moose - Serious testing for serious Perl • Test::mongod - run a temporary instance of MongoDB by Jesse Shy Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 43. References • Test::PostgreSQL • Reply • App::Sqitch • DBIx::Class::EasyFixture Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 44. MoreTesting with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 45. Updating DBIC Schemas #!/bin/env perl use v5.20; use autodie ':all'; use App::Sqitch; use App::Sqitch::Command::deploy; use App::Sqitch::Command::verify; use Test::PostgreSQL; my $db = Test::PostgreSQL->new; my $sqitch = App::Sqitch->new( options => { engine => 'pg', }, ); my $deploy = App::Sqitch::Command::deploy->new( sqitch => $sqitch, target => $db->uri, ); $deploy->execute(); say $db->dsn; my $dsn = $db->dsn; $dsn =~ s/^dbi/dbi/i; $dsn =~ s/dbname=/database=/i; system "dbicdump -o dump_directory=./lib MyApp::Schema '$dsn'"; Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti
  • 46. sqitch.t use Test::PostgreSQL; use Test::Most; use App::Sqitch; use App::Sqitch::Target; use App::Sqitch::Command::deploy; use App::Sqitch::Command::verify; use App::Sqitch::Command::revert; bail_on_fail; my $db = Test::PostgreSQL->new; my $sqitch = App::Sqitch->new( options => { engine => 'pg', }, ); my $target = App::Sqitch::Target->new( sqitch => $sqitch); my $plan = $target->plan; my ( @revert ); while ( my $change = $plan->next ) { my $deploy = App::Sqitch::Command::deploy->new( sqitch => $sqitch, target => $db->uri, to_change => $change->name, ); lives_ok { $deploy->execute() } 'deploy sqitch plan to ' . $change->name; my $verify = App::Sqitch::Command::verify->new( sqitch => $sqitch, target => $db->uri, to_change => $change->name, ); lives_ok { $verify->execute() } 'verify sqitch plan'; push @revert, $change->name; } pop @revert; while ( my $change_name = pop @revert ) { my $verify = App::Sqitch::Command::revert->new( sqitch => $sqitch, target => $db->uri, to_change => $change_name, no_prompt => 1, ); lives_ok { $verify->execute() } 'revert sqitch plan to ' . $change_name; } done_testing(); Testing with Postgresql // Toronto Perl Mongers // Shawn Sorichetti