Dirty SQL test system

* Added a system that allows "dirty" tests to be written. These tests
actually need to change the database, so a temporary test database must
be created to run them.
This commit is contained in:
Emmanuel BENOîT 2012-01-14 09:02:24 +01:00
parent 04e550709a
commit c18bdc2d1f
5 changed files with 114 additions and 17 deletions

View file

@ -9,8 +9,8 @@ user=tests
password=tests password=tests
EOF EOF
fi fi
TEST_DATABASE="`grep ^db= db-config.txt | sed -e s/.*=//`" export TEST_DATABASE="`grep ^db= db-config.txt | sed -e s/.*=//`"
TEST_USER="`grep ^user= db-config.txt | sed -e s/.*=//`" export TEST_USER="`grep ^user= db-config.txt | sed -e s/.*=//`"
echo echo
echo echo
@ -53,3 +53,6 @@ fi
if [ -d user ]; then if [ -d user ]; then
pg_prove -U $TEST_USER -d $TEST_DATABASE `find user/ -type f -name '*.sql'` || exit 1 pg_prove -U $TEST_USER -d $TEST_DATABASE `find user/ -type f -name '*.sql'` || exit 1
fi fi
if [ -x dirty/run-dirty-tests.sql ]; then
( cd dirty; exec ./run-dirty-tests.sql ) || exit 1
fi

View file

@ -0,0 +1,23 @@
/*
* Dirty test system self-check
*
* Insert an address, it should exist during the main test. Also create a
* function and a table which are used to synchronise execution.
*/
BEGIN;
INSERT INTO users.addresses ( address )
VALUES ( 'prepare@example.org' );
CREATE TABLE _barriers( _barrier BIGINT );
CREATE FUNCTION _synchronise_tests( _lock BIGINT )
RETURNS VOID
AS $$
BEGIN
WHILE pg_try_advisory_lock( _lock )
LOOP
PERFORM pg_advisory_unlock( _lock );
END LOOP;
END;
$$ LANGUAGE PLPGSQL;
COMMIT;

View file

@ -0,0 +1,17 @@
/*
* Dirty test system self-check
*
* Insert an address, it should exist during the main test.
*/
BEGIN;
SELECT no_plan( );
SELECT pg_advisory_lock( 1 );
SELECT diag_test_name( 'Dirty test system self-check - prepare.sql was executed' );
SELECT is( COUNT(*)::INT , 1 )
FROM users.addresses
WHERE address = 'prepare@example.org';
SELECT * FROM finish( );
ROLLBACK;

View file

@ -0,0 +1,37 @@
#!/bin/bash
if [ -z "$TEST_DATABASE" ]; then
echo "Missing TEST_DATABASE environment variable"
exit 1;
fi
echo
echo 'Running "dirty" database tests'
echo
find -mindepth 1 -maxdepth 1 -type d | sort | while read testdir; do
[ -f "$testdir/run-test.sql" ] || continue
echo "Dirty test $testdir"
echo "--------------------------------------------"
echo
echo "Creating temporary database ..."
echo "DROP DATABASE IF EXISTS dirty_tests; CREATE DATABASE dirty_tests TEMPLATE $TEST_DATABASE;" \
| psql -vQUIET=1 -vON_ERROR_STOP=1 $TEST_DATABASE || exit 1
if [ -f "$testdir/prepare.sql" ]; then
echo "Preparing database ..."
( cd .. && exec psql -vQUIET=1 -vON_ERROR_STOP=1 --file "dirty/$testdir/prepare.sql" dirty_tests ) || exit 1
fi
echo "Running main test ..."
( cd .. && pg_prove -d dirty_tests dirty/$testdir/run-test.sql ) || exit 1
echo "Dropping temporary database ..."
echo -e "DROP DATABASE IF EXISTS dirty_tests;" \
| psql -vQUIET=1 -vON_ERROR_STOP=1 $TEST_DATABASE || exit 1
echo
done

View file

@ -60,22 +60,33 @@ The tests/ sub-directory contains the SQL source code for the pgTAP testing
framework as well as the tests themselves. See below for more information. framework as well as the tests themselves. See below for more information.
Unit tests Unit tests
---------- ----------
There are three sub-directories in the tests/ directory. The admin/ directory There are four sub-directories in the tests/ directory. The admin/ directory
contains tests that require administrative permissions on the database contains tests that require administrative permissions on the database
(therefore most functionality checks can be found there), while the user/ (therefore most functionality checks can be found there), while the user/
sub-directory contains unit tests that must be executed as the standard sub-directory contains unit tests that must be executed as the standard
user (for example privileges checks). Finally, the utils/ sub-directory user (for example privileges checks).
contains scripts used by tests from the admin/ directory to create test
data. The dirty/ sub-directory contains tests which require actual changes to
be committed to the database; while unit tests are not supposed to be executed
on a loaded database anyway, these specific tests could cause problems with
other tests, and therefore run on copies of the database.
Finally, the utils/ sub-directory contains scripts used by tests from both the
admin/ and dirty/ sub-directories to create test data.
In both directories, files are organised in a manner that is parallel to the In both the admin/ and user/ directories, files are organised in a manner that
contents of the database creation scripts. For each actual SQL file, a is parallel to the contents of the database creation scripts. For each actual
sub-directory with the same name (minus the ".sql" extension) can be created, SQL file, a sub-directory with the same name (minus the ".sql" extension) can
each sub-directory containing the test suites for the definitions and be created, each sub-directory containing the test suites for the definitions
functions from the corresponding file. and functions from the corresponding file.
The dirty/ sub-directory contains a script which can be used to run the
"dirty" test suites, as well as one directory per test suite. Each test suite
directory may contain a "prepare.sql" script, to be executed before the actual
tests, as well as a "run-test.sql" which runs the actual tests.
In order to run the database unit tests, the following steps must be taken: In order to run the database unit tests, the following steps must be taken:
@ -93,14 +104,20 @@ In order to run the database unit tests, the following steps must be taken:
4) The tests/pgtap.sql script must be loaded into the database as the 4) The tests/pgtap.sql script must be loaded into the database as the
administrative user. administrative user.
At this point, it becomes possible to launch the test suites by issuing a At this point, it becomes possible to launch the basic test suites by issuing a
command similar to: command similar to:
pg_prove -d $DATABASE -U $USER \ pg_prove -d $DATABASE -U $USER \
`find $DIR/ -type f -name '*.sql' | sort` `find $DIR/ -type f -name '*.sql' | sort`
where $DATABASE is the name of the database, $USER the name of the user that where $DATABASE is the name of the database, $USER the name of the user that
will execute the tests and $DIR being either admin or user. will execute the tests and $DIR being either admin or user. The "dirty" test
suite can be launched by running:
TEST_DATABASE=$DATABASE ./run-dirty-tests.sh
Note that the dirty tests will fail unless all existing connections to the
main database are closed.
Build system Build system
@ -109,5 +126,5 @@ Build system
The build system will attempt to create the database using the scripts. It will The build system will attempt to create the database using the scripts. It will
stop at the first unsuccessful command. On success, it will proceed to loading stop at the first unsuccessful command. On success, it will proceed to loading
pgTAP, then run all available unit tests: first it will execute tests from the pgTAP, then run all available unit tests: first it will execute tests from the
admin/ sub-directory, then tests from the user/ sub-directory. A failure will admin/ sub-directory, then tests from the user/ sub-directory, and finally the
cause the build to be aborted. dirty tests. A failure will cause the build to be aborted.