summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJP <jpellerin@gmail.com>2011-12-21 10:46:45 -0800
committerJP <jpellerin@gmail.com>2011-12-21 10:46:45 -0800
commit214cacd6321a9396c0722304887cfb7620e09863 (patch)
tree059519261f2bfd9213bf01e3f9c72707904159c6
parentaea6f557a416ec2e96262f6f058933883031ac23 (diff)
parent28db0e5f14ece94865b59e4aeda3dea71afd9435 (diff)
downloadnose-214cacd6321a9396c0722304887cfb7620e09863.tar.gz
Merge pull request #479 from erikrose/unittest-global
Define __unittest in scope of nose's assertion helpers to hide noisy stack frames. Closes #453.
-rw-r--r--AUTHORS1
-rw-r--r--CHANGELOG3
-rw-r--r--nose/tools/__init__.py11
-rw-r--r--nose/tools/nontrivial.py (renamed from nose/tools.py)52
-rw-r--r--nose/tools/trivial.py52
-rw-r--r--unit_tests/test_tools.py50
6 files changed, 104 insertions, 65 deletions
diff --git a/AUTHORS b/AUTHORS
index c647a2b..b852772 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -22,3 +22,4 @@ Takafumi Arakaki
Peter Bengtsson
Gary Donovan
Brendan McCollam
+Erik Rose
diff --git a/CHANGELOG b/CHANGELOG
index 8f6233b..0bab124 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -10,6 +10,9 @@
Patch by Timothée Peignier.
- Fixed Unicode issue on Python 3.1 with coverage (#442)
- fixed class level fixture handling in multiprocessing plugin
+- Clue in the ``unittest`` module so it no longer prints traceback frames for
+ our clones of their simple assertion helpers. (#453).
+ Patch by Erik Rose.
1.1.2
diff --git a/nose/tools/__init__.py b/nose/tools/__init__.py
new file mode 100644
index 0000000..ba32301
--- /dev/null
+++ b/nose/tools/__init__.py
@@ -0,0 +1,11 @@
+"""
+Tools for testing
+-----------------
+
+nose.tools provides a few convenience functions to make writing tests
+easier. You don't have to use them; nothing in the rest of nose depends
+on any of these methods.
+
+"""
+from nose.tools.nontrivial import *
+from nose.tools.trivial import *
diff --git a/nose/tools.py b/nose/tools/nontrivial.py
index 2fb3e75..e47ac62 100644
--- a/nose/tools.py
+++ b/nose/tools/nontrivial.py
@@ -1,36 +1,16 @@
-"""
-Tools for testing
------------------
-
-nose.tools provides a few convenience functions to make writing tests
-easier. You don't have to use them; nothing in the rest of nose depends
-on any of these methods.
-"""
-import re
+"""Tools not exempt from being descended into in tracebacks"""
+
import time
-import unittest
-__all__ = ['ok_', 'eq_', 'make_decorator', 'raises', 'set_trace', 'timed',
- 'with_setup', 'TimeExpired', 'istest', 'nottest']
+__all__ = ['make_decorator', 'raises', 'set_trace', 'timed', 'with_setup',
+ 'TimeExpired', 'istest', 'nottest']
class TimeExpired(AssertionError):
pass
-def ok_(expr, msg=None):
- """Shorthand for assert. Saves 3 whole characters!
- """
- assert expr, msg
-
-
-def eq_(a, b, msg=None):
- """Shorthand for 'assert a == b, "%r != %r" % (a, b)
- """
- assert a == b, msg or "%r != %r" % (a, b)
-
-
def make_decorator(func):
"""
Wraps a test decorator so as to properly replicate metadata
@@ -168,27 +148,3 @@ def nottest(func):
"""
func.__test__ = False
return func
-
-#
-# Expose assert* from unittest.TestCase
-# - give them pep8 style names
-#
-caps = re.compile('([A-Z])')
-
-def pep8(name):
- return caps.sub(lambda m: '_' + m.groups()[0].lower(), name)
-
-class Dummy(unittest.TestCase):
- def nop():
- pass
-_t = Dummy('nop')
-
-for at in [ at for at in dir(_t)
- if at.startswith('assert') and not '_' in at ]:
- pepd = pep8(at)
- vars()[pepd] = getattr(_t, at)
- __all__.append(pepd)
-
-del Dummy
-del _t
-del pep8
diff --git a/nose/tools/trivial.py b/nose/tools/trivial.py
new file mode 100644
index 0000000..34d5569
--- /dev/null
+++ b/nose/tools/trivial.py
@@ -0,0 +1,52 @@
+"""Tools so trivial that tracebacks should not descend into them
+
+We define the ``__unittest`` symbol in their module namespace so unittest will
+skip them when printing tracebacks, just as it does for their corresponding
+methods in ``unittest`` proper.
+
+"""
+import re
+import unittest
+
+
+__all__ = ['ok_', 'eq_']
+
+# Use the same flag as unittest itself to prevent descent into these functions:
+__unittest = 1
+
+
+def ok_(expr, msg=None):
+ """Shorthand for assert. Saves 3 whole characters!
+ """
+ assert expr, msg
+
+
+def eq_(a, b, msg=None):
+ """Shorthand for 'assert a == b, "%r != %r" % (a, b)
+ """
+ assert a == b, msg or "%r != %r" % (a, b)
+
+
+#
+# Expose assert* from unittest.TestCase
+# - give them pep8 style names
+#
+caps = re.compile('([A-Z])')
+
+def pep8(name):
+ return caps.sub(lambda m: '_' + m.groups()[0].lower(), name)
+
+class Dummy(unittest.TestCase):
+ def nop():
+ pass
+_t = Dummy('nop')
+
+for at in [ at for at in dir(_t)
+ if at.startswith('assert') and not '_' in at ]:
+ pepd = pep8(at)
+ vars()[pepd] = getattr(_t, at)
+ __all__.append(pepd)
+
+del Dummy
+del _t
+del pep8
diff --git a/unit_tests/test_tools.py b/unit_tests/test_tools.py
index 839d12b..4dadc02 100644
--- a/unit_tests/test_tools.py
+++ b/unit_tests/test_tools.py
@@ -31,22 +31,38 @@ class TestTools(unittest.TestCase):
else:
self.fail("eq_(1, 0) did not raise assertion error")
+ def test_eq_unittest_flag(self):
+ """Make sure eq_() is in a namespace that has __unittest = 1.
+
+ This lets tracebacks refrain from descending into the eq_ frame.
+
+ """
+ assert '__unittest' in eq_.func_globals
+
+ def test_istest_unittest_flag(self):
+ """Make sure istest() is not in a namespace that has __unittest = 1.
+
+ That is, make sure our __unittest labeling didn't get overzealous.
+
+ """
+ assert '__unittest' not in istest.func_globals
+
def test_raises(self):
from nose.case import FunctionTestCase
-
+
def raise_typeerror():
raise TypeError("foo")
def noraise():
pass
-
+
raise_good = raises(TypeError)(raise_typeerror)
raise_other = raises(ValueError)(raise_typeerror)
no_raise = raises(TypeError)(noraise)
tc = FunctionTestCase(raise_good)
self.assertEqual(str(tc), "%s.%s" % (__name__, 'raise_typeerror'))
-
+
raise_good()
try:
raise_other()
@@ -67,7 +83,7 @@ class TestTools(unittest.TestCase):
def too_slow():
time.sleep(.3)
too_slow = timed(.2)(too_slow)
-
+
def quick():
time.sleep(.1)
quick = timed(.2)(quick)
@@ -88,21 +104,21 @@ class TestTools(unittest.TestCase):
def f1():
pass
-
+
f2 = make_decorator(func)(f1)
-
+
assert f2.setup == 'setup'
assert f2.teardown == 'teardown'
def test_nested_decorators(self):
from nose.tools import raises, timed, with_setup
-
+
def test():
pass
-
+
def foo():
pass
-
+
test = with_setup(foo, foo)(test)
test = timed(1.0)(test)
test = raises(TypeError)(test)
@@ -112,7 +128,7 @@ class TestTools(unittest.TestCase):
def test_decorator_func_sorting(self):
from nose.tools import raises, timed, with_setup
from nose.util import func_lineno
-
+
def test1():
pass
@@ -136,13 +152,13 @@ class TestTools(unittest.TestCase):
self.assertEqual(func_lineno(test1), test1_pos)
self.assertEqual(func_lineno(test2), test2_pos)
self.assertEqual(func_lineno(test3), test3_pos)
-
+
def test_testcase_funcs(self):
import nose.tools
tc_asserts = [ at for at in dir(nose.tools)
if at.startswith('assert_') ]
print tc_asserts
-
+
# FIXME: not sure which of these are in all supported
# versions of python
assert 'assert_raises' in tc_asserts
@@ -153,7 +169,7 @@ class TestTools(unittest.TestCase):
from nose.tools import with_setup
from nose.case import FunctionTestCase
from unittest import TestResult
-
+
called = []
def test():
called.append('test')
@@ -163,7 +179,7 @@ class TestTools(unittest.TestCase):
def test3():
called.append('test3')
-
+
def s1():
called.append('s1')
@@ -172,7 +188,7 @@ class TestTools(unittest.TestCase):
def s3():
called.append('s3')
-
+
def t1():
called.append('t1')
@@ -181,7 +197,7 @@ class TestTools(unittest.TestCase):
def t3():
called.append('t3')
-
+
ws1 = with_setup(s1, t1)(test)
case1 = FunctionTestCase(ws1)
case1(TestResult())
@@ -202,6 +218,6 @@ class TestTools(unittest.TestCase):
case3(TestResult())
self.assertEqual(called, ['s1', 's2', 's3',
'test3', 't3', 't2', 't1'])
-
+
if __name__ == '__main__':
unittest.main()