Skip to content

Commit

Permalink
Merge dca8fe1 into 1e1ff37
Browse files Browse the repository at this point in the history
  • Loading branch information
rafmagns-skepa-dreag committed Dec 16, 2020
2 parents 1e1ff37 + dca8fe1 commit f9816eb
Show file tree
Hide file tree
Showing 15 changed files with 114 additions and 20 deletions.
11 changes: 9 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
dist: xenial
dist: bionic
language: python
python:
- 3.8
- 3.7
- 3.6
- 3.9-dev
- 3.9
- nightly
- pypy3
# blocklist branches
branches:
except:
- requires-io-master
- /^dependabot.*$/
addons:
apt:
packages:
- postgresql-12
- postgresql-client-12
- postgresql-13
- postgresql-client-13
install:
- pip install -r requirements-test.txt
- pip install coveralls wheel
Expand Down
8 changes: 8 additions & 0 deletions CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,11 @@ Coding style

#. All python coding style are being enforced by `Pylama <https://pypi.python.org/pypi/pylama>`_ and configured in pylama.ini file.
#. Additional, not always mandatory checks are being performed by `QuantifiedCode <https://www.quantifiedcode.com/app/project/gh:ClearcodeHQ:pytest-postgresql>`_

Testing
-------

# Tests are writen using pytest.
# PR tests run in Travis.
# In order to run the tests locally you need to have multiple versions of postgres installed (see `tests/conftest.py <../tests/conftest.py>` for a full list).
# If you encounter any test failures due to locale issues, make sure that both `en_US.UTF-8` and `de_DE.UTF-8` are enabled in `/etc/locale.gen` and then run `sudo locale-gen`.
8 changes: 7 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -196,12 +196,18 @@ You can pick which you prefer, but remember that these settings are handled in t
- postgresql_password
- yes
-
* - Starting parameters
* - Starting parameters (extra pg_ctl arguments)
- startparams
- --postgresql-startparams
- postgresql_startparams
- -
- -w
* - Postgres exe extra arguments (passed via pg_ctl's -o argument)
- postgres_options
- --postgresql-postgres-options
- postgresql_postgres_options
- -
-
* - Log filename's prefix
- logsprefix
- --postgresql-logsprefix
Expand Down
3 changes: 3 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[pytest]
pytester_example_dir = tests/examples
norecursedirs=examples
2 changes: 1 addition & 1 deletion requirements-test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
pip>=9 # minimum installation requirements
setuptools>=21 # minimum installation requirements
coverage==5.3 # pytest-cov
pytest==6.2.0
pytest==6.2.1
pytest-cov==2.10.1
pytest-xdist==2.2.0
psycopg2-binary==2.8.6; platform_python_implementation != "PyPy"
Expand Down
12 changes: 9 additions & 3 deletions src/pytest_postgresql/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,18 @@ class PostgreSQLExecutor(TCPExecutor):
BASE_PROC_START_COMMAND = ' '.join((
"{executable} start -D {datadir}",
"-o \"-F -p {port} -c log_destination='stderr'",
"-c logging_collector=off -c %s='{unixsocketdir}'\"",
"-c logging_collector=off -c %s='{unixsocketdir}' {postgres_options}\"",
"-l {logfile} {startparams}"
))

VERSION_RE = re.compile(r'.* (?P<version>\d+\.\d+)')
MIN_SUPPORTED_VERSION = parse_version('9.0')
MIN_SUPPORTED_VERSION = parse_version('9.5')

# pylint:disable=too-many-locals
def __init__(self, executable, host, port,
datadir, unixsocketdir, logfile, startparams,
shell=False, timeout=60, sleep=0.1, user='postgres',
password='', options=''):
password='', options='', postgres_options=''):
"""
Initialize PostgreSQLExecutor executor.
Expand All @@ -80,6 +81,8 @@ def __init__(self, executable, host, port,
:param str user: [default] postgresql's username used to manage
and access PostgreSQL
:param str password: optional password for the user
:param str options:
:param str postgres_options: extra arguments to `postgres start`
"""
self._directory_initialised = False
self.executable = executable
Expand All @@ -90,13 +93,15 @@ def __init__(self, executable, host, port,
self.unixsocketdir = unixsocketdir
self.logfile = logfile
self.startparams = startparams
self.postgres_options = postgres_options
command = self.proc_start_command().format(
executable=self.executable,
datadir=self.datadir,
port=port,
unixsocketdir=self.unixsocketdir,
logfile=self.logfile,
startparams=self.startparams,
postgres_options=self.postgres_options
)
super().__init__(
command,
Expand All @@ -111,6 +116,7 @@ def __init__(self, executable, host, port,
"LANG": _LOCALE,
}
)
# pylint:enable=too-many-locals

def start(self: ExecutorType) -> ExecutorType:
"""Add check for postgresql version before starting process."""
Expand Down
6 changes: 5 additions & 1 deletion src/pytest_postgresql/executor_noop.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,14 @@ def version(self):
options=self.options
) as connection:
version = str(connection.server_version)
# Pad the version for releases before 10
# if not we get 90524 instead of 090524
if len(version) < 6:
version = '0' + version
self._version = parse_version(
'.'.join([
version[i: i+2] for i in range(0, len(version), 2)
if int(version[i: i+2])
])
][:2])
)
return self._version
6 changes: 4 additions & 2 deletions src/pytest_postgresql/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def get_config(request: FixtureRequest) -> dict:
config = {}
options = [
'exec', 'host', 'port', 'user', 'password', 'options', 'startparams',
'logsprefix', 'unixsocketdir', 'dbname', 'load'
'logsprefix', 'unixsocketdir', 'dbname', 'load', 'postgres_options',
]
for option in options:
option_name = 'postgresql_' + option
Expand Down Expand Up @@ -91,7 +91,7 @@ def postgresql_proc(
executable: str = None, host: str = None, port: Union[str, int, Iterable] = -1,
user: str = None, password: str = None,
options: str = '', startparams: str = None, unixsocketdir: str = None,
logs_prefix: str = '',
logs_prefix: str = '', postgres_options: str = None,
) -> Callable[[FixtureRequest, TempdirFactory], PostgreSQLExecutor]:
"""
Postgresql process factory.
Expand All @@ -110,6 +110,7 @@ def postgresql_proc(
:param str startparams: postgresql starting parameters
:param str unixsocketdir: directory to create postgresql's unixsockets
:param str logs_prefix: prefix for log filename
:param str postgres_options: Postgres executable options for use by pg_ctl
:rtype: func
:returns: function which makes a postgresql process
"""
Expand Down Expand Up @@ -159,6 +160,7 @@ def postgresql_proc_fixture(
unixsocketdir=unixsocketdir or config['unixsocketdir'],
logfile=logfile_path,
startparams=startparams or config['startparams'],
postgres_options=postgres_options or config['postgres_options']
)
# start server
with postgresql_executor:
Expand Down
15 changes: 14 additions & 1 deletion src/pytest_postgresql/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,15 @@
_help_unixsocketdir = "Location of the socket directory"
_help_dbname = "Default database name"
_help_load = "Load this SQL file by default, may be set multiple times"
_help_postgres_options = 'Postgres executable extra parameters. Passed via the -o option to pg_ctl'


def pytest_addoption(parser):
"""Configure options for pytest-postgresql."""
parser.addini(
name='postgresql_exec',
help=_help_executable,
default='/usr/lib/postgresql/9.1/bin/pg_ctl'
default='/usr/lib/postgresql/9.5/bin/pg_ctl'
)

parser.addini(
Expand Down Expand Up @@ -103,6 +104,11 @@ def pytest_addoption(parser):
help=_help_load,
default=None
)
parser.addini(
name='postgresql_postgres_options',
help=_help_postgres_options,
default=''
)

parser.addoption(
'--postgresql-exec',
Expand Down Expand Up @@ -182,6 +188,13 @@ def pytest_addoption(parser):
help=_help_load
)

parser.addoption(
'--postgresql-postgres-options',
action='store',
dest='postgresql_postgres_options',
help=_help_postgres_options,
)


postgresql_proc = factories.postgresql_proc()
postgresql_nooproc = factories.postgresql_noproc()
Expand Down
10 changes: 7 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@
import os
from pytest_postgresql import factories

pytest_plugins = ['pytester']

PG_CTL = '/usr/lib/postgresql/{ver}/bin/pg_ctl'
TEST_SQL_DIR = os.path.dirname(os.path.abspath(__file__)) + '/test_sql/'

# pylint:disable=invalid-name
postgresql92 = factories.postgresql_proc(PG_CTL.format(ver='9.2'), port=None)
postgresql93 = factories.postgresql_proc(PG_CTL.format(ver='9.3'), port=None)
postgresql94 = factories.postgresql_proc(PG_CTL.format(ver='9.4'), port=None)
postgresql95 = factories.postgresql_proc(PG_CTL.format(ver='9.5'), port=None)
postgresql96 = factories.postgresql_proc(PG_CTL.format(ver='9.6'), port=None)
postgresql10 = factories.postgresql_proc(PG_CTL.format(ver='10'), port=None)
postgres10 = factories.postgresql('postgresql10')
postgresql11 = factories.postgresql_proc(PG_CTL.format(ver='11'), port=None)
postgresql12 = factories.postgresql_proc(PG_CTL.format(ver='12'), port=None)
postgresql13 = factories.postgresql_proc(PG_CTL.format(ver='13'), port=None)

postgresql_proc2 = factories.postgresql_proc(port=9876)
postgresql2 = factories.postgresql('postgresql_proc2', db_name='test-db')
Expand All @@ -25,4 +26,7 @@

postgresql_rand_proc = factories.postgresql_proc(port=None)
postgresql_rand = factories.postgresql('postgresql_rand_proc')

postgresql_max_conns_proc = factories.postgresql_proc(postgres_options='-N 10')
postgres_max_conns = factories.postgresql('postgresql_max_conns_proc')
# pylint:enable=invalid-name
6 changes: 6 additions & 0 deletions tests/examples/test_postgres_options.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"""This is not called directly but is used in another test."""

def test_postgres_options(postgresql):
cur = postgresql.cursor()
cur.execute('SHOW max_connections')
assert cur.fetchone() == ('10',)
7 changes: 7 additions & 0 deletions tests/test_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,10 @@ def test_proc_with_password(
password='bogus',
host=postgres_with_password.host,
port=postgres_with_password.port)


def test_postgres_options(postgres_max_conns):
"""Check that max connections (-N 10) is honored."""
cur = postgres_max_conns.cursor()
cur.execute('SHOW max_connections')
assert cur.fetchone() == ('10',)
15 changes: 13 additions & 2 deletions tests/test_noopexecutor.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
from pytest_postgresql.factories import NoopExecutor


def test_nooproc_version(postgresql_proc):
"""Test the way postgresql version is being read."""
def test_nooproc_version_9(postgresql_proc):
"""Test the way postgresql version is being read for versions < 10."""
postgresql_nooproc = NoopExecutor(
postgresql_proc.host,
postgresql_proc.port,
Expand All @@ -14,6 +14,17 @@ def test_nooproc_version(postgresql_proc):
assert postgresql_proc.version == postgresql_nooproc.version


def test_nooproc_version_post_10(postgresql11):
"""Test the way postgresql version is being read for versions >= 10."""
postgresql_nooproc = NoopExecutor(
postgresql11.host,
postgresql11.port,
postgresql11.user,
postgresql11.options
)
assert postgresql11.version == postgresql_nooproc.version


def test_nooproc_cached_version(postgresql_proc):
"""Test that the version is being cached."""
postgresql_nooproc = NoopExecutor(
Expand Down
16 changes: 16 additions & 0 deletions tests/test_postgres_options_plugin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""Test behavior of postgres_options passed in different ways."""


def test_postgres_options_config_in_cli(pytester):
"""Check that command line arguments are honored."""
pytester.copy_example('test_postgres_options.py')
ret = pytester.runpytest('--postgresql-postgres-options', '-N 10', 'test_postgres_options.py')
ret.assert_outcomes(passed=1)


def test_postgres_options_config_in_ini(pytester):
"""Check that pytest.ini arguments are honored."""
pytester.copy_example('test_postgres_options.py')
pytester.makefile('.ini', pytest='[pytest]\npostgresql_postgres_options = -N 10\n')
ret = pytester.runpytest('test_postgres_options.py')
ret.assert_outcomes(passed=1)
9 changes: 5 additions & 4 deletions tests/test_postgresql.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@
reason='These fixtures are only for linux'
)
@pytest.mark.parametrize('postgres', (
'postgresql94',
'postgresql95',
'postgresql96',
'postgresql10',
pytest.param('postgresql11', marks=pytest.mark.xfail),
'postgresql11',
'postgresql12',
'postgresql13'
))
def test_postgresql_proc(request, postgres):
"""Test different postgresql versions."""
Expand Down Expand Up @@ -71,13 +72,13 @@ def test_rand_postgres_port(postgresql_rand):

@pytest.mark.parametrize('_', range(2))
def test_postgres_terminate_connection(
postgresql, _):
postgres10, _):
"""
Test that connections are terminated between tests.
And check that only one exists at a time.
"""
cur = postgresql.cursor()
cur = postgres10.cursor()
cur.execute(
'SELECT * FROM pg_stat_activity '
'WHERE backend_type = \'client backend\';'
Expand Down

0 comments on commit f9816eb

Please sign in to comment.