Improve landscape.io ratings by reducing ddt complexity
This commit is contained in:
110
ddt.py
110
ddt.py
@@ -1,3 +1,10 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# This file is a part of DDT (https://github.com/txels/ddt)
|
||||||
|
# Copyright 2012-2015 Carles Barrobés and DDT contributors
|
||||||
|
# For the exact contribution history, see the git revision log.
|
||||||
|
# DDT is licensed under the MIT License, included in
|
||||||
|
# https://github.com/txels/ddt/blob/master/LICENSE.md
|
||||||
|
|
||||||
import inspect
|
import inspect
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
@@ -129,6 +136,55 @@ def mk_test_name(name, value, index=0):
|
|||||||
return re.sub('\W|^(?=\d)', '_', test_name)
|
return re.sub('\W|^(?=\d)', '_', test_name)
|
||||||
|
|
||||||
|
|
||||||
|
def feed_data(func, new_name, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
This internal method decorator feeds the test data item to the test.
|
||||||
|
|
||||||
|
"""
|
||||||
|
@wraps(func)
|
||||||
|
def wrapper(self):
|
||||||
|
return func(self, *args, **kwargs)
|
||||||
|
wrapper.__name__ = new_name
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
def add_test(cls, test_name, func, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Add a test case to this class.
|
||||||
|
|
||||||
|
The test will be based on an existing function but will give it a new
|
||||||
|
name.
|
||||||
|
|
||||||
|
"""
|
||||||
|
setattr(cls, test_name, feed_data(func, test_name, *args, **kwargs))
|
||||||
|
|
||||||
|
|
||||||
|
def process_file_data(cls, name, func, file_attr):
|
||||||
|
"""
|
||||||
|
Process the parameter in the `file_data` decorator.
|
||||||
|
|
||||||
|
"""
|
||||||
|
cls_path = os.path.abspath(inspect.getsourcefile(cls))
|
||||||
|
data_file_path = os.path.join(os.path.dirname(cls_path), file_attr)
|
||||||
|
|
||||||
|
def _raise_ve(*args): # pylint: disable-msg=W0613
|
||||||
|
raise ValueError("%s does not exist" % file_attr)
|
||||||
|
|
||||||
|
if os.path.exists(data_file_path) is False:
|
||||||
|
test_name = mk_test_name(name, "error")
|
||||||
|
add_test(cls, test_name, _raise_ve, None)
|
||||||
|
else:
|
||||||
|
data = json.loads(open(data_file_path).read())
|
||||||
|
for i, elem in enumerate(data):
|
||||||
|
if isinstance(data, dict):
|
||||||
|
key, value = elem, data[elem]
|
||||||
|
test_name = mk_test_name(name, key, i)
|
||||||
|
elif isinstance(data, list):
|
||||||
|
value = elem
|
||||||
|
test_name = mk_test_name(name, value, i)
|
||||||
|
add_test(cls, test_name, func, value)
|
||||||
|
|
||||||
|
|
||||||
def ddt(cls):
|
def ddt(cls):
|
||||||
"""
|
"""
|
||||||
Class decorator for subclasses of ``unittest.TestCase``.
|
Class decorator for subclasses of ``unittest.TestCase``.
|
||||||
@@ -153,67 +209,21 @@ def ddt(cls):
|
|||||||
from the ``data`` key.
|
from the ``data`` key.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def feed_data(func, new_name, *args, **kwargs):
|
|
||||||
"""
|
|
||||||
This internal method decorator feeds the test data item to the test.
|
|
||||||
|
|
||||||
"""
|
|
||||||
@wraps(func)
|
|
||||||
def wrapper(self):
|
|
||||||
return func(self, *args, **kwargs)
|
|
||||||
wrapper.__name__ = new_name
|
|
||||||
return wrapper
|
|
||||||
|
|
||||||
def add_test(test_name, func, *args, **kwargs):
|
|
||||||
"""
|
|
||||||
Add a test case to this class.
|
|
||||||
|
|
||||||
The test will be based on an existing function but will give it a new
|
|
||||||
name.
|
|
||||||
|
|
||||||
"""
|
|
||||||
setattr(cls, test_name, feed_data(func, test_name, *args, **kwargs))
|
|
||||||
|
|
||||||
def process_file_data(name, func, file_attr):
|
|
||||||
"""
|
|
||||||
Process the parameter in the `file_data` decorator.
|
|
||||||
|
|
||||||
"""
|
|
||||||
cls_path = os.path.abspath(inspect.getsourcefile(cls))
|
|
||||||
data_file_path = os.path.join(os.path.dirname(cls_path), file_attr)
|
|
||||||
|
|
||||||
def _raise_ve(*args):
|
|
||||||
raise ValueError("%s does not exist" % file_attr)
|
|
||||||
|
|
||||||
if os.path.exists(data_file_path) is False:
|
|
||||||
test_name = mk_test_name(name, "error")
|
|
||||||
add_test(test_name, _raise_ve, None)
|
|
||||||
else:
|
|
||||||
data = json.loads(open(data_file_path).read())
|
|
||||||
for i, elem in enumerate(data):
|
|
||||||
if isinstance(data, dict):
|
|
||||||
key, value = elem, data[elem]
|
|
||||||
test_name = mk_test_name(name, key, i)
|
|
||||||
elif isinstance(data, list):
|
|
||||||
value = elem
|
|
||||||
test_name = mk_test_name(name, value, i)
|
|
||||||
add_test(test_name, func, value)
|
|
||||||
|
|
||||||
for name, func in list(cls.__dict__.items()):
|
for name, func in list(cls.__dict__.items()):
|
||||||
if hasattr(func, DATA_ATTR):
|
if hasattr(func, DATA_ATTR):
|
||||||
for i, v in enumerate(getattr(func, DATA_ATTR)):
|
for i, v in enumerate(getattr(func, DATA_ATTR)):
|
||||||
test_name = mk_test_name(name, getattr(v, "__name__", v), i)
|
test_name = mk_test_name(name, getattr(v, "__name__", v), i)
|
||||||
if hasattr(func, UNPACK_ATTR):
|
if hasattr(func, UNPACK_ATTR):
|
||||||
if isinstance(v, tuple) or isinstance(v, list):
|
if isinstance(v, tuple) or isinstance(v, list):
|
||||||
add_test(test_name, func, *v)
|
add_test(cls, test_name, func, *v)
|
||||||
else:
|
else:
|
||||||
# unpack dictionary
|
# unpack dictionary
|
||||||
add_test(test_name, func, **v)
|
add_test(cls, test_name, func, **v)
|
||||||
else:
|
else:
|
||||||
add_test(test_name, func, v)
|
add_test(cls, test_name, func, v)
|
||||||
delattr(cls, name)
|
delattr(cls, name)
|
||||||
elif hasattr(func, FILE_ATTR):
|
elif hasattr(func, FILE_ATTR):
|
||||||
file_attr = getattr(func, FILE_ATTR)
|
file_attr = getattr(func, FILE_ATTR)
|
||||||
process_file_data(name, func, file_attr)
|
process_file_data(cls, name, func, file_attr)
|
||||||
delattr(cls, name)
|
delattr(cls, name)
|
||||||
return cls
|
return cls
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ master_doc = 'index'
|
|||||||
|
|
||||||
# General information about the project.
|
# General information about the project.
|
||||||
project = u'DDT'
|
project = u'DDT'
|
||||||
|
# pylint: disable-msg=W0622
|
||||||
|
# - copyright is a builtin
|
||||||
copyright = u'2012, Carles Barrobés'
|
copyright = u'2012, Carles Barrobés'
|
||||||
|
|
||||||
# The version info for the project you're documenting, acts as replacement for
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ from ddt import ddt, data, file_data, unpack
|
|||||||
from test.mycode import larger_than_two, has_three_elements, is_a_greeting
|
from test.mycode import larger_than_two, has_three_elements, is_a_greeting
|
||||||
|
|
||||||
|
|
||||||
class mylist(list):
|
class Mylist(list):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def annotated(a, b):
|
def annotated(a, b):
|
||||||
r = mylist([a, b])
|
r = Mylist([a, b])
|
||||||
setattr(r, "__name__", "test_%d_greater_than_%d" % (a, b))
|
setattr(r, "__name__", "test_%d_greater_than_%d" % (a, b))
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
|||||||
@@ -187,21 +187,21 @@ def test_ddt_data_name_attribute():
|
|||||||
def hello():
|
def hello():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class myint(int):
|
class Myint(int):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class mytest(object):
|
class Mytest(object):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
d1 = myint(1)
|
d1 = Myint(1)
|
||||||
d1.__name__ = 'data1'
|
d1.__name__ = 'data1'
|
||||||
|
|
||||||
d2 = myint(2)
|
d2 = Myint(2)
|
||||||
|
|
||||||
data_hello = data(d1, d2)(hello)
|
data_hello = data(d1, d2)(hello)
|
||||||
setattr(mytest, 'test_hello', data_hello)
|
setattr(Mytest, 'test_hello', data_hello)
|
||||||
|
|
||||||
ddt_mytest = ddt(mytest)
|
ddt_mytest = ddt(Mytest)
|
||||||
assert_is_not_none(getattr(ddt_mytest, 'test_hello_1_data1'))
|
assert_is_not_none(getattr(ddt_mytest, 'test_hello_1_data1'))
|
||||||
assert_is_not_none(getattr(ddt_mytest, 'test_hello_2_2'))
|
assert_is_not_none(getattr(ddt_mytest, 'test_hello_2_2'))
|
||||||
|
|
||||||
@@ -219,33 +219,33 @@ def test_ddt_data_unicode():
|
|||||||
if six.PY2:
|
if six.PY2:
|
||||||
|
|
||||||
@ddt
|
@ddt
|
||||||
class mytest(object):
|
class Mytest(object):
|
||||||
@data(u'ascii', u'non-ascii-\N{SNOWMAN}', {u'\N{SNOWMAN}': 'data'})
|
@data(u'ascii', u'non-ascii-\N{SNOWMAN}', {u'\N{SNOWMAN}': 'data'})
|
||||||
def test_hello(self, val):
|
def test_hello(self, val):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
assert_is_not_none(getattr(mytest, 'test_hello_1_ascii'))
|
assert_is_not_none(getattr(Mytest, 'test_hello_1_ascii'))
|
||||||
assert_is_not_none(getattr(mytest, 'test_hello_2_non_ascii__u2603'))
|
assert_is_not_none(getattr(Mytest, 'test_hello_2_non_ascii__u2603'))
|
||||||
if is_hash_randomized():
|
if is_hash_randomized():
|
||||||
assert_is_not_none(getattr(mytest, 'test_hello_3'))
|
assert_is_not_none(getattr(Mytest, 'test_hello_3'))
|
||||||
else:
|
else:
|
||||||
assert_is_not_none(getattr(mytest,
|
assert_is_not_none(getattr(Mytest,
|
||||||
'test_hello_3__u__u2603____data__'))
|
'test_hello_3__u__u2603____data__'))
|
||||||
|
|
||||||
elif six.PY3:
|
elif six.PY3:
|
||||||
|
|
||||||
@ddt
|
@ddt
|
||||||
class mytest(object):
|
class Mytest(object):
|
||||||
@data('ascii', 'non-ascii-\N{SNOWMAN}', {'\N{SNOWMAN}': 'data'})
|
@data('ascii', 'non-ascii-\N{SNOWMAN}', {'\N{SNOWMAN}': 'data'})
|
||||||
def test_hello(self, val):
|
def test_hello(self, val):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
assert_is_not_none(getattr(mytest, 'test_hello_1_ascii'))
|
assert_is_not_none(getattr(Mytest, 'test_hello_1_ascii'))
|
||||||
assert_is_not_none(getattr(mytest, 'test_hello_2_non_ascii__'))
|
assert_is_not_none(getattr(Mytest, 'test_hello_2_non_ascii__'))
|
||||||
if is_hash_randomized():
|
if is_hash_randomized():
|
||||||
assert_is_not_none(getattr(mytest, 'test_hello_3'))
|
assert_is_not_none(getattr(Mytest, 'test_hello_3'))
|
||||||
else:
|
else:
|
||||||
assert_is_not_none(getattr(mytest, 'test_hello_3________data__'))
|
assert_is_not_none(getattr(Mytest, 'test_hello_3________data__'))
|
||||||
|
|
||||||
|
|
||||||
def test_feed_data_with_invalid_identifier():
|
def test_feed_data_with_invalid_identifier():
|
||||||
|
|||||||
Reference in New Issue
Block a user