Skip to content


Subversion checkout URL

You can clone with
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

executable file 458 lines (325 sloc) 12.2 KB
#!/usr/bin/perl -w
use strict;
use warnings;
use TAP::Harness;
use Getopt::Long;
our $VERSION = '0.23';
Getopt::Long::Configure (qw(bundling));
my $opts = { psql => 'psql', color => 1 };
'psql-bin|b=s' => \$opts->{psql},
'dbname|d=s' => \$opts->{dbname},
'username|U=s' => \$opts->{username},
'host|h=s' => \$opts->{host},
'port|p=s' => \$opts->{port},
'pset|P=s%' => \$opts->{pset},
'runtests|r' => \$opts->{runtests},
'schema|s=s' => \$opts->{schema},
'match|x=s' => \$opts->{match},
'timer|t' => \$opts->{timer},
'color|c!' => \$opts->{color},
'formatter|f=s' => \$opts->{formatter},
'archive|a=s' => \$opts->{archive},
'verbose|v+' => \$opts->{verbose},
'help|H' => \$opts->{help},
'man|m' => \$opts->{man},
'version|V' => \$opts->{version},
) or require Pod::Usage && Pod::Usage::pod2usage(2);
if ( $opts->{help} or $opts->{man} ) {
require Pod::Usage;
'-sections' => $opts->{man} ? '.+' : '(?i:(Usage|Options))',
'-verbose' => 99,
'-exitval' => 0,
if ($opts->{version}) {
print 'pg_prove ', main->VERSION, $/;
# --schema and --match assume --runtests.
$opts->{runtests} ||= !!($opts->{schema} || $opts->{match});
unless ($opts->{runtests} or @ARGV) {
require Pod::Usage;
'-message' => "\nOops! You didn't say what test scripts to run or specify --runtests.\n",
'-sections' => '(?i:(Usage|Options))',
'-verbose' => 99,
'-exitval' => 1,
my @command = ($opts->{psql});
for (qw(username host port dbname)) {
push @command, "--$_" => $opts->{$_} if defined $opts->{$_}
# We can't use --tuples-only because then it doesn't allow --pset to toggle it
# properly. :-(
push @command, qw(
--pset pager=
--pset tuples_only=true
if (my $pset = $opts->{pset}) {
while (my ($k, $v) = each %{ $pset }) {
push @command, '--pset', "$k=$v";
# Figure out what tests to run.
my $tests;
if ($opts->{runtests}) {
# We're just going to call `runtests()`.
push @command, '--command';
my @args;
for my $key qw(schema match) {
next unless $opts->{$key};
(my $arg = $opts->{$key}) =~ s/'/\\'/g;
# Gotta cast the arguments.
push @args, "'$arg'::" . ($key eq 'schema' ? 'name' : 'text');
# This is the command we'll run.
$tests = [[
"SELECT * FROM runtests(" . join( ', ', @args ) . ');',
'runtests(' . join(', ', @args) . ')',
} else {
# Each item in @ARGV is a file name.
$tests = \@ARGV;
push @command, '--file';
# Are we using TAP::Harness or TAP::Harness::Archive?
my $harness_class = 'TAP::Harness';
if ( $opts->{archive} ) {
require TAP::Harness::Archive;
$harness_class = 'TAP::Harness::Archive';
my $verbosity = $opts->{verbose} || $ENV{TEST_VERBOSE};
# Make it so!
my $return = $harness_class->new({
verbosity => $verbosity,
failures => !$verbosity,
( TAP::Harness->VERSION ge '3.17' ? (comments => !$verbosity) : ()),
timer => $opts->{timer},
color => $opts->{color},
formatter_class => $opts->{formatter},
($opts->{archive} ? (archive => $opts->{archive}) : ()),
exec => \@command,
})->runtests( @{ $tests } );
# Exit with non-zero status if tests failed.
exit 1 if $return->{failed};
=encoding utf8
=head1 Name
pg_prove - A command-line tool for running and harnessing pgTAP tests
=head1 Usage
pg_prove -d template1 test*.sql
pg_prove -d testdb -s testschema
=head1 Description
C<pg_prove> is a command-line application to run one or more pgTAP tests in a
PostgreSQL database. The output of the tests is harvested and processed by
L<TAP::Harness|TAP::Harness> in order to summarize the results of the test.
Tests can be written and run in one of two ways, as SQL scripts or as database
=head2 Test Scripts
pgTAP test scripts should consist of a series of SQL statements that output
TAP. Here’s a simple example that assumes that the pgTAP functions have been
installed in the database:
-- Start transaction and plan the tests.
SELECT plan(1);
-- Run the tests.
SELECT pass( 'My test passed, w00t!' );
-- Finish the tests and clean up.
SELECT * FROM finish();
Now run the tests by passing the list of SQL script names to C<pg_prove>.
Here’s what it looks like when the pgTAP tests are run with C<pg_prove>
% pg_prove -U postgres sql/*.sql
All tests successful.
Files=5, Tests=216, 1 wallclock secs ( 0.06 usr 0.02 sys + 0.08 cusr 0.07 csys = 0.23 CPU)
Result: PASS
=head2 xUnit Test Functions
pgTAP test functions should return a set of text, and then simply return the
values returned by pgTAP functions, like so:
RETURN NEXT is( MAX(nick), NULL, 'Should have no users') FROM users;
INSERT INTO users (nick) VALUES ('theory');
$$ LANGUAGE plpgsql;
SELECT is( nick, 'theory', 'Should have nick') FROM users;
$$ LANGUAGE sql;
Once you have these functions defined in your database, you can run them with
C<pg_prove> by using the C<--runtests> option.
% pg_prove -d myapp -r
All tests successful.
Files=1, Tests=32, 0 wallclock secs ( 0.02 usr 0.01 sys + 0.01 cusr 0.00 csys = 0.04 CPU)
Result: PASS
Be sure to pass the C<--schema> option if your test functions are all in one
schema, and the C<--match> option if they have names that don’t start with
“test”. For example, if you have all of your test functions in “test” schema
and I<ending> with “test,” run the tests like so:
pg_prove -d myapp --schema test --match 'test$'
=head1 Options
-b --psql-bin PSQL Location of the psql program.
-d --dbname DBNAME Database to which to connect.
-U --username USERNAME Username with which to connect.
-h --host HOST Host to which to connect.
-p --port PORT Port to which to connect.
-P --pset OPTION=VALUE Set psql printing option.
-v --verbose Display output of test scripts while running them.
-r --runtests Run xUnit test using C<runtests()>.
-s --schema Schema in which to find xUnit tests.
-x --match Regular expression to find xUnit tests.
-t --timer Print elapsed time after each test file.
-c --color Display colored test ouput.
--nocolor Do not display colored test ouput.
-f --formatter FORMATTER TAP::Formatter class to format output.
-a --archive FILENAME Store the resulting TAP in an archive file.
-H --help Print a usage statement and exit.
-m --man Print the complete documentation and exit.
-V --version Print the version number and exit.
=head1 Options Details
=item C<-b>
=item C<--psql-bin>
pg_prove --psql-bin /usr/local/pgsql/bin/psql
pg_prove -b /usr/local/bin/psql
Path to the C<psql> program, which will be used to actually run the tests.
Defaults to F<psql>.
=item C<-d>
=item C<--dbname>
pg_prove --dbname try
pg_prove -d postgres
The name of database to which to connect. Defaults to be the same as the user
=item C<-U>
=item C<--username>
pg_prove --username foo
pg_prove -U postgres
PostgreSQL user name to connect as. Defaults to be the same as the operating
system name of the user running the application.
=item C<-h>
=item C<--host>
pg_prove --host
pg_prove -h dev.local
Specifies the host name of the machine on which the server is running. If the
value begins with a slash, it is used as the directory for the Unix-domain
=item C<-p>
=item C<--port>
pg_prove --port 1234
pg_prove -p 666
Specifies the TCP port or the local Unix-domain socket file extension on which
the server is listening for connections. Defaults to the value of the
C<$PGPORT> environment variable or, if not set, to the port specified at
compile time, usually 5432.
=item C<-P>
=item C<--pset>
pg_prove --pset tuples_only=0
pg_prove -P null=[NULL]
Specifies printing options in the style of C<\pset> in the C<psql> program.
See L<> for details
on the supported options.
=item C<-v>
=item C<--verbose>
pg_prove --verbose
pg_prove -v
Display standard output of test scripts while running them. This behavior can
also be triggered by setting the C<$TEST_VERBOSE> environment variable to a
true value.
=item C<-r>
=item C<--runtests>
pg_prove --runtests
pg_prove -r
Don’t run any test scripts, but just use the C<runtests()> pgTAP function to
run xUnit tests. This ends up looking like a single test script has been run,
when in fact no test scripts have been run. Instead, C<pg_prove> tells C<psql>
to run something like:
psql --command 'SELECT * FROM runtests()'
You should use this option when you’ve written your tests in xUnit style,
where they’re all defined in test functions already loaded in the database.
=item C<-s>
=item C<--schema>
pg_prove --schema test
pg_prove -s mytest
Used with C<--runtests>, and, in fact, implicitly forces C<--runtests> to be
true. This option can be used to specify the name of a schema in which to find
xUnit functions to run. Basically, it tells C<psql> to run something like:
psql --command "SELECT * FROM runtests('test'::name)"
=item C<-x>
=item C<--match>
pg_prove --match 'test$'
pg_prove -x _test_
Used with C<--runtests>, and, in fact, implicitly forces C<--runtests> to be
true. This option can be used to specify a POSIX regular expression that will
be used to search for xUnit functions to run. Basically, it tells C<psql> to
run something like:
psql --command "SELECT * FROM runtests('_test_'::text)"
This will run any visible functions with the string “_test_” in their names.
This can be especially useful if you just want to run a single test in a
given schema. For example, this:
pg_prove --schema testing --match '^test_widgets$'
Will have C<psql> execute the C<runtests()> function like so:
SELECT * FROM runtests('testing'::name, '^test_widgets$'::text);
=item C<-t>
=item C<--timer>
pg_prove --timer
pg_prove -t
Print elapsed time after each test file.
=item C<-t>
=item C<--color>
pg_prove --color
pg_prove -c
Display test results in color. Colored test output is the default, but if
output is not to a terminal, color is disabled.
Requires L<Term::ANSIColor|Term::ANSIColor> on Unix-like platforms and
L<Win32::Console|Win32::Console> on Windows. If the necessary module is not
installed colored output will not be available.
=item C<--nocolor>
Do not display test results in color.
=item C<-f>
=item C<--formatter>
pg_prove --formatter TAP::Formatter::File
pg_prove -f TAP::Formatter::Console
The name of the class to use to format output. The default is
L<TAP::Formatter::Console|TAP::Formatter::Console>, or
L<TAP::Formatter::File|TAP::Formatter::File> if the output isn’t a TTY.
=item C<-a>
=item C<--archive>
pg_prove --archive tap.tar.gz
pg_prove -a test_output.tar
Send the TAP output to a TAP archive file as wel as to the normal output
destination. The archive formats supported are F<.tar> and F<.tar.gz>.
=item C<-H>
=item C<--help>
pg_prove --help
pg_prove -H
Outputs a brief description of the options supported by C<pg_prove> and exits.
=item C<-m>
=item C<--man>
pg_prove --man
pg_prove -m
Outputs this documentation and exits.
=item C<-V>
=item C<--version>
pg_prove --version
pg_prove -V
Outputs the program name and version and exits.
=head1 Author
David E. Wheeler <>
=head1 Copyright
Copyright (c) 2008-2009 Kineticode, Inc. Some Rights Reserved.
Jump to Line
Something went wrong with that request. Please try again.