Skip to content

Instantly share code, notes, and snippets.

@tipabu
Created August 29, 2017 18:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tipabu/1a06eafe0a43b29b82f1d806488cdb8a to your computer and use it in GitHub Desktop.
Save tipabu/1a06eafe0a43b29b82f1d806488cdb8a to your computer and use it in GitHub Desktop.
import functools
import unittest
import mock
__inputoutput__ = "__inputoutput__"
def with_inputs(input, output, identifier=None):
def decorator(f):
try:
io = getattr(f, __inputoutput__)
except AttributeError:
io = []
setattr(f, __inputoutput__, io)
io.append((input, output, identifier))
return f
return decorator
class TestWithData(unittest.TestCase):
class __metaclass__(type):
def __new__(meta, name, bases, clsdict):
to_remove = []
for methodname, method in clsdict.items():
if not hasattr(method, __inputoutput__):
continue
to_remove.append(methodname)
io = getattr(method, __inputoutput__)
delattr(method, __inputoutput__)
for input, output, identifier in io:
@functools.wraps(method)
def dummy(self, method=method, input=input, output=output):
method(self, input, output)
if identifier:
test_name = '_'.join((methodname, identifier))
else:
test_name = '%s(%s, %s)' % (methodname, input, output)
dummy.__name__ = test_name
if test_name in clsdict:
raise ValueError('Already defined %s' % test_name)
clsdict[test_name] = dummy
for methodname in to_remove:
del clsdict[methodname]
return type.__new__(meta, name, bases, clsdict)
class TestAdd(TestWithData):
@with_inputs((2, 3), 5)
@with_inputs((1, 1), 2)
@with_inputs((1, 1), 3, 'foo')
@with_inputs((1, 1), 3, 'bar')
def test_add(self, input, output):
a, b = input
self.assertEqual(a + b, output)
@with_inputs(1, 1)
@with_inputs(1, 2)
@mock.patch('sys.path')
def test_reflexive(self, input, output, mock_sys):
print mock_sys
self.assertEqual(input, output)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment