Skip to content

Commit

Permalink
Merge pull request #1 from fizyk/fixtures
Browse files Browse the repository at this point in the history
Move fixtures and tests from pytest-dbfixtures
  • Loading branch information
fizyk committed Jun 30, 2016
2 parents 1d4dc53 + e7c6e29 commit 978f68a
Show file tree
Hide file tree
Showing 5 changed files with 258 additions and 0 deletions.
2 changes: 2 additions & 0 deletions pylama.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
linters = pep8,pyflakes,pep257
skip = docs/*,\
build/*
ignore = D203,\
D204
142 changes: 142 additions & 0 deletions src/pytest_elasticsearch/factories.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# Copyright (C) 2013-2016 by Clearcode <http://clearcode.cc>
# and associates (see AUTHORS).

# This file is part of pytest-elasticsearch.

# pytest-elasticsearch is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# pytest-elasticsearch is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.

# You should have received a copy of the GNU Lesser General Public License
# along with pytest-elasticsearch. If not, see <http://www.gnu.org/licenses/>.
"""Fixture factories."""
import shutil

import pytest
from path import path

from elasticsearch import Elasticsearch
from mirakuru import HTTPExecutor
from pytest_elasticsearch.port import get_port


def elasticsearch_proc(executable='/usr/share/elasticsearch/bin/elasticsearch',
host='127.0.0.1', port=9201, cluster_name=None,
network_publish_host='127.0.0.1',
discovery_zen_ping_multicast_enabled=False,
index_store_type='memory', logs_prefix=''):
"""
Create elasticsearch process fixture.
.. warning::
This fixture requires at least version 1.0 of elasticsearch to work.
:param str executable: elasticsearch's executable
:param str host: host that the instance listens on
:param int|str port: exact port that the instance listens on (e.g. 8000),
or randomly selected port:
'?' - any random available port
'2000-3000' - random available port from a given range
'4002,4003' - random of 4002 or 4003 ports
:param str cluster_name: name of a cluser this node should work on.
Used for autodiscovery. By default each node is in it's own cluser.
:param str network_publish_host: host to publish itself within cluser
http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-network.html
:param bool discovery_zen_ping_multicast_enabled: whether to enable or
disable host discovery
http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-discovery-zen.html
:param str index_store_type: index.store.type setting. *memory* by default
to speed up tests
:param str logs_prefix: prefix for log filename
"""
@pytest.fixture(scope='session')
def elasticsearch_proc_fixture(request):
"""Elasticsearch process starting fixture."""
elasticsearch_port = get_port(port)

pidfile = '/tmp/elasticsearch.{0}.pid'.format(elasticsearch_port)
home_path = '/tmp/elasticsearch_{0}'.format(elasticsearch_port)
logsdir = path(request.config.getvalue('logsdir'))
logs_path = logsdir / '{prefix}elasticsearch_{port}_logs'.format(
prefix=logs_prefix,
port=elasticsearch_port
)
work_path = '/tmp/elasticsearch_{0}_tmp'.format(elasticsearch_port)
cluster = cluster_name or 'dbfixtures.{0}'.format(elasticsearch_port)
multicast_enabled = str(discovery_zen_ping_multicast_enabled).lower()

command_exec = '''
{deamon} -p {pidfile} --http.port={port}
--path.home={home_path} --default.path.logs={logs_path}
--default.path.work={work_path}
--default.path.conf=/etc/elasticsearch
--cluster.name={cluster}
--network.publish_host='{network_publish_host}'
--discovery.zen.ping.multicast.enabled={multicast_enabled}
--index.store.type={index_store_type}
'''.format(
deamon=executable,
pidfile=pidfile,
port=elasticsearch_port,
home_path=home_path,
logs_path=logs_path,
work_path=work_path,
cluster=cluster,
network_publish_host=network_publish_host,
multicast_enabled=multicast_enabled,
index_store_type=index_store_type

)

elasticsearch_executor = HTTPExecutor(
command_exec, 'http://{host}:{port}'.format(
host=host,
port=elasticsearch_port
),
timeout=60,
)

elasticsearch_executor.start()

def finalize_elasticsearch():
elasticsearch_executor.stop()
shutil.rmtree(home_path)

request.addfinalizer(finalize_elasticsearch)
return elasticsearch_executor

return elasticsearch_proc_fixture


def elasticsearch(process_fixture_name):
"""
Create Elasticsearch client fixture.
:param str process_fixture_name: elasticsearch process fixture name
"""
@pytest.fixture
def elasticsearch_fixture(request):
"""Elasticsearch client fixture."""
process = request.getfuncargvalue(process_fixture_name)
if not process.running():
process.start()

hosts = '%s:%s' % (process.host, process.port)

client = Elasticsearch(hosts=hosts)

def drop_indexes():
client.indices.delete(index='*')

request.addfinalizer(drop_indexes)

return client

return elasticsearch_fixture
90 changes: 90 additions & 0 deletions src/pytest_elasticsearch/port.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Copyright (C) 2013 by Clearcode <http://clearcode.cc>
# and associates (see AUTHORS).

# This file is part of pytest-dbfixtures.

# pytest-dbfixtures is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# pytest-dbfixtures is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.

# You should have received a copy of the GNU Lesser General Public License
# along with pytest-dbfixtures. If not, see <http://www.gnu.org/licenses/>.
"""Port parsing helpers."""
import port_for


class InvalidPortsDefinition(Exception):
"""Exception raised if ports definition is not a valid string."""
def __init__(self, ports):
"""
Exception initalisation.
:param ports: passed exception value.
"""
self.ports = ports

def __str__(self):
"""String representation of a method."""
return ('Unknown format of ports: %s.\n'
'You should provide an exact port, ports range "4000-5000"'
'or a comma-separated ports list "4000,5000,6000-8000".'
% self.ports)


def get_port(ports):
"""
Return a random available port.
If there's only one port passed (e.g. 5000 or '5000') function
does not check if port is available. When a range or list
of ports is passed `port_for` external package is used in order
to find a free port.
:param int|str ports: e.g. 3000, '3000', '3000-3100', '3000,3002', '?'
:returns: a random free port
"""
try:
return int(ports)
except ValueError:
pass

return port_for.select_random(parse_ports(ports))


def parse_ports(ports):
"""
Parse ports expression.
:param str ports: e.g. '3000', '3000-3100', '3000,3002', '?'
:returns: ports set reflecting specifified ports list/range.
:rtype set
"""
if ports == '?':
return None

port_set = set()

for p in ports.split(','):
if '-' not in p:
# single, comma-separated port:
try:
port_set.add(int(p))
except ValueError:
raise InvalidPortsDefinition(ports)
else:
# range of ports:
try:
start, end = p.split('-')
except ValueError:
raise InvalidPortsDefinition(ports)
if end < start:
raise InvalidPortsDefinition(ports)
port_set.update(range(int(start), int(end) + 1))

return port_set
1 change: 1 addition & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from pytest_elasticsearch.plugin import * # noqa
23 changes: 23 additions & 0 deletions tests/test_elastic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""Pytest-elasticsearch tests."""

from pytest_elasticsearch import factories


def test_elastic_process(elasticsearch_proc):
"""Simple test for starting elasticsearch_proc."""
assert elasticsearch_proc.running() is True


def test_elasticsarch(elasticsearch):
"""Test if elasticsearch fixtures connects to process."""
info = elasticsearch.info()
assert info['status'] == 200


elasticsearch_proc_random = factories.elasticsearch_proc(port='?')
elasticsearch_random = factories.elasticsearch('elasticsearch_proc_random')


def test_random_port(elasticsearch_random):
"""Test if elasticsearch fixture can be started on random port."""
assert elasticsearch_random.info()['status'] == 200

0 comments on commit 978f68a

Please sign in to comment.