Running Tests¶
RelStorage ships with an extensive test suite. It can be run from a local checkout using tox:
tox -e py27-mysql
There are environments for each database and each Python version.
Note
This may not always be in a working state; the core developers tend to work in multiple independent virtual environments rather than using tox.
You can also run tests manually (be sure to have installed
relstorage’s test dependencies; for example, pip install -e
.[test]
). Many test files contain a __main__
block that can be
used with Python’s -m
:
python -m relstorage.tests.test_zodbconvert
Running all tests can be done with zope.testrunner:
zope-testrunner --test-path=src
For each database driver installed, tests will be run. Use the
--unit
argument to only run the (small) subset of tests that do
not require access to an operational database. Use --layer
<driver>
to run tests for a particular database driver; for example,
--layer PG8000
. The -t
and -m
arguments are also useful
for filtering tests; the --repeat
argument can help find
intermittent issues.
Shell aliases make this more convenient:
alias ztest='zope-testrunner --test-path=src --auto-color --auto-progress'
alias ztestv='zope-testrunner --test-path=src --auto-color -vvv --slow-test=3'
Note
zope-testrunner is how the core developers test. It’s advanced features (layers) are required to run the complete test suite.
The --list
argument can be used to discover tests. To find the
available layers, look for Listing
:
$ ztest --list | grep Listing | sort
Listing .MySQLCMySQLConnector_Python_SharedHistoryFreeBlobTests tests:
...
Listing .Oraclecx_Oracle_SharedHistoryFreeBlobTests tests:
Listing .Oraclecx_Oracle_SharedHistoryPreservingBlobTests tests:
...
Listing .PostgreSQLgeventPsycopg2Driver_SharedHistoryFreeBlobTests tests:
...
Listing .Sqlite3sqlite3_SharedHistoryFreeBlobTests tests:
...
Databases¶
Many of RelStorage’s test require access to a database. You will have to have the appropriate database adapter (driver) installed to run these tests; tests for which you don’t have an adapter installed will be skipped.
For example, to get started testing RelStorage against MySQL in a virtual environment you could write:
pip install -e ".[test,mysql]"
from the root of the checkout. This sets up an editable installation of relstorage complete with the correct MySQL driver.
For all databases except SQLite, before actually running the tests, you need to create a test user account and several databases. Use or adapt the SQL statements below to create the databases. (You can also see example scripts that are used to set up the continuous integration test environment in the .travis directory.)
If the environment variable RS_SMALL_BLOB
is set when running
the tests, certain blob tests will use a much smaller size, making the
test run much faster.
Tip
See relstorage.tests.util
for other environment variables
RelStorage’s tests look at. RS_DB_HOST
is useful if you
want to have the database servers running on a different machine.
PostgreSQL¶
Execute the following using the psql
command:
RS_PG_UNAME=${RELSTORAGETEST_PG_UNAME:-postgres}
psql -U $RS_PG_UNAME $RELSTORAGETEST_PG_DBNAME -c "CREATE USER relstoragetest WITH PASSWORD 'relstoragetest';"
psql -U $RS_PG_UNAME $RELSTORAGETEST_PG_DBNAME -c "CREATE DATABASE relstoragetest OWNER relstoragetest;"
psql -U $RS_PG_UNAME $RELSTORAGETEST_PG_DBNAME -c "CREATE DATABASE relstoragetest2 OWNER relstoragetest;"
psql -U $RS_PG_UNAME $RELSTORAGETEST_PG_DBNAME -c "CREATE DATABASE relstoragetest_hf OWNER relstoragetest;"
psql -U $RS_PG_UNAME $RELSTORAGETEST_PG_DBNAME -c "CREATE DATABASE relstoragetest2_hf OWNER relstoragetest;"
psql -U $RS_PG_UNAME $RELSTORAGETEST_PG_DBNAME -c "SELECT version();"
Also, add the following lines to the top of pg_hba.conf (if you put them at the bottom, they may be overridden by other parameters):
local relstoragetest relstoragetest md5
local relstoragetest2 relstoragetest md5
local relstoragetest_hf relstoragetest md5
local relstoragetest2_hf relstoragetest md5
host relstoragetest relstoragetest 127.0.0.1/32 md5
host relstoragetest_hf relstoragetest 127.0.0.1/32 md5
PostgreSQL specific tests can be run with the PostgreSQL layer:
ztest --layer PostgreSQL
MySQL¶
Execute the following using the mysql
command:
#!/bin/bash
# To be able to successfully test against a MySQL on a different host,
# it's best to set up a proxy: socat tcp-listen:3306,reuseaddr,fork tcp:192.168.99.100:3306
# This can arise when running mysql in docker on macOS, which doesn't
# correctly handle the `docker run` `-p` option to forward ports to the local host;
# specify the address of the virtual machine.
# docker run --publish 3306:3306 --rm --name mysqld -e MYSQL_ALLOW_EMPTY_PASSWORD=yes mysql:8.0
HOST="-h ${RS_DB_HOST-localhost}"
DBNAME=${RELSTORAGETEST_DBNAME:-relstoragetest}
DBNAME2=${DBNAME}2
DBNAME_HF=${DBNAME}_hf
DBNAME2_HF=${DBNAME}2_hf
PW=$RELSTORAGETEST_MY_PW
echo $DBNAME_hf
echo $DBNAME2_hf
mysql -uroot $PW $HOST -e "CREATE USER 'relstoragetest' IDENTIFIED BY 'relstoragetest';"
mysql -uroot $PW $HOST -e "CREATE DATABASE $DBNAME;"
mysql -uroot $PW $HOST -e "GRANT ALL ON $DBNAME.* TO 'relstoragetest';"
mysql -uroot $PW $HOST -e "CREATE DATABASE $DBNAME2;"
mysql -uroot $PW $HOST -e "GRANT ALL ON $DBNAME2.* TO 'relstoragetest';"
mysql -uroot $PW $HOST -e "CREATE DATABASE $DBNAME_HF;"
mysql -uroot $PW $HOST -e "GRANT ALL ON $DBNAME_HF.* TO 'relstoragetest';"
mysql -uroot $PW $HOST -e "CREATE DATABASE $DBNAME2_HF;"
mysql -uroot $PW $HOST -e "GRANT ALL ON $DBNAME2_HF.* TO 'relstoragetest';"
mysql -uroot $PW $HOST -e "GRANT SELECT ON performance_schema.* TO 'relstoragetest'"
mysql -uroot $PW $HOST -e "GRANT SELECT ON sys.* TO 'relstoragetest'"
mysql -uroot $PW $HOST -e "GRANT PROCESS ON *.* TO 'relstoragetest'"
mysql -uroot $PW $HOST -e "SELECT version()"
mysql -uroot $PW $HOST -e "FLUSH PRIVILEGES;"
MySQL specific tests can be run with the MySQL layer:
ztest --layer MySQL
Note
For some MySQL tests to pass (check16MObject), it may be
necessary to increase the server’s max_allowed_packet
setting. See the MySQL Documentation
for more information.
Oracle¶
Initial setup will require SYS
privileges. Using Oracle 10g XE, you
can start a SYS
session with the following shell commands:
$ su - oracle
$ sqlplus / as sysdba
Using sqlplus
with SYS
privileges, execute the
following:
CREATE USER relstoragetest IDENTIFIED BY relstoragetest;
GRANT CONNECT, RESOURCE, CREATE TABLE, CREATE SEQUENCE, CREATE VIEW TO relstoragetest;
GRANT EXECUTE ON DBMS_LOCK TO relstoragetest;
CREATE USER relstoragetest2 IDENTIFIED BY relstoragetest;
GRANT CONNECT, RESOURCE, CREATE TABLE, CREATE SEQUENCE, CREATE VIEW TO relstoragetest2;
GRANT EXECUTE ON DBMS_LOCK TO relstoragetest2;
CREATE USER relstoragetest_hf IDENTIFIED BY relstoragetest;
GRANT CONNECT, RESOURCE, CREATE TABLE, CREATE SEQUENCE, CREATE VIEW TO relstoragetest_hf;
GRANT EXECUTE ON DBMS_LOCK TO relstoragetest_hf;
CREATE USER relstoragetest2_hf IDENTIFIED BY relstoragetest;
GRANT CONNECT, RESOURCE, CREATE TABLE, CREATE SEQUENCE, CREATE VIEW TO relstoragetest2_hf;
GRANT EXECUTE ON DBMS_LOCK TO relstoragetest2_hf;
You may need to grant tablespace privileges if you get “no privileges on tablespace” errors:
grant unlimited tablespace to relstoragetest;
grant unlimited tablespace to relstoragetest2;
grant unlimited tablespace to relstoragetest_hf;
grant unlimited tablespace to relstoragetest2_hf;
Oracle specific tests can be run with the Oracle layer:
ztest --layer Oracle
When running the tests, you can use the environment variable
ORACLE_TEST_DSN to override the data source name, which defaults to
“XE” (for Oracle 10g XE). For example, using Oracle’s Developer Days
Virtual Box VM with an IP of 192.168.1.131, you might set
ORACLE_TEST_DSN to 192.168.1.131/orcl
. (And you would connect as
sysdba with sqlplus 'sys/oracle@192.168.1.131/orcl' as sysdba
.)
If the environment variable RS_ORCL_SMALL_BLOB
is set when running
the tests, certain blob tests will use a much smaller size, making the
test run much faster.
- Docs:
- Excellent setup instructions:
Work around session limit (fixes ORA-12520):
ALTER SYSTEM SET PROCESSES=150 SCOPE=SPFILE;
ALTER SYSTEM SET SESSIONS=150 SCOPE=SPFILE;
(then restart Oracle)
Manually rollback an in-dispute transaction:
select local_tran_id, state from DBA_2PC_PENDING;
rollback force '$local_tran_id';