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 json
|
||||
import os
|
||||
@@ -129,6 +136,55 @@ def mk_test_name(name, value, index=0):
|
||||
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):
|
||||
"""
|
||||
Class decorator for subclasses of ``unittest.TestCase``.
|
||||
@@ -153,67 +209,21 @@ def ddt(cls):
|
||||
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()):
|
||||
if hasattr(func, DATA_ATTR):
|
||||
for i, v in enumerate(getattr(func, DATA_ATTR)):
|
||||
test_name = mk_test_name(name, getattr(v, "__name__", v), i)
|
||||
if hasattr(func, UNPACK_ATTR):
|
||||
if isinstance(v, tuple) or isinstance(v, list):
|
||||
add_test(test_name, func, *v)
|
||||
add_test(cls, test_name, func, *v)
|
||||
else:
|
||||
# unpack dictionary
|
||||
add_test(test_name, func, **v)
|
||||
add_test(cls, test_name, func, **v)
|
||||
else:
|
||||
add_test(test_name, func, v)
|
||||
add_test(cls, test_name, func, v)
|
||||
delattr(cls, name)
|
||||
elif hasattr(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)
|
||||
return cls
|
||||
|
||||
@@ -48,6 +48,8 @@ master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'DDT'
|
||||
# pylint: disable-msg=W0622
|
||||
# - copyright is a builtin
|
||||
copyright = u'2012, Carles Barrobés'
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
class mylist(list):
|
||||
class Mylist(list):
|
||||
pass
|
||||
|
||||
|
||||
def annotated(a, b):
|
||||
r = mylist([a, b])
|
||||
r = Mylist([a, b])
|
||||
setattr(r, "__name__", "test_%d_greater_than_%d" % (a, b))
|
||||
return r
|
||||
|
||||
|
||||
@@ -187,21 +187,21 @@ def test_ddt_data_name_attribute():
|
||||
def hello():
|
||||
pass
|
||||
|
||||
class myint(int):
|
||||
class Myint(int):
|
||||
pass
|
||||
|
||||
class mytest(object):
|
||||
class Mytest(object):
|
||||
pass
|
||||
|
||||
d1 = myint(1)
|
||||
d1 = Myint(1)
|
||||
d1.__name__ = 'data1'
|
||||
|
||||
d2 = myint(2)
|
||||
d2 = Myint(2)
|
||||
|
||||
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_2_2'))
|
||||
|
||||
@@ -219,33 +219,33 @@ def test_ddt_data_unicode():
|
||||
if six.PY2:
|
||||
|
||||
@ddt
|
||||
class mytest(object):
|
||||
class Mytest(object):
|
||||
@data(u'ascii', u'non-ascii-\N{SNOWMAN}', {u'\N{SNOWMAN}': 'data'})
|
||||
def test_hello(self, val):
|
||||
pass
|
||||
|
||||
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_1_ascii'))
|
||||
assert_is_not_none(getattr(Mytest, 'test_hello_2_non_ascii__u2603'))
|
||||
if is_hash_randomized():
|
||||
assert_is_not_none(getattr(mytest, 'test_hello_3'))
|
||||
assert_is_not_none(getattr(Mytest, 'test_hello_3'))
|
||||
else:
|
||||
assert_is_not_none(getattr(mytest,
|
||||
assert_is_not_none(getattr(Mytest,
|
||||
'test_hello_3__u__u2603____data__'))
|
||||
|
||||
elif six.PY3:
|
||||
|
||||
@ddt
|
||||
class mytest(object):
|
||||
class Mytest(object):
|
||||
@data('ascii', 'non-ascii-\N{SNOWMAN}', {'\N{SNOWMAN}': 'data'})
|
||||
def test_hello(self, val):
|
||||
pass
|
||||
|
||||
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_1_ascii'))
|
||||
assert_is_not_none(getattr(Mytest, 'test_hello_2_non_ascii__'))
|
||||
if is_hash_randomized():
|
||||
assert_is_not_none(getattr(mytest, 'test_hello_3'))
|
||||
assert_is_not_none(getattr(Mytest, 'test_hello_3'))
|
||||
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():
|
||||
|
||||
Reference in New Issue
Block a user