summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Szakmeister <john@szakmeister.net>2015-11-28 04:10:21 -0500
committerJohn Szakmeister <john@szakmeister.net>2015-11-28 04:10:21 -0500
commitad63d9a357d07c74b4cdcc4da32c7a02e03a57a6 (patch)
treed56f7fc183b31ed6657688d4e0e3e2691d2d1a39
parent7c8f005616223d4f585204535c7c5c800daaf0fb (diff)
parentc37ce12ae1d73c4ba9bcf933a08a6f1d12b081a0 (diff)
downloadnose-ad63d9a357d07c74b4cdcc4da32c7a02e03a57a6.tar.gz
Merge pull request #951 from LewisHaley/fix-test-repr-with-mutable-args
Fix test repr with mutable args
-rw-r--r--nose/case.py50
-rw-r--r--unit_tests/test_cases.py40
2 files changed, 61 insertions, 29 deletions
diff --git a/nose/case.py b/nose/case.py
index cffa4ab..c585c2b 100644
--- a/nose/case.py
+++ b/nose/case.py
@@ -199,7 +199,7 @@ class TestBase(unittest.TestCase):
def shortDescription(self):
if hasattr(self.test, 'description'):
return self.test.description
- func, arg = self._descriptors()
+ func = self._descriptor()
doc = getattr(func, '__doc__', None)
if not doc:
doc = str(self)
@@ -239,6 +239,7 @@ class FunctionTestCase(TestBase):
self.setUpFunc = setUp
self.tearDownFunc = tearDown
self.arg = arg
+ self.arg_repr = repr(self.arg)
self.descriptor = descriptor
TestBase.__init__(self)
@@ -276,32 +277,27 @@ class FunctionTestCase(TestBase):
try_run(self.test, names)
def __str__(self):
- func, arg = self._descriptors()
+ func = self._descriptor()
if hasattr(func, 'compat_func_name'):
name = func.compat_func_name
else:
name = func.__name__
name = "%s.%s" % (func.__module__, name)
- if arg:
- name = "%s%s" % (name, arg)
+ if not self.arg_repr == '()':
+ name = "%s%s" % (name, self.arg_repr)
# FIXME need to include the full dir path to disambiguate
# in cases where test module of the same name was seen in
# another directory (old fromDirectory)
return name
__repr__ = __str__
- def _descriptors(self):
- """Get the descriptors of the test function: the function and
- arguments that will be used to construct the test name. In
- most cases, this is the function itself and no arguments. For
- tests generated by generator functions, the original
- (generator) function and args passed to the generated function
- are returned.
+ def _descriptor(self):
+ """Get the descriptor of the test method.
+
+ If a `descriptor` was specified for __init__, then it is returned, else
+ the test method (callable object) is returned.
"""
- if self.descriptor:
- return self.descriptor, self.arg
- else:
- return self.test, self.arg
+ return self.descriptor if self.descriptor is not None else self.test
class MethodTestCase(TestBase):
@@ -338,6 +334,7 @@ class MethodTestCase(TestBase):
self.method = method
self.test = test
self.arg = arg
+ self.arg_repr = repr(self.arg)
self.descriptor = descriptor
if isfunction(method):
raise ValueError("Unbound methods must be wrapped using pyversion.unbound_method before passing to MethodTestCase")
@@ -349,7 +346,7 @@ class MethodTestCase(TestBase):
TestBase.__init__(self)
def __str__(self):
- func, arg = self._descriptors()
+ func = self._descriptor()
if hasattr(func, 'compat_func_name'):
name = func.compat_func_name
else:
@@ -357,8 +354,8 @@ class MethodTestCase(TestBase):
name = "%s.%s.%s" % (self.cls.__module__,
self.cls.__name__,
name)
- if arg:
- name = "%s%s" % (name, arg)
+ if not self.arg_repr == '()':
+ name = "%s%s" % (name, self.arg_repr)
return name
__repr__ = __str__
@@ -383,15 +380,10 @@ class MethodTestCase(TestBase):
def tearDown(self):
try_run(self.inst, ('teardown', 'tearDown'))
- def _descriptors(self):
- """Get the descriptors of the test method: the method and
- arguments that will be used to construct the test name. In
- most cases, this is the method itself and no arguments. For
- tests generated by generator methods, the original
- (generator) method and args passed to the generated method
- or function are returned.
+ def _descriptor(self):
+ """Get the descriptor of the test method.
+
+ If a `descriptor` was specified for __init__, then it is returned, else
+ the test method (callable object) is returned.
"""
- if self.descriptor:
- return self.descriptor, self.arg
- else:
- return self.method, self.arg
+ return self.descriptor if self.descriptor is not None else self.method
diff --git a/unit_tests/test_cases.py b/unit_tests/test_cases.py
index af399e5..fd5302d 100644
--- a/unit_tests/test_cases.py
+++ b/unit_tests/test_cases.py
@@ -115,6 +115,46 @@ class TestNoseCases(unittest.TestCase):
f(res)
assert res.errors
+ def test_FunctionTestCase_repr_is_consistent_with_mutable_args(self):
+ class Foo(object):
+ def __init__(self):
+ self.bar = 'unmodified'
+ def __repr__(self):
+ return "Foo(%s)" % self.bar
+
+ def test_foo(foo):
+ pass
+
+ foo = Foo()
+ case = nose.case.FunctionTestCase(test_foo, arg=(foo,))
+ case_repr_before = case.__repr__()
+ foo.bar = "snafu'd!"
+ case_repr_after = case.__repr__()
+ assert case_repr_before == case_repr_after, (
+ "Modifying a mutable object arg during test case changed the test "
+ "case's __repr__")
+
+ def test_MethodTestCase_repr_is_consistent_with_mutable_args(self):
+ class Foo(object):
+ def __init__(self):
+ self.bar = 'unmodified'
+ def __repr__(self):
+ return "Foo(%s)" % self.bar
+
+ class FooTester(object):
+ def test_foo(self, foo):
+ pass
+
+ foo = Foo()
+ case = nose.case.FunctionTestCase(
+ unbound_method(FooTester, FooTester.test_foo), arg=(foo,))
+ case_repr_before = case.__repr__()
+ foo.bar = "snafu'd!"
+ case_repr_after = case.__repr__()
+ assert case_repr_before == case_repr_after, (
+ "Modifying a mutable object arg during test case changed the test "
+ "case's __repr__")
+
class TestNoseTestWrapper(unittest.TestCase):
def test_case_fixtures_called(self):