Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added logging output support to unittests #1259

Merged
merged 5 commits into from
Apr 10, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import os, sys
import param
import logging

from holoviews.element.comparison import ComparisonTestCase

try:
# Standardize backend due to random inconsistencies
Expand All @@ -9,3 +13,77 @@

cwd = os.path.abspath(os.path.split(__file__)[0])
sys.path.insert(0, os.path.join(cwd, '..'))


class MockLoggingHandler(logging.Handler):
"""
Mock logging handler to check for expected logs used by
LoggingComparisonTestCase.

Messages are available from an instance's ``messages`` dict, in
order, indexed by a lowercase log level string (e.g., 'debug',
'info', etc.)."""

def __init__(self, *args, **kwargs):
self.messages = {'DEBUG': [], 'INFO': [], 'WARNING': [],
'ERROR': [], 'CRITICAL': [], 'VERBOSE':[]}
super(MockLoggingHandler, self).__init__(*args, **kwargs)

def emit(self, record):
"Store a message to the instance's messages dictionary"
self.acquire()
try:
self.messages[record.levelname].append(record.getMessage())
finally:
self.release()

def reset(self):
self.acquire()
try:
for message_list in self.messages.values():
message_list = []
finally:
self.release()

def tail(self, level, n=1):
"Returns the last n lines captured at the given level"
return [str(el) for el in self.messages[level][-n:]]

def assertEndsWith(self, level, substring):
"""
Assert that the last line captured at the given level ends with
a particular substring.
"""
methods = {'WARNING':'param.warning()', 'INFO':'param.message()',
'VERBOSE':'param.verbose()', 'DEBUG':'param.debug()'}
msg='\n\n{method}: {last_line}\ndoes not end with:\n{substring}'
last_line = self.tail(level, n=1)
if len(last_line) == 0:
raise AssertionError('Missing {method} output: {repr(substring)}'.format(
method=methods[level], substring=repr(substring)))
if not last_line[0].endswith(substring):
raise AssertionError(msg.format(method=methods[level],
last_line=repr(last_line[0]),
substring=repr(substring)))



class LoggingComparisonTestCase(ComparisonTestCase):
"""
ComparisonTestCase with support for capturing param logging output.

Subclasses must call super setUp to make the
tests independent. Testing can then be done via the
self.log_handler.tail and self.log_handler.assertEndsWith methods.
"""

@classmethod
def setUpClass(cls):
super(LoggingComparisonTestCase, cls).setUpClass()
log = param.parameterized.get_logger()
cls.log_handler = MockLoggingHandler(level='DEBUG')
log.addHandler(cls.log_handler)

def setUp(self):
super(LoggingComparisonTestCase, self).setUp()
self.log_handler.reset()
9 changes: 7 additions & 2 deletions tests/testdimensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@
from unittest import SkipTest
from holoviews.core import Dimensioned, Dimension
from holoviews.element.comparison import ComparisonTestCase
from . import LoggingComparisonTestCase

import numpy as np
try:
import pandas as pd
except:
pd = None

class DimensionNameLabelTest(ComparisonTestCase):
class DimensionNameLabelTest(LoggingComparisonTestCase):

def setUp(self):
super(DimensionNameLabelTest, self).setUp()

def test_dimension_name(self):
dim = Dimension('test')
Expand All @@ -35,8 +39,9 @@ def test_dimension_label_kwarg(self):
self.assertEqual(dim.label, 'A test')

def test_dimension_label_kwarg_and_tuple(self):
# Should work but issue a warning
dim = Dimension(('test', 'A test'), label='Another test')
substr = "Using label as supplied by keyword ('Another test'), ignoring tuple value 'A test'"
self.log_handler.assertEndsWith('WARNING', substr)
self.assertEqual(dim.label, 'Another test')

def test_dimension_invalid_name(self):
Expand Down
2 changes: 1 addition & 1 deletion tests/testdynamic.py
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ def callback():
self.assertEqual(list(grid.keys()), [(i, j) for i in range(1, 3)
for j in range(1, 3)])
self.assertEqual(grid[(0, 1)][()], Image(np.array([[1, 1], [2, 3]])))

def test_dynamic_collate_grid_with_integer_stream_mapping(self):
def callback():
return GridSpace({(i, j): Image(np.array([[i, j], [2, 3]]))
Expand Down