Skip to content

Commit

Permalink
Merge pull request #16 from jcollado/use-pytest
Browse files Browse the repository at this point in the history
Use pytest
  • Loading branch information
jcollado committed Jan 19, 2017
2 parents 1ae3fa0 + daf16b5 commit 7f18fdc
Show file tree
Hide file tree
Showing 16 changed files with 545 additions and 463 deletions.
2 changes: 2 additions & 0 deletions requirements/test.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
-r common.txt
coveralls==1.1
mock==2.0.0
pytest==3.0.5
pytest-cov==2.4.0
tox==2.5.0
21 changes: 19 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-

from setuptools import setup
from setuptools.command.test import test as TestCommand

with open('README.rst') as readme_file:
readme = readme_file.read()
Expand All @@ -17,9 +18,24 @@
]

test_requirements = [
# TODO: put package test requirements here
'coveralls',
'mock',
'pytest',
'tox',
]


class PyTest(TestCommand):
def finalize_options(self):
TestCommand.finalize_options(self)
self.test_args = []
self.test_suite = True

def run_tests(self):
# import here, cause outside the eggs aren't loaded
import pytest
pytest.main(self.test_args)

setup(
name='rabbithole',
version='0.2.0',
Expand Down Expand Up @@ -54,5 +70,6 @@
'Programming Language :: Python :: 3.5',
],
test_suite='tests',
tests_require=test_requirements
tests_require=test_requirements,
cmdclass={'test': PyTest},
)
4 changes: 4 additions & 0 deletions stubs/pytest/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from . import mark

def fixture(name):
pass
2 changes: 2 additions & 0 deletions stubs/pytest/mark.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
def usefixtures(*args):
pass
3 changes: 3 additions & 0 deletions tests/cli/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-

"""CLI test cases."""
44 changes: 44 additions & 0 deletions tests/cli/test_configure_logging.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# -*- coding: utf-8 -*-

"""Logging configuration test cases."""

import logging

import pytest

from rabbithole.cli import configure_logging


@pytest.fixture
def logger():
"""Remove handlers from root logger after each test case."""
yield
root_logger = logging.getLogger()
root_logger.handlers = []


@pytest.mark.usefixtures('logger')
def test_root_level_set_to_debug():
"""Root logger level set to debug."""
configure_logging(logging.ERROR)
root_logger = logging.getLogger()
assert root_logger.level == logging.DEBUG


@pytest.mark.usefixtures('logger')
def test_stream_handler_level():
"""Stream handler level set to argument value."""
expected_value = logging.ERROR
configure_logging(expected_value)
root_logger = logging.getLogger()
assert len(root_logger.handlers) == 1
handler = root_logger.handlers[0]
assert handler.level == expected_value


@pytest.mark.usefixtures('logger')
def test_pika_level_set_warning():
"""Pika logger level is set to warning."""
configure_logging(logging.DEBUG)
pika_logger = logging.getLogger('pika')
assert pika_logger.level == logging.WARNING
51 changes: 51 additions & 0 deletions tests/cli/test_create_block_instance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# -*- coding: utf-8 -*-

"""Create block instance test cases."""

import pytest

from mock import (
MagicMock as Mock,
patch,
)

from rabbithole.cli import create_block_instance

BLOCK_NAME = '<block_name>'
BLOCK_TYPE = '<block_type>'


@pytest.fixture(name='block_class')
def fixture_block_class():
"""Patch available block classes."""
block_class = Mock()

patcher = patch.dict(
'rabbithole.cli.BLOCK_CLASSES',
{BLOCK_TYPE: block_class},
)
patcher.start()
yield block_class
patcher.stop()


def test_block_instance_created(block_class):
"""Create block instance successfully."""
create_block_instance({
'name': BLOCK_NAME,
'type': BLOCK_TYPE,
'args': [1, 2, 3],
'kwargs': {'a': 1, 'b': 2, 'c': 3}
})
block_class.assert_called_once_with(1, 2, 3, a=1, b=2, c=3)


def test_exit_on_instance_error(block_class):
"""Exit on block instantiation error."""
block_class.side_effect = Exception
with pytest.raises(SystemExit) as exc_info:
create_block_instance({
'name': BLOCK_NAME,
'type': BLOCK_TYPE,
})
assert exc_info.value.code == 1
75 changes: 75 additions & 0 deletions tests/cli/test_create_flow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# -*- coding: utf-8 -*-

"""Create flow test cases."""

import pytest

from mock import (
MagicMock as Mock,
patch,
)

from rabbithole.cli import create_flow


@pytest.fixture(name='input_block')
def fixture_input_block():
"""Create mock input block."""
return Mock()


@pytest.fixture(name='output_block')
def fixture_output_block():
"""Create mock output block."""
return Mock()


@pytest.fixture(name='kwargs')
def fixture_kwargs(input_block, output_block):
"""Create flow kwargs."""
return {
'flow': [
{'name': 'input'},
{'name': 'output'},
],
'namespace': {
'input': input_block,
'output': output_block,
},
'batcher_config': {},
}


def test_signals_connected(input_block, output_block, kwargs):
"""Signals are connected as expected."""
input_signal = input_block()
output_cb = output_block()

with patch('rabbithole.cli.Batcher') as batcher_cls:
create_flow(**kwargs)

input_signal.connect.assert_called_once_with(
batcher_cls().message_received_cb,
weak=False,
)
batcher_signal = batcher_cls().batch_ready
batcher_signal.connect.assert_called_once_with(
output_cb,
weak=False,
)


def test_exit_on_input_signal_error(input_block, kwargs):
"""Exit on error trying to get the input signal."""
input_block.side_effect = Exception()
with pytest.raises(SystemExit) as exc_info:
create_flow(**kwargs)
assert exc_info.value.code == 1


def test_exit_on_output_cb_error(output_block, kwargs):
"""Exit on error trying to get the output callback."""
output_block.side_effect = Exception()
with pytest.raises(SystemExit) as exc_info:
create_flow(**kwargs)
assert exc_info.value.code == 1
27 changes: 27 additions & 0 deletions tests/cli/test_main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-

"""Main entry point test cases."""

from mock import patch

from rabbithole.cli import main


def test_exit_on_keyboard_interrupt():
"""Exit when user hits Ctrl+C."""
with patch('rabbithole.cli.parse_arguments') as parse_arguments_, \
patch('rabbithole.cli.configure_logging'), \
patch('rabbithole.cli.create_block_instance'), \
patch('rabbithole.cli.create_flow'), \
patch('rabbithole.cli.run_input_blocks'), \
patch('rabbithole.cli.time') as time:
parse_arguments_().config = {
'blocks': [
{'name': '<block#1>'},
{'name': '<block#2>'},
],
'flows': ['<flow#1>', '<flow#2>'],
}
time.sleep.side_effect = KeyboardInterrupt
return_code = main()
assert return_code == 0
42 changes: 42 additions & 0 deletions tests/cli/test_parse_arguments.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-

"""Argument parsing test cases."""

import pytest
import yaml

from mock import patch
from six import StringIO

from rabbithole.cli import parse_arguments


def test_config_file_does_not_exist():
"""SystemExit is raised if the configuration file does not exist."""
# Do not include error output in test output
with pytest.raises(SystemExit), patch('rabbithole.cli.sys.stderr'):
parse_arguments(['file-does-not-exist'])


def test_config_file_invalid():
"""SystemExit is raised if the configuration file is invalid."""
with pytest.raises(SystemExit), \
patch('rabbithole.cli.sys.stderr'), \
patch('rabbithole.cli.os') as os_, \
patch('rabbithole.cli.open') as open_:
os_.path.isfile.return_value = True
open_().__enter__.return_value = StringIO('>invalid yaml<')
parse_arguments(['some file'])


def test_config_file_load_success():
"""Config file successfully loaded."""
expected_value = {'a': 'value'}
with patch('rabbithole.cli.os') as os_, \
patch('rabbithole.cli.open') as open_:
os_.path.isfile.return_value = True
open_().__enter__.return_value = (
StringIO(yaml.dump(expected_value)))
args = parse_arguments(['some file'])

assert args['config'] == expected_value
19 changes: 19 additions & 0 deletions tests/cli/test_run_input_blocks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-

"""Run input blocks test cases."""

from mock import MagicMock as Mock

from rabbithole.cli import run_input_blocks


def test_run_method_called():
"""Run method is called."""
block_instance = Mock()
namespace = {
'<name>': block_instance,
}
threads = run_input_blocks(namespace)
for thread in threads:
thread.join()
block_instance.run.assert_called_once_with()

0 comments on commit 7f18fdc

Please sign in to comment.