Repository: datadriventests/ddt

Issue:
function ddt 
function ddt    test_docstring = getattr(v, "__doc__", None)，
when  v has attribte， return __doc__ of  v    So that desc of report  is __doc__ of v（list  tuple dict） ,not __doc__ of  testing function

Discussion:

Patch:
diff --git a/.gitignore b/.gitignore
index b29aa3e..a82433e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,4 @@ ddt.egg-info/
 /docs/_build/
 .tox
 .ropeproject
+venv/
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
index 7ef2224..efeae23 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,12 +1,10 @@
 language: python
 python:
-  #- 2.6
   - 2.7
-  #- 3.2
-  - 3.3
   - 3.4
   - 3.5
 install: pip install -r requirements/test.txt
+
 script:
     - nosetests --with-cov --cover-package=ddt
     - flake8 ddt.py test
diff --git a/ddt.py b/ddt.py
index 60eb1b0..636de02 100644
--- a/ddt.py
+++ b/ddt.py
@@ -19,7 +19,7 @@ except ImportError:  # pragma: no cover
 else:
     _have_yaml = True
 
-__version__ = '1.2.0'
+__version__ = '1.2.1'
 
 # These attributes will not conflict with any real python attribute
 # They are added to the decorated test method and processed later
@@ -135,7 +135,7 @@ def mk_test_name(name, value, index=0):
     return re.sub(r'\W|^(?=\d)', '_', test_name)
 
 
-def feed_data(func, new_name, test_docstring, *args, **kwargs):
+def feed_data(func, new_name, test_data_docstring, *args, **kwargs):
     """
     This internal method decorator feeds the test data item to the test.
 
@@ -146,8 +146,8 @@ def feed_data(func, new_name, test_docstring, *args, **kwargs):
     wrapper.__name__ = new_name
     wrapper.__wrapped__ = func
     # set docstring if exists
-    if test_docstring is not None:
-        wrapper.__doc__ = test_docstring
+    if test_data_docstring is not None:
+        wrapper.__doc__ = test_data_docstring
     else:
         # Try to call format on the docstring
         if func.__doc__:
@@ -177,7 +177,6 @@ def add_test(cls, test_name, test_docstring, func, *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)
@@ -223,7 +222,6 @@ def process_file_data(cls, name, func, file_attr):
 def _add_tests_from_data(cls, name, func, data):
     """
     Add tests from data loaded from the data file into the class
-
     """
     for i, elem in enumerate(data):
         if isinstance(data, dict):
@@ -238,6 +236,23 @@ def _add_tests_from_data(cls, name, func, data):
             add_test(cls, test_name, test_name, func, value)
 
 
+def _is_primitive(obj):
+    """Finds out if the obj is a "primitive". It is somewhat hacky but it works.
+    """
+    return not hasattr(obj, '__dict__')
+
+
+def _get_test_data_docstring(func, value):
+    """Returns a docstring based on the following resolution strategy:
+    1. Passed value is not a "primitive" and has a docstring, then use it.
+    2. In all other cases return None, i.e the test name is used.
+    """
+    if not _is_primitive(value) and value.__doc__:
+        return value.__doc__
+    else:
+        return None
+
+
 def ddt(cls):
     """
     Class decorator for subclasses of ``unittest.TestCase``.
@@ -266,15 +281,27 @@ def ddt(cls):
         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)
-                test_docstring = getattr(v, "__doc__", None)
+                test_data_docstring = _get_test_data_docstring(func, v)
                 if hasattr(func, UNPACK_ATTR):
                     if isinstance(v, tuple) or isinstance(v, list):
-                        add_test(cls, test_name, test_docstring, func, *v)
+                        add_test(
+                            cls,
+                            test_name,
+                            test_data_docstring,
+                            func,
+                            *v
+                        )
                     else:
                         # unpack dictionary
-                        add_test(cls, test_name, test_docstring, func, **v)
+                        add_test(
+                            cls,
+                            test_name,
+                            test_data_docstring,
+                            func,
+                            **v
+                        )
                 else:
-                    add_test(cls, test_name, test_docstring, func, v)
+                    add_test(cls, test_name, test_data_docstring, func, v)
             delattr(cls, name)
         elif hasattr(func, FILE_ATTR):
             file_attr = getattr(func, FILE_ATTR)
diff --git a/tox.ini b/tox.ini
index 13df3d3..da77f04 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
 [tox]
-envlist = py27, py33, py34, py35
+envlist = py27, py34, py35
 
 [testenv]
 deps = 


Test patch:
diff --git a/test/test_functional.py b/test/test_functional.py
index 07f326a..5049928 100644
--- a/test/test_functional.py
+++ b/test/test_functional.py
@@ -242,7 +242,7 @@ def test_ddt_data_doc_attribute():
     Test the ``__doc__`` attribute handling of ``data`` items with ``ddt``
     """
 
-    def hello():
+    def func_w_doc():
         """testFunctionDocstring {6}
 
         :param: None
@@ -250,6 +250,9 @@ def test_ddt_data_doc_attribute():
         """
         pass
 
+    def func_wo_doc():
+        pass
+
     class Myint(int):
         pass
 
@@ -263,18 +266,40 @@ def test_ddt_data_doc_attribute():
     d2 = Myint(2)
     d2.__name__ = 'case2'
 
-    data_hello = data(d1, d2)(hello)
-    setattr(Mytest, 'test_hello', data_hello)
+    data_hello = data(d1, d2, {'test': True})(func_w_doc)
+    data_hello2 = data(d1, d2, {'test': True})(func_wo_doc)
+
+    setattr(Mytest, 'first_test', data_hello)
+    setattr(Mytest, 'second_test', data_hello2)
     ddt_mytest = ddt(Mytest)
 
     assert_equal(
         getattr(
-            getattr(ddt_mytest, 'test_hello_1_case1'), '__doc__'), d1.__doc__
+            getattr(ddt_mytest, 'first_test_1_case1'), '__doc__'), d1.__doc__
+    )
+    assert_equal(
+        getattr(
+            getattr(ddt_mytest, 'first_test_2_case2'), '__doc__'),
+        func_w_doc.__doc__
+    )
+    assert_equal(
+        getattr(
+            getattr(ddt_mytest, 'first_test_3'), '__doc__'),
+        func_w_doc.__doc__
+    )
+    assert_equal(
+        getattr(
+            getattr(ddt_mytest, 'second_test_1_case1'), '__doc__'), d1.__doc__
     )
     assert_equal(
         getattr(
-            getattr(ddt_mytest, 'test_hello_2_case2'), '__doc__'),
-        hello.__doc__
+            getattr(ddt_mytest, 'second_test_2_case2'), '__doc__'),
+        None
+    )
+    assert_equal(
+        getattr(
+            getattr(ddt_mytest, 'second_test_3'), '__doc__'),
+        None
     )
 
 
@@ -282,10 +307,6 @@ def test_ddt_data_unicode():
     """
     Test that unicode strings are converted to function names correctly
     """
-
-    def hello():
-        pass
-
     # We test unicode support separately for python 2 and 3
 
     if six.PY2: