Merge branch 'master' of github.com:wolever/parameterized
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 8559710..17cc2e3 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -1,5 +1,7 @@
-0.6.2 (???)
+0.6.2 (2018-03-11)
* Make sure that `setUp` and `tearDown` methods work correctly (#40)
+ * Raise a ValueError when input is empty (thanks @danielbradburn;
+ https://github.com/wolever/parameterized/pull/48)
0.6.1 (2017-03-21)
* Rename package from nose-parameterized to parameterized. A
diff --git a/parameterized/parameterized.py b/parameterized/parameterized.py
index 96de811..775a1cd 100644
--- a/parameterized/parameterized.py
+++ b/parameterized/parameterized.py
@@ -13,6 +13,12 @@
from unittest import TestCase
+try:
+ from unittest import SkipTest
+except ImportError:
+ class SkipTest(Exception):
+ pass
+
PY3 = sys.version_info[0] == 3
PY2 = sys.version_info[0] == 2
@@ -40,6 +46,8 @@
_param = namedtuple("param", "args kwargs")
+def skip_on_empty_helper(*a, **kw):
+ raise SkipTest("parameterized input is empty")
def reapply_patches_if_need(func):
@@ -57,7 +65,6 @@
func = patch_obj.decorate_callable(func)
return func
-
def delete_patches_if_need(func):
if hasattr(func, 'patchings'):
func.patchings[:] = []
@@ -305,9 +312,10 @@
assert_equal(a + b, expected)
"""
- def __init__(self, input, doc_func=None):
+ def __init__(self, input, doc_func=None, skip_on_empty=False):
self.get_input = self.input_as_callable(input)
self.doc_func = doc_func or default_doc_func
+ self.skip_on_empty = skip_on_empty
def __call__(self, test_func):
self.assert_not_in_testcase_subclass()
@@ -343,9 +351,21 @@
if test_self is not None:
delattr(test_cls, test_func.__name__)
wrapper.__doc__ = original_doc
- wrapper.parameterized_input = self.get_input()
+
+ input = self.get_input()
+ if not input:
+ if not self.skip_on_empty:
+ raise ValueError(
+ "Parameters iterable is empty (hint: use "
+ "`parameterized([], skip_on_empty=True)` to skip "
+ "this test when the input is empty)"
+ )
+ wrapper = wraps(test_func)(lambda: skip_on_empty_helper())
+
+ wrapper.parameterized_input = input
wrapper.parameterized_func = test_func
test_func.__name__ = "_parameterized_original_%s" %(test_func.__name__, )
+
return wrapper
def param_as_nose_tuple(self, test_self, func, num, p):
@@ -410,7 +430,8 @@
return [ param.from_decorator(p) for p in input_values ]
@classmethod
- def expand(cls, input, name_func=None, doc_func=None, **legacy):
+ def expand(cls, input, name_func=None, doc_func=None, skip_on_empty=False,
+ **legacy):
""" A "brute force" method of parameterizing test cases. Creates new
test cases and injects them into the namespace that the wrapped
function is being defined in. Useful for parameterizing tests in
@@ -447,6 +468,16 @@
frame_locals = frame[0].f_locals
paramters = cls.input_as_callable(input)()
+
+ if not paramters:
+ if not skip_on_empty:
+ raise ValueError(
+ "Parameters iterable is empty (hint: use "
+ "`parameterized.expand([], skip_on_empty=True)` to skip "
+ "this test when the input is empty)"
+ )
+ return wraps(f)(lambda: skip_on_empty_helper())
+
for num, p in enumerate(paramters):
name = name_func(f, num, p)
# If the original function has patches applied by 'mock.patch',
diff --git a/parameterized/test.py b/parameterized/test.py
index 2cfded3..f470127 100644
--- a/parameterized/test.py
+++ b/parameterized/test.py
@@ -3,12 +3,11 @@
import inspect
import mock
from unittest import TestCase
-from nose.tools import assert_equal
-from nose.plugins.skip import SkipTest
+from nose.tools import assert_equal, assert_raises
from .parameterized import (
PY3, PY2, parameterized, param, parameterized_argument_value_pairs,
- short_repr, detect_runner,
+ short_repr, detect_runner, SkipTest
)
def assert_contains(haystack, needle):
@@ -283,6 +282,32 @@
else:
raise AssertionError("Expected exception not raised")
+
+def test_helpful_error_on_empty_iterable_input():
+ try:
+ parameterized([])(lambda: None)
+ except ValueError as e:
+ assert_contains(str(e), "iterable is empty")
+ else:
+ raise AssertionError("Expected exception not raised")
+
+def test_skip_test_on_empty_iterable():
+ func = parameterized([], skip_on_empty=True)(lambda: None)
+ assert_raises(SkipTest, func)
+
+
+def test_helpful_error_on_empty_iterable_input_expand():
+ try:
+ class ExpectErrorOnEmptyInput(TestCase):
+ @parameterized.expand([])
+ def test_expect_error(self):
+ pass
+ except ValueError as e:
+ assert_contains(str(e), "iterable is empty")
+ else:
+ raise AssertionError("Expected exception not raised")
+
+
expect("generator", [
"test_wrapped_iterable_input('foo')",
])