summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Grönholm <alex.gronholm@nextday.fi>2014-05-30 09:44:04 +0300
committerAlex Grönholm <alex.gronholm@nextday.fi>2014-05-30 10:41:51 +0300
commit1c844df9d58674b8d79a6e440b0f470c514b8c9a (patch)
tree0d3d1244e8b067173aa37190e99dc749d3bca5f6
parentb56ba7f41b4c4f3784bc326ce2cc7ea7133ca263 (diff)
downloadapscheduler-1c844df9d58674b8d79a6e440b0f470c514b8c9a.tar.gz
Overhauled the tests for apscheduler.util module
-rw-r--r--apscheduler/util.py4
-rw-r--r--tests/test_util.py268
2 files changed, 150 insertions, 122 deletions
diff --git a/apscheduler/util.py b/apscheduler/util.py
index 0f5d2d6..ef8a9c7 100644
--- a/apscheduler/util.py
+++ b/apscheduler/util.py
@@ -11,7 +11,7 @@ import six
try:
from inspect import signature
-except ImportError:
+except ImportError: # pragma: nocover
try:
from funcsigs import signature
except ImportError:
@@ -107,7 +107,7 @@ def convert_to_datetime(input, tz, arg_name):
values = dict(values)
datetime_ = datetime(**values)
else:
- raise TypeError('Unsupported input type: %s' % type(input))
+ raise TypeError('Unsupported input type: %s' % input.__class__.__name__)
if datetime_.tzinfo is not None:
return datetime_
diff --git a/tests/test_util.py b/tests/test_util.py
index 39470c6..d5cdc0d 100644
--- a/tests/test_util.py
+++ b/tests/test_util.py
@@ -1,16 +1,16 @@
# coding: utf-8
from datetime import date, datetime, timedelta, tzinfo
from functools import partial
-import shelve
import pytest
import pytz
+import six
from apscheduler.util import (
asint, asbool, astimezone, convert_to_datetime, datetime_to_utc_timestamp, utc_timestamp_to_datetime,
timedelta_seconds, datetime_ceil, combine_opts, get_callable_name, obj_to_ref, ref_to_obj, maybe_ref,
- check_callable_args)
-from tests.conftest import minpython
+ check_callable_args, datetime_repr, repr_escape)
+from tests.conftest import minpython, maxpython
class DummyClass(object):
@@ -34,97 +34,91 @@ class DummyClass(object):
pass
-def test_asint_invalid_1():
- pytest.raises(ValueError, asint, '5s')
+class TestAsint(object):
+ @pytest.mark.parametrize('value', ['5s', 'shplse'], ids=['digit first', 'text'])
+ def test_invalid_value(self, value):
+ pytest.raises(ValueError, asint, value)
+ def test_number(self):
+ assert asint('539') == 539
-def test_asint_invalid_2():
- pytest.raises(ValueError, asint, 'shplse')
+ def test_none(self):
+ assert asint(None) is None
-def test_asint_number():
- assert asint('539') == 539
+class TestAsbool(object):
+ @pytest.mark.parametrize('value', [' True', 'true ', 'Yes', ' yes ', '1 ', True],
+ ids=['capital true', 'lowercase true', 'capital yes', 'lowercase yes', 'one', 'True'])
+ def test_true(self, value):
+ assert asbool(value) is True
+ @pytest.mark.parametrize('value', [' False', 'false ', 'No', ' no ', '0 ', False],
+ ids=['capital', 'lowercase false', 'capital no', 'lowercase no', 'zero', 'False'])
+ def test_false(self, value):
+ assert asbool(value) is False
-def test_asint_none():
- assert asint(None) is None
+ def test_bad_value(self):
+ pytest.raises(ValueError, asbool, 'yep')
-def test_asbool_true():
- for val in (' True', 'true ', 'Yes', ' yes ', '1 '):
- assert asbool(val) is True
- assert asbool(True) is True
+class TestAstimezone(object):
+ def test_str(self):
+ value = astimezone('Europe/Helsinki')
+ assert isinstance(value, tzinfo)
+ def test_tz(self):
+ tz = pytz.timezone('Europe/Helsinki')
+ value = astimezone(tz)
+ assert tz is value
-def test_asbool_false():
- for val in (' False', 'false ', 'No', ' no ', '0 '):
- assert asbool(val) is False
- assert asbool(False) is False
+ def test_none(self):
+ assert astimezone(None) is None
+ def test_bad_timezone_type(self):
+ exc = pytest.raises(TypeError, astimezone, tzinfo())
+ assert 'Only timezones from the pytz library are supported' in str(exc.value)
-def test_asbool_fail():
- pytest.raises(ValueError, asbool, 'yep')
+ def test_bad_value(self):
+ exc = pytest.raises(TypeError, astimezone, 4)
+ assert 'Expected tzinfo, got int instead' in str(exc.value)
-def test_astimezone_str():
- value = astimezone('Europe/Helsinki')
- assert isinstance(value, tzinfo)
+class TestConvertToDatetime(object):
+ @pytest.mark.parametrize('input,expected', [
+ (None, None),
+ (date(2009, 8, 1), datetime(2009, 8, 1)),
+ (datetime(2009, 8, 1, 5, 6, 12), datetime(2009, 8, 1, 5, 6, 12)),
+ ('2009-8-1', datetime(2009, 8, 1)),
+ ('2009-8-1 5:16:12', datetime(2009, 8, 1, 5, 16, 12)),
+ (pytz.FixedOffset(-60).localize(datetime(2009, 8, 1)), pytz.FixedOffset(-60).localize(datetime(2009, 8, 1)))
+ ], ids=['None', 'date', 'datetime', 'date as text', 'datetime as text', 'existing tzinfo'])
+ def test_date(self, timezone, input, expected):
+ returned = convert_to_datetime(input, timezone, None)
+ if expected is not None:
+ assert isinstance(returned, datetime)
+ expected = timezone.localize(expected) if not expected.tzinfo else expected
+ assert returned == expected
-def test_astimezone_tz():
- tz = pytz.timezone('Europe/Helsinki')
- value = astimezone(tz)
- assert tz is value
+ def test_invalid_input_type(self, timezone):
+ exc = pytest.raises(TypeError, convert_to_datetime, 92123, timezone, None)
+ assert str(exc.value) == 'Unsupported input type: int'
+ def test_invalid_input_value(self, timezone):
+ exc = pytest.raises(ValueError, convert_to_datetime, '19700-12-1', timezone, None)
+ assert str(exc.value) == 'Invalid date string'
-def test_astimezone_none():
- assert astimezone(None) is None
+ def test_missing_timezone(self):
+ exc = pytest.raises(ValueError, convert_to_datetime, '2009-8-1', None, 'argname')
+ assert str(exc.value) == 'The "tz" argument must be specified if argname has no timezone information'
+ def test_text_timezone(self):
+ returned = convert_to_datetime('2009-8-1', 'UTC', None)
+ assert returned == datetime(2009, 8, 1, tzinfo=pytz.utc)
-def test_astimezone_fail():
- pytest.raises(TypeError, astimezone, 4)
-
-
-def test_convert_datetime_date(timezone):
- dateval = date(2009, 8, 1)
- datetimeval = convert_to_datetime(dateval, timezone, None)
- assert isinstance(datetimeval, datetime)
- assert datetimeval == timezone.localize(datetime(2009, 8, 1))
-
-
-def test_convert_datetime_passthrough(timezone):
- datetimeval = datetime(2009, 8, 1, 5, 6, 12)
- convertedval = convert_to_datetime(datetimeval, timezone, None)
- assert convertedval == timezone.localize(datetimeval)
-
-
-def test_convert_datetime_text1(timezone):
- convertedval = convert_to_datetime('2009-8-1', timezone, None)
- assert convertedval == timezone.localize(datetime(2009, 8, 1))
-
-
-def test_convert_datetime_text2(timezone):
- convertedval = convert_to_datetime('2009-8-1 5:16:12', timezone, None)
- assert convertedval == timezone.localize(datetime(2009, 8, 1, 5, 16, 12))
-
-
-def test_datestring_parse_datetime_micro(timezone):
- convertedval = convert_to_datetime('2009-8-1 5:16:12.843821', timezone, None)
- assert convertedval == timezone.localize(datetime(2009, 8, 1, 5, 16, 12, 843821))
-
-
-def test_existing_tzinfo(timezone):
- alter_tz = pytz.FixedOffset(-60)
- dateval = alter_tz.localize(datetime(2009, 8, 1))
- assert convert_to_datetime(dateval, timezone, None) == dateval
-
-
-def test_convert_datetime_invalid(timezone):
- pytest.raises(TypeError, convert_to_datetime, 995302092123, timezone, None)
-
-
-def test_convert_datetime_invalid_str(timezone):
- pytest.raises(ValueError, convert_to_datetime, '19700-12-1', timezone, None)
+ def test_bad_timezone(self):
+ exc = pytest.raises(TypeError, convert_to_datetime, '2009-8-1', tzinfo(), None)
+ assert str(exc.value) == 'Only pytz timezones are supported (need the localize() and normalize() methods)'
def test_datetime_to_utc_timestamp(timezone):
@@ -140,62 +134,96 @@ def test_timedelta_seconds():
assert seconds == 150
-def test_datetime_ceil_round():
- dateval = datetime(2009, 4, 7, 2, 10, 16, 4000)
- correct_answer = datetime(2009, 4, 7, 2, 10, 17)
- assert datetime_ceil(dateval) == correct_answer
+@pytest.mark.parametrize('input,expected', [
+ (datetime(2009, 4, 7, 2, 10, 16, 4000), datetime(2009, 4, 7, 2, 10, 17)),
+ (datetime(2009, 4, 7, 2, 10, 16), datetime(2009, 4, 7, 2, 10, 16))
+], ids=['milliseconds', 'exact'])
+def test_datetime_ceil(input, expected):
+ assert datetime_ceil(input) == expected
-def test_datetime_ceil_exact():
- dateval = datetime(2009, 4, 7, 2, 10, 16)
- correct_answer = datetime(2009, 4, 7, 2, 10, 16)
- assert datetime_ceil(dateval) == correct_answer
+@pytest.mark.parametrize('input,expected', [
+ (None, 'None'),
+ (pytz.timezone('Europe/Helsinki').localize(datetime(2014, 5, 30, 7, 12, 20)), '2014-05-30 07:12:20 EEST')
+], ids=['None', 'datetime+tzinfo'])
+def test_datetime_repr(input, expected):
+ assert datetime_repr(input) == expected
def test_combine_opts():
- global_opts = {'someprefix.opt1': '123',
- 'opt2': '456',
- 'someprefix.opt3': '789'}
+ global_opts = {'someprefix.opt1': '123', 'opt2': '456', 'someprefix.opt3': '789'}
local_opts = {'opt3': 'abc'}
combined = combine_opts(global_opts, 'someprefix.', local_opts)
assert combined == dict(opt1='123', opt3='abc')
-def test_callable_name():
- assert get_callable_name(test_callable_name) == 'test_callable_name'
- assert get_callable_name(DummyClass.staticmeth) == 'staticmeth'
- assert get_callable_name(DummyClass.classmeth) == 'DummyClass.classmeth'
- assert get_callable_name(DummyClass.meth) == 'meth'
- assert get_callable_name(DummyClass().meth) == 'DummyClass.meth'
- assert get_callable_name(DummyClass) == 'DummyClass'
- assert get_callable_name(DummyClass()) == 'DummyClass'
- pytest.raises(TypeError, get_callable_name, object())
-
-
-def test_obj_to_ref():
- pytest.raises(ValueError, obj_to_ref, DummyClass.meth)
- pytest.raises(ValueError, obj_to_ref, DummyClass.staticmeth)
- pytest.raises(ValueError, obj_to_ref, partial(DummyClass.meth))
- assert obj_to_ref(DummyClass.classmeth) == 'tests.test_util:DummyClass.classmeth'
- assert obj_to_ref(shelve.open) == 'shelve:open'
-
-
-@minpython(3, 3)
-def test_inner_obj_to_ref():
- assert obj_to_ref(DummyClass.InnerDummyClass.innerclassmeth) == \
- 'tests.test_util:DummyClass.InnerDummyClass.innerclassmeth'
-
-
-def test_ref_to_obj():
- assert ref_to_obj('shelve:open') == shelve.open
- pytest.raises(TypeError, ref_to_obj, object())
- pytest.raises(ValueError, ref_to_obj, 'module')
- pytest.raises(LookupError, ref_to_obj, 'module:blah')
-
-
-def test_maybe_ref():
- assert maybe_ref('shelve:open') == shelve.open
- assert maybe_ref(shelve.open) == shelve.open
+class TestGetCallableName(object):
+ @pytest.mark.parametrize('input,expected', [
+ (asint, 'asint'),
+ (DummyClass.staticmeth, 'staticmeth'),
+ (DummyClass.classmeth, 'DummyClass.classmeth'),
+ (DummyClass.meth, 'meth'),
+ (DummyClass().meth, 'DummyClass.meth'),
+ (DummyClass, 'DummyClass'),
+ (DummyClass(), 'DummyClass')
+ ], ids=['function', 'static method', 'class method', 'unbounded method', 'bounded method', 'class', 'instance'])
+ def test_inputs(self, input, expected):
+ assert get_callable_name(input) == expected
+
+ def test_bad_input(self):
+ pytest.raises(TypeError, get_callable_name, object())
+
+
+class TestObjToRef(object):
+ @pytest.mark.parametrize('input', [DummyClass.meth, DummyClass.staticmeth, partial(DummyClass.meth)],
+ ids=['bound method', 'static method', 'partial/bound method'])
+ def test_no_ref_found(self, input):
+ exc = pytest.raises(ValueError, obj_to_ref, input)
+ assert 'Cannot determine the reference to ' in str(exc.value)
+
+ @pytest.mark.parametrize('input,expected', [
+ (DummyClass.classmeth, 'tests.test_util:DummyClass.classmeth'),
+ (timedelta, 'datetime:timedelta'),
+ ], ids=['class method', 'timedelta'])
+ def test_valid_refs(self, input, expected):
+ assert obj_to_ref(input) == expected
+
+ @minpython(3, 3)
+ def test_inner_class_method(self):
+ """Tests that a reference to a class method of an inner class can be discovered."""
+
+ assert obj_to_ref(DummyClass.InnerDummyClass.innerclassmeth) == \
+ 'tests.test_util:DummyClass.InnerDummyClass.innerclassmeth'
+
+
+class TestRefToObj(object):
+ def test_valid_ref(self):
+ assert ref_to_obj('datetime:timedelta') == timedelta
+
+ @pytest.mark.parametrize('input,error', [
+ (object(), TypeError),
+ ('module', ValueError),
+ ('module:blah', LookupError)
+ ], ids=['raw object', 'module', 'module attribute'])
+ def test_lookup_error(self, input, error):
+ pytest.raises(error, ref_to_obj, input)
+
+
+@pytest.mark.parametrize('input,expected', [
+ ('datetime:timedelta', timedelta),
+ (timedelta, timedelta)
+], ids=['textref', 'direct'])
+def test_maybe_ref(input, expected):
+ assert maybe_ref(input) == expected
+
+
+@pytest.mark.parametrize('input,expected', [
+ (b'T\xc3\xa9st'.decode('utf-8'), 'T\\xe9st' if six.PY2 else 'Tést'),
+ (1, 1)
+])
+@maxpython(3)
+def test_repr_escape_py2(input, expected):
+ assert repr_escape(input) == expected
class TestCheckCallableArgs(object):