Fix #134 - wrap str, bytes, and any non-iterable input
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index ea8d4da..8196da0 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -10,6 +10,9 @@
(https://github.com/wolever/parameterized/pull/135; thanks @Ronserruya)
* Work around for bug bpo-40126 in older versions of ``mock``
(https://github.com/wolever/parameterized/pull/129; thanks @alexpizarroj)
+ * Allow str, bytes, and any non-iterable input to be passed to
+ ``@parameterized`` without wrapping in a tuple
+ (https://github.com/wolever/parameterized/pull/157)
0.8.1 (2021-01-09)
* Add README and LICENSE to pypi sdist package
diff --git a/parameterized/parameterized.py b/parameterized/parameterized.py
index b68ec21..d94be9b 100644
--- a/parameterized/parameterized.py
+++ b/parameterized/parameterized.py
@@ -2,6 +2,7 @@
import sys
import inspect
import warnings
+from typing import Iterable
from functools import wraps
from types import MethodType as MethodType
from collections import namedtuple
@@ -208,7 +209,7 @@
"""
if isinstance(args, param):
return args
- elif isinstance(args, string_types):
+ elif isinstance(args, (str, bytes)) or not isinstance(args, Iterable):
args = (args, )
try:
return cls(*args)
@@ -635,6 +636,8 @@
@classmethod
def to_safe_name(cls, s):
+ if not isinstance(s, str):
+ s = str(s)
return str(re.sub("[^a-zA-Z0-9_]+", "_", s))
diff --git a/parameterized/test.py b/parameterized/test.py
index 8f28d7a..1d012ad 100644
--- a/parameterized/test.py
+++ b/parameterized/test.py
@@ -93,15 +93,19 @@
test_params = [
(42, ),
"foo0",
+ b"bar",
+ 123,
param("foo1"),
param("foo2", bar=42),
]
expect("standalone", [
+ "test_naked_function(42, bar=None)",
"test_naked_function('foo0', bar=None)",
+ "test_naked_function(b'bar', bar=None)",
+ "test_naked_function(123, bar=None)",
"test_naked_function('foo1', bar=None)",
"test_naked_function('foo2', bar=42)",
- "test_naked_function(42, bar=None)",
])
@parameterized(test_params)
@@ -111,10 +115,12 @@
class TestParameterized(object):
expect("generator", [
+ "test_instance_method(42, bar=None)",
+ "test_instance_method(b'bar', bar=None)",
+ "test_instance_method(123, bar=None)",
"test_instance_method('foo0', bar=None)",
"test_instance_method('foo1', bar=None)",
"test_instance_method('foo2', bar=42)",
- "test_instance_method(42, bar=None)",
])
@parameterized(test_params)
@@ -149,7 +155,8 @@
def custom_naming_func(custom_tag):
def custom_naming_func(testcase_func, param_num, param):
- return testcase_func.__name__ + ('_%s_name_' % custom_tag) + str(param.args[0])
+ arg = param.args[0]
+ return testcase_func.__name__ + ('_%s_name_' % custom_tag) + parameterized.to_safe_name(arg)
return custom_naming_func
@@ -287,10 +294,12 @@
class TestParamerizedOnTestCase(TestCase):
expect([
+ "test_on_TestCase(42, bar=None)",
+ "test_on_TestCase(b'bar', bar=None)",
+ "test_on_TestCase(123, bar=None)",
"test_on_TestCase('foo0', bar=None)",
"test_on_TestCase('foo1', bar=None)",
"test_on_TestCase('foo2', bar=42)",
- "test_on_TestCase(42, bar=None)",
])
@parameterized.expand(test_params)
@@ -299,6 +308,8 @@
expect([
"test_on_TestCase2_custom_name_42(42, bar=None)",
+ "test_on_TestCase2_custom_name_b_bar_(b'bar', bar=None)",
+ "test_on_TestCase2_custom_name_123(123, bar=None)",
"test_on_TestCase2_custom_name_foo0('foo0', bar=None)",
"test_on_TestCase2_custom_name_foo1('foo1', bar=None)",
"test_on_TestCase2_custom_name_foo2('foo2', bar=42)",
@@ -311,7 +322,7 @@
frame = stack[1]
frame_locals = frame[0].f_locals
nose_test_method_name = frame_locals['a'][0]._testMethodName
- expected_name = "test_on_TestCase2_custom_name_" + str(foo)
+ expected_name = "test_on_TestCase2_custom_name_" + parameterized.to_safe_name(foo)
assert_equal(nose_test_method_name, expected_name,
"Test Method name '%s' did not get customized to expected: '%s'" %
(nose_test_method_name, expected_name))
@@ -393,14 +404,6 @@
else:
raise AssertionError("Expected exception not raised")
-def test_helpful_error_on_invalid_parameters():
- try:
- parameterized([1432141234243])(lambda: None)
- except Exception as e:
- assert_contains(str(e), "Parameters must be tuples")
- else:
- raise AssertionError("Expected exception not raised")
-
def test_helpful_error_on_empty_iterable_input():
try: