Skip to content

Commit

Permalink
* Added do_tap(), which finds test functions and runs them, allowi…
Browse files Browse the repository at this point in the history
…ng tap tests to be embedded in functions and then executed all at once.

 * Added `runtests()`, which introduces xUnit-style test running, for those who prefer to put their tests in a slew of test functions and then run one function to run all of the test functions (plus startup, setup, teardown, and shutdown tests).
 * Added `findfuncs()`, which is used by `do_tap()` to find the functions to execute.
 * The `col_type_is()` function now requires that the type be visible in the search path when it is called without a schema argument.
 * The `plan()` function no longer resets the `client_min_messages` setting to its default value, but leaves it set to whatever it was set to before the function was called.
 * Fixed a typo in the documentation of the short version of the `--version` option to `pg_prove`, which is `-V`, not `-v`.
  • Loading branch information
theory committed Jan 18, 2009
1 parent 0149587 commit a46ff14
Show file tree
Hide file tree
Showing 11 changed files with 576 additions and 20 deletions.
15 changes: 15 additions & 0 deletions Changes
Expand Up @@ -3,6 +3,21 @@ Revision history for pgTAP
0.15
- Changed `pg_typeof()` from immutable to stable, in compliance with its
configuration in the forthcoming PostgreSQL 8.4.
- Added `do_tap()`, which finds test functions and runs them, allowing
tap tests to be embedded in functions and then executed all at once.
- Added `runtests()`, which introduces xUnit-style test running, for
those who prefer to put their tests in a slew of test functions and
then run one function to run all of the test functions (plus startup,
setup, teardown, and shutdown tests).
- Added `findfuncs()`, which is used by `do_tap()` to find the functions
to execute.
- The `col_type_is()` function now requires that the type be visible in
the search path when it is called without a schema argument.
- The `plan()` function no longer resets the `client_min_messages`
setting to its default value, but leaves it set to whatever it was set
to before the function was called.
- Fixed a typo in the documentation of the short version of the
`--version` option to `pg_prove`, which is `-V`, not `-v`.

0.14 2008-10-27T22:43:36
- Added `SET search_path` statements to `uninstall_pgtap.sql.in` so that
Expand Down
117 changes: 113 additions & 4 deletions README.pgtap
Expand Up @@ -699,10 +699,10 @@ This function tests that the specified column is of a particular type. If it
fails, it will emit diagnostics naming the actual type. The first argument is
the schema name, the second the table name, the third the column name, the
fourth the type, and the fifth is the test description. If the schema is
omitted, the table must be visible in the search path. If the test description
is omitted, it will be set to "Column `:table`.`:column` should be type
`:type`". Note that this test will fail if the table or column in question
does not exist.
omitted, the table and the type must be visible in the search path. If the
test description is omitted, it will be set to "Column `:table`.`:column`
should be type `:type`". Note that this test will fail if the table or column
in question does not exist.

The type argument should be formatted as it would be displayed in the view of
a table using the `\d` command in `psql`. For example, if you have a numeric
Expand Down Expand Up @@ -1647,6 +1647,98 @@ it gets the job done. Of course, if your diagnostics use something other than
indented "have" and "want", such failures will be easier to read. But either
way, do test your diagnostics!

Tap that Batch
--------------

Sometimes it can be useful to batch a lot of TAP tests into a function. The
simplest way to do so is to define a function that `RETURNS SETOF TEXT` and
then simply call `RETURN NEXT` for each TAP test. Here's a simple example:

CREATE OR REPLACE FUNCTION my_tests(
) RETURNS SETOF TEXT AS $$
BEGIN
RETURN NEXT pass( 'plpgsql simple' );
RETURN NEXT pass( 'plpgsql simple 2' );
END;
$$ LANGUAGE plpgsql;

Then you can just call the function to run all of your TAP tests at once:

SELECT plan(2);
SELECT * FROM my_tests();
SELECT * FROM finish();

### `do_tap( schema, pattern )` ###
### `do_tap( schema )` ###
### `do_tap( pattern )` ###
### `do_tap()` ###

SELECT plan(32);
SELECT * FROM do_tap('testschema');
SELECT * FROM finish();

If you like you can create a whole slew of these batched tap functions, and
then use the `do_tap()` function to run them all at once. If passed no
arguments, it will attempt to find all visible functions that start with
"test". If passed a schema name, it will look for and run test functions only
in that schema (be sure to cast the schema to `name` if it is the only
argument). If passed a regular expression pattern, it will look for function
names that match that pattern in the search path. If passed both, it will of
course only search for test functions that match the function in the named
schema.

This can be very useful if you prefer to keep all of your TAP tests in
functions defined in the database. Simply call `plan()`, use `do_tap()` to
execute all of your tests, and then call `finish()`.

As a bonus, if `client_min_messages` is set to "warning", "error", "fatal", or
"panic", the name of each function will be emitted as a diagnostic message
before it is called. For example, if `do_tap()` found and executed two TAP
testing functions an `client_min_messages` is set to "warning", output will
look something like this:

# public.test_this()
ok 1 - simple pass
ok 2 - another simple pass
# public.test_that()
ok 3 - that simple
ok 4 - that simple 2

Which will make it much easier to tell what functions need to be examined for
failing tests.

### `runtests( schema, match )` ###
### `runtests( schema )` ###
### `runtests( match )` ###
### `runtests( )` ###

SELECT * FROM runtests('testschema');

If you'd like pgTAP to plan, run all of your tests functions, and finish all
in one fell swoop, use `runtests()`. This most closely emulates the xUnit
testing environment, similar to the functionality of
[PGUnit](http://en.dklab.ru/lib/dklab_pgunit/) and
[Epic](http://www.epictest.org/).

As with `do_tap()`, you can pass in a schema argument and/or a pattern that
the names of the tests functions can match. But unlike `do_tap()`,
`runtests()` fully supports startup, shutdown, setup, and teardown functions,
as well as transactional rollbacks between tests. It also outputs the test
plan and fishes the tests, so you don't have to call `plan()` or `finish()`
yourself.

The fixture functions run by `runtests()` are as follows:

* `^startup` - Functions whose names start with "startup" are run in
alphabetical order before any test functions are run.
* `^setup` - Functions whose names start with "setup" are run in alphabetical
order before each test function is run.
* `^teardown` - Functions whose names start with "teardown" are run in
alphabetical order after each test function is run. They will not be run,
however, after a test that has died.
* `^shutdown` - Functions whose names start with "shutdown" are run in
alphabetical order after all test functions have been run.

Utility Functions
=================

Expand Down Expand Up @@ -1722,6 +1814,22 @@ executing the comparison, but might be generally useful.
-----------+-----------
integer | numeric

### `findfuncs( schema, pattern )` ###
### `findfuncs( pattern )` ###

SELECT findfuncs('myschema', '^test' );

This function searches the named schema or, if no schema is passed, the search
patch, for all functions that match the regular expression pattern. The
functions it finds are returned as an array of text values, with each value
consisting of the schema name, a dot, and the function name. For example:

SELECT findfuncs('tests', '^test);
findfuncs
-----------------------------------
{tests.test_foo,tests."test bar"}
(1 row)

Compatibility
=============

Expand Down Expand Up @@ -1772,6 +1880,7 @@ and `lives_ok()` functions do not work under 8.0. Don't even use them there.
To Do
-----

* Add a `pgtap_version()` function.
* Update build for 8.4, where `pg_typeof()` is already included.
* Add xUnit-style support by adding a function to run test functions that emit
TAP. The function should support startup and shutdown and setup and teardown
Expand Down
9 changes: 6 additions & 3 deletions bin/pg_prove
Expand Up @@ -115,7 +115,7 @@ The test scripts should be a series of SQL statements
-v --verbose Display output of test scripts while running them.
-h --help Print a usage statement and exit.
-m --man Print the complete documentation and exit.
-v --version Print the version number and exit.
-V --version Print the version number and exit.
-P --pset OPTION=VALUE Set psql printing option.
=head1 Options Details
Expand Down Expand Up @@ -190,6 +190,9 @@ on the supported options.
=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.
Expand Down Expand Up @@ -239,12 +242,12 @@ Outputs a brief description of the options supported by C<pg_prove> and exits.
Outputs this documentation and exits.
=item C<-v>
=item C<-V>
=item C<--version>
pg_prove --version
pg_prove -v
pg_prove -V
Outputs the program name and version and exits.
Expand Down
40 changes: 40 additions & 0 deletions expected/do_tap.out
@@ -0,0 +1,40 @@
\unset ECHO
1..26
ok 1 - findfuncs(public, ^test) should work
ok 2 - findfuncs(^test) should work
# public."test ident"()
ok 3 - ident
ok 4 - ident 2
# public.test_this()
ok 5 - simple pass
ok 6 - another simple pass
# public.testplpgsql()
ok 7 - plpgsql simple
ok 8 - plpgsql simple 2
# public."test ident"()
ok 9 - ident
ok 10 - ident 2
# public.test_this()
ok 11 - simple pass
ok 12 - another simple pass
# public.testplpgsql()
ok 13 - plpgsql simple
ok 14 - plpgsql simple 2
# public."test ident"()
ok 15 - ident
ok 16 - ident 2
# public.test_this()
ok 17 - simple pass
ok 18 - another simple pass
# public.testplpgsql()
ok 19 - plpgsql simple
ok 20 - plpgsql simple 2
# public."test ident"()
ok 21 - ident
ok 22 - ident 2
# public.test_this()
ok 23 - simple pass
ok 24 - another simple pass
# public.testplpgsql()
ok 25 - plpgsql simple
ok 26 - plpgsql simple 2
38 changes: 38 additions & 0 deletions expected/runtests.out
@@ -0,0 +1,38 @@
\unset ECHO
ok 1 - starting up
ok 2 - starting up some more
# whatever."test ident"()
ok 3 - setup
ok 4 - Should be nothing in the test table
ok 5 - setup more
ok 6 - ident
ok 7 - ident 2
ok 8 - teardown
ok 9 - teardown more
# whatever.test_this()
ok 10 - setup
ok 11 - Should be nothing in the test table
ok 12 - setup more
ok 13 - simple pass
ok 14 - another simple pass
ok 15 - teardown
ok 16 - teardown more
# whatever.testplpgsql()
ok 17 - setup
ok 18 - Should be nothing in the test table
ok 19 - setup more
ok 20 - plpgsql simple
ok 21 - plpgsql simple 2
ok 22 - Should be a 1 in the test table
ok 23 - teardown
ok 24 - teardown more
# whatever.testz()
ok 25 - setup
ok 26 - Should be nothing in the test table
ok 27 - setup more
ok 28 - Late test should find nothing in the test table
ok 29 - teardown
ok 30 - teardown more
ok 31 - shutting down
ok 32 - shutting down more
1..32
3 changes: 2 additions & 1 deletion expected/util.out
@@ -1,5 +1,5 @@
\unset ECHO
1..10
1..11
ok 1 - pg_type(int) should work
ok 2 - pg_type(numeric) should work
ok 3 - pg_type(text) should work
Expand All @@ -10,3 +10,4 @@ ok 7 - pg_version() should return same as "sever_version" setting
ok 8 - pg_version_num() should return integer
ok 9 - pg_version_num() should be correct
ok 10 - os_name() should output something like an OS name
ok 11 - findfincs() should return distinct values

0 comments on commit a46ff14

Please sign in to comment.