7 new commits in pytest:

https://bitbucket.org/hpk42/pytest/commits/6845bca4e5ee/
Changeset:   6845bca4e5ee
Branch:      issue351
User:        pfctdayelise
Date:        2014-04-17 19:08:49+00:00
Summary:     issue351: Add ability to specify parametrize ids as a callable, to 
generate custom test ids. + tests, docs
Affected #:  3 files

diff -r 229f3213f7a629f547e6b89a20263a41611807a1 -r 
6845bca4e5eea15fbfe186e465e0dcb8f249c964 _pytest/python.py
--- a/_pytest/python.py
+++ b/_pytest/python.py
@@ -771,9 +771,14 @@
             function so that it can perform more expensive setups during the
             setup phase of a test rather than at collection time.
 
-        :arg ids: list of string ids each corresponding to the argvalues so
-            that they are part of the test id. If no ids are provided they will
-            be generated automatically from the argvalues.
+        :arg ids: list of string ids, or a callable.
+            If strings, each is corresponding to the argvalues so that they are
+            part of the test id.
+            If callable, it should take one argument (a single argvalue) and 
return
+            a string or return None. If None, the automatically generated id 
for that
+            argument will be used.
+            If no ids are provided they will be generated automatically from
+            the argvalues.
 
         :arg scope: if specified it denotes the scope of the parameters.
             The scope is used for grouping tests by parameter instances.
@@ -813,11 +818,15 @@
                     raise ValueError("%r uses no fixture %r" %(
                                      self.function, arg))
         valtype = indirect and "params" or "funcargs"
+        idfn = None
+        if callable(ids):
+            idfn = ids
+            ids = None
         if ids and len(ids) != len(argvalues):
             raise ValueError('%d tests specified with %d ids' %(
                              len(argvalues), len(ids)))
         if not ids:
-            ids = idmaker(argnames, argvalues)
+            ids = idmaker(argnames, argvalues, idfn)
         newcalls = []
         for callspec in self._calls or [CallSpec2(self)]:
             for param_index, valset in enumerate(argvalues):
@@ -865,17 +874,31 @@
         cs.setall(funcargs, id, param)
         self._calls.append(cs)
 
-def idmaker(argnames, argvalues):
-    idlist = []
-    for valindex, valset in enumerate(argvalues):
-        this_id = []
-        for nameindex, val in enumerate(valset):
-            if not isinstance(val, (float, int, str, bool, NoneType)):
-                this_id.append(str(argnames[nameindex])+str(valindex))
-            else:
-                this_id.append(str(val))
-        idlist.append("-".join(this_id))
-    return idlist
+
+def _idval(val, argname, idx, idfn):
+    if idfn:
+        try:
+            s = idfn(val)
+            if s:
+                return s
+        except Exception:
+            pass
+    if isinstance(val, (float, int, str, bool, NoneType)):
+        return str(val)
+    return str(argname)+str(idx)
+
+def _idvalset(idx, valset, argnames, idfn):
+    this_id = [_idval(val, argname, idx, idfn)
+               for val, argname in zip(valset, argnames)]
+    return "-".join(this_id)
+
+def idmaker(argnames, argvalues, idfn=None):
+    ids = [_idvalset(valindex, valset, argnames, idfn)
+           for valindex, valset in enumerate(argvalues)]
+    if len(set(ids)) < len(ids):
+        # the user may have provided a bad idfn which means the ids are not 
unique
+        ids = ["{}".format(i) + testid for i, testid in enumerate(ids)]
+    return ids
 
 def showfixtures(config):
     from _pytest.main import wrap_session

diff -r 229f3213f7a629f547e6b89a20263a41611807a1 -r 
6845bca4e5eea15fbfe186e465e0dcb8f249c964 doc/en/example/parametrize.txt
--- a/doc/en/example/parametrize.txt
+++ b/doc/en/example/parametrize.txt
@@ -68,6 +68,81 @@
 As expected when running the full range of ``param1`` values
 we'll get an error on the last one.
 
+
+Different options for test IDs
+------------------------------------
+
+pytest will build a string that is the test ID for each set of values in a
+parametrized test. These IDs can be used with "-k" to select specific cases
+to run, and they will also identify the specific case when one is failing.
+Running pytest with --collect-only will show the generated IDs.
+
+Numbers, strings, booleans and None will have their usual string representation
+used in the test ID. For other objects, pytest will make a string based on
+the argument name::
+
+    # contents of test_time.py
+
+    from datetime import datetime, timedelta
+
+    testdata = [(datetime(2001, 12, 12), datetime(2001, 12, 11), timedelta(1)),
+               (datetime(2001, 12, 11), datetime(2001, 12, 12), timedelta(-1)),
+               ]
+
+
+    @pytest.mark.parametrize("a,b,expected", testdata)
+    def test_timedistance_v0(a, b, expected):
+       diff = a - b
+       assert diff == expected
+
+
+    @pytest.mark.parametrize("a,b,expected", testdata, ids=["forward", 
"backward"])
+    def test_timedistance_v1(a, b, expected):
+       diff = a - b
+       assert diff == expected
+
+
+    def idfn(val):
+       if isinstance(val, (datetime,)):
+           # note this wouldn't show any hours/minutes/seconds
+           return val.strftime('%Y%m%d')
+
+
+    @pytest.mark.parametrize("a,b,expected", testdata, ids=idfn)
+    def test_timedistance_v2(a, b, expected):
+       diff = a - b
+       assert diff == expected
+
+
+In ``test_timedistance_v0``, we let pytest generate the test IDs.
+
+In ``test_timedistance_v1``, we specified ``ids`` as a list of strings which 
were
+used as the test IDs. These are succinct, but can be a pain to maintain.
+
+In ``test_timedistance_v2``, we specified ``ids`` as a function that can 
generate a
+string representation to make part of the test ID. So our ``datetime`` values 
use the
+label generated by ``idfn``, but because we didn't generate a label for 
``timedelta``
+objects, they are still using the default pytest representation::
+
+
+    $ py.test test_time.py --collect-only
+    ============================ test session starts 
=============================
+    platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.6.0.dev1
+    plugins: cache
+    collected 6 items
+    <Module 'test_time.py'>
+      <Function 'test_timedistance_v0[a0-b0-expected0]'>
+      <Function 'test_timedistance_v0[a1-b1-expected1]'>
+      <Function 'test_timedistance_v1[forward]'>
+      <Function 'test_timedistance_v1[backward]'>
+      <Function 'test_timedistance_v2[20011212-20011211-expected0]'>
+      <Function 'test_timedistance_v2[20011211-20011212-expected1]'>
+
+    ============================== in 0.04 seconds 
===============================
+
+
+
+
 A quick port of "testscenarios"
 ------------------------------------
 

diff -r 229f3213f7a629f547e6b89a20263a41611807a1 -r 
6845bca4e5eea15fbfe186e465e0dcb8f249c964 testing/python/metafunc.py
--- a/testing/python/metafunc.py
+++ b/testing/python/metafunc.py
@@ -151,6 +151,52 @@
                           "a6-b6",
                           "a7-b7"]
 
+    @pytest.mark.issue351
+    def test_idmaker_idfn(self):
+        from _pytest.python import idmaker
+        def ids(val):
+            if isinstance(val, Exception):
+                return repr(val)
+
+        result = idmaker(("a", "b"), [(10.0, IndexError()),
+                                      (20, KeyError()),
+                                      ("three", [1, 2, 3]),
+        ], idfn=ids)
+        assert result == ["10.0-IndexError()",
+                          "20-KeyError()",
+                          "three-b2",
+                         ]
+
+    @pytest.mark.issue351
+    def test_idmaker_idfn_unique_names(self):
+        from _pytest.python import idmaker
+        def ids(val):
+            return 'a'
+
+        result = idmaker(("a", "b"), [(10.0, IndexError()),
+                                      (20, KeyError()),
+                                      ("three", [1, 2, 3]),
+        ], idfn=ids)
+        assert result == ["0a-a",
+                          "1a-a",
+                          "2a-a",
+                         ]
+
+    @pytest.mark.issue351
+    def test_idmaker_idfn_exception(self):
+        from _pytest.python import idmaker
+        def ids(val):
+            raise Exception("bad code")
+
+        result = idmaker(("a", "b"), [(10.0, IndexError()),
+                                      (20, KeyError()),
+                                      ("three", [1, 2, 3]),
+        ], idfn=ids)
+        assert result == ["10.0-b0",
+                          "20-b1",
+                          "three-b2",
+                         ]
+
     def test_addcall_and_parametrize(self):
         def func(x, y): pass
         metafunc = self.Metafunc(func)


https://bitbucket.org/hpk42/pytest/commits/899b817f5de1/
Changeset:   899b817f5de1
Branch:      issue351
User:        flub
Date:        2014-10-07 23:11:32+00:00
Summary:     Functional tests for id function
Affected #:  1 file

diff -r 6845bca4e5eea15fbfe186e465e0dcb8f249c964 -r 
899b817f5de1f119c1c8d7d38028447a442d3f50 testing/python/integration.py
--- a/testing/python/integration.py
+++ b/testing/python/integration.py
@@ -262,5 +262,58 @@
         call = reprec.getcalls("pytest_collection_modifyitems")[0]
         assert len(call.items) == 1
         assert call.items[0].cls.__name__ == "TC"
-        
 
+
+@pytest.mark.issue351
+class TestParameterize:
+
+    def test_idfn_marker(self, testdir):
+        testdir.makepyfile("""
+            import pytest
+
+            def idfn(param):
+                if param == 0:
+                    return 'spam'
+                elif param == 1:
+                    return 'ham'
+                else:
+                    return None
+
+            @pytest.mark.parametrize('a,b', [(0, 2), (1, 2)], ids=idfn)
+            def test_params(a, b):
+                pass
+        """)
+        res = testdir.runpytest('--collect-only')
+        res.stdout.fnmatch_lines([
+            "*spam-2*",
+            "*ham-2*",
+        ])
+
+    def test_idfn_fixture(self, testdir):
+        testdir.makepyfile("""
+            import pytest
+
+            def idfn(param):
+                if param == 0:
+                    return 'spam'
+                elif param == 1:
+                    return 'ham'
+                else:
+                    return None
+
+            @pytest.fixture(params=[0, 1], ids=idfn)
+            def a(request):
+                return request.param
+
+            @pytest.fixture(params=[1, 2], ids=idfn)
+            def b(request):
+                return request.param
+
+            def test_params(a, b):
+                pass
+        """)
+        res = testdir.runpytest('--collect-only')
+        res.stdout.fnmatch_lines([
+            "*spam-2*",
+            "*ham-2*",
+        ])


https://bitbucket.org/hpk42/pytest/commits/27d71618e41a/
Changeset:   27d71618e41a
Branch:      issue351
User:        flub
Date:        2014-10-07 23:43:27+00:00
Summary:     Document the ids keyword for fixture parametrisation
Affected #:  2 files

diff -r 899b817f5de1f119c1c8d7d38028447a442d3f50 -r 
27d71618e41af0a36f9aaffbe169a7f7bbe4bc1e doc/en/example/parametrize.txt
--- a/doc/en/example/parametrize.txt
+++ b/doc/en/example/parametrize.txt
@@ -73,9 +73,9 @@
 ------------------------------------
 
 pytest will build a string that is the test ID for each set of values in a
-parametrized test. These IDs can be used with "-k" to select specific cases
+parametrized test. These IDs can be used with ``-k`` to select specific cases
 to run, and they will also identify the specific case when one is failing.
-Running pytest with --collect-only will show the generated IDs.
+Running pytest with ``--collect-only`` will show the generated IDs.
 
 Numbers, strings, booleans and None will have their usual string representation
 used in the test ID. For other objects, pytest will make a string based on

diff -r 899b817f5de1f119c1c8d7d38028447a442d3f50 -r 
27d71618e41af0a36f9aaffbe169a7f7bbe4bc1e doc/en/fixture.txt
--- a/doc/en/fixture.txt
+++ b/doc/en/fixture.txt
@@ -431,6 +431,61 @@
 connection the second test fails in ``test_ehlo`` because a
 different server string is expected than what arrived.
 
+pytest will build a string that is the test ID for each fixture value
+in a parametrized fixture, e.g. ``test_ehlo[merlinux.eu]`` and
+``test_ehlo[mail.python.org]`` in the above examples.  These IDs can
+be used with ``-k`` to select specific cases to run, and they will
+also identify the specific case when one is failing.  Running pytest
+with ``--collect-only`` will show the generated IDs.
+
+Numbers, strings, booleans and None will have their usual string
+representation used in the test ID. For other objects, pytest will
+make a string based on the argument name.  It is possible to customise
+the string used in a test ID for a certain fixture value by using the
+``ids`` keyword argument::
+
+   import pytest
+
+   @pytest.fixture(params=[0, 1], ids=["spam", "ham"])
+   def a(request):
+       return request.param
+
+   def test_a(a):
+       pass
+
+   def idfn(fixture_value):
+       if fixture_value == 0:
+           return "eggs"
+       else:
+           return None
+
+   @pytest.fixture(params=[0, 1], ids=idfn)
+   def b(request):
+       return request.param
+
+   def test_b(b):
+       pass
+
+The above shows how ``ids`` can be either a list of strings to use or
+a function which will be called with the fixture value and then
+has to return a string to use.  In the latter case if the function
+return ``None`` then pytest's auto-generated ID will be used.
+
+Running the above tests results in the following test IDs being used::
+
+   $ py.test --collect-only
+   ========================== test session starts ==========================
+   platform linux2 -- Python 2.7.6 -- py-1.4.25.dev2 -- pytest-2.6.0.dev1
+   plugins: xdist
+   collected 4 items
+   <Module 'test_ids.py'>
+     <Function 'test_a[spam]'>
+     <Function 'test_a[ham]'>
+     <Function 'test_b[eggs]'>
+     <Function 'test_b[1]'>
+
+   ===========================  in 0.05 seconds ============================
+
 
 .. _`interdependent fixtures`:
 


https://bitbucket.org/hpk42/pytest/commits/c710cf744edc/
Changeset:   c710cf744edc
User:        flub
Date:        2014-10-22 22:18:01+00:00
Summary:     Merged in pfctdayelise/pytest/issue351 (pull request #161)

Fixes issue351: Add ability to specify parametrize ids as a
callable, to generate custom test ids. + tests, docs

Hg branch merge
Affected #:  5 files

diff -r e9bfc62abed3c6151cd6978167377f4bb1566802 -r 
c710cf744edc7053cae1c5a08903d15df5e82679 _pytest/python.py
--- a/_pytest/python.py
+++ b/_pytest/python.py
@@ -798,9 +798,14 @@
             function so that it can perform more expensive setups during the
             setup phase of a test rather than at collection time.
 
-        :arg ids: list of string ids each corresponding to the argvalues so
-            that they are part of the test id. If no ids are provided they will
-            be generated automatically from the argvalues.
+        :arg ids: list of string ids, or a callable.
+            If strings, each is corresponding to the argvalues so that they are
+            part of the test id.
+            If callable, it should take one argument (a single argvalue) and 
return
+            a string or return None. If None, the automatically generated id 
for that
+            argument will be used.
+            If no ids are provided they will be generated automatically from
+            the argvalues.
 
         :arg scope: if specified it denotes the scope of the parameters.
             The scope is used for grouping tests by parameter instances.
@@ -840,11 +845,15 @@
                     raise ValueError("%r uses no fixture %r" %(
                                      self.function, arg))
         valtype = indirect and "params" or "funcargs"
+        idfn = None
+        if callable(ids):
+            idfn = ids
+            ids = None
         if ids and len(ids) != len(argvalues):
             raise ValueError('%d tests specified with %d ids' %(
                              len(argvalues), len(ids)))
         if not ids:
-            ids = idmaker(argnames, argvalues)
+            ids = idmaker(argnames, argvalues, idfn)
         newcalls = []
         for callspec in self._calls or [CallSpec2(self)]:
             for param_index, valset in enumerate(argvalues):
@@ -892,17 +901,31 @@
         cs.setall(funcargs, id, param)
         self._calls.append(cs)
 
-def idmaker(argnames, argvalues):
-    idlist = []
-    for valindex, valset in enumerate(argvalues):
-        this_id = []
-        for nameindex, val in enumerate(valset):
-            if not isinstance(val, (float, int, str, bool, NoneType)):
-                this_id.append(str(argnames[nameindex])+str(valindex))
-            else:
-                this_id.append(str(val))
-        idlist.append("-".join(this_id))
-    return idlist
+
+def _idval(val, argname, idx, idfn):
+    if idfn:
+        try:
+            s = idfn(val)
+            if s:
+                return s
+        except Exception:
+            pass
+    if isinstance(val, (float, int, str, bool, NoneType)):
+        return str(val)
+    return str(argname)+str(idx)
+
+def _idvalset(idx, valset, argnames, idfn):
+    this_id = [_idval(val, argname, idx, idfn)
+               for val, argname in zip(valset, argnames)]
+    return "-".join(this_id)
+
+def idmaker(argnames, argvalues, idfn=None):
+    ids = [_idvalset(valindex, valset, argnames, idfn)
+           for valindex, valset in enumerate(argvalues)]
+    if len(set(ids)) < len(ids):
+        # the user may have provided a bad idfn which means the ids are not 
unique
+        ids = ["{}".format(i) + testid for i, testid in enumerate(ids)]
+    return ids
 
 def showfixtures(config):
     from _pytest.main import wrap_session

diff -r e9bfc62abed3c6151cd6978167377f4bb1566802 -r 
c710cf744edc7053cae1c5a08903d15df5e82679 doc/en/example/parametrize.txt
--- a/doc/en/example/parametrize.txt
+++ b/doc/en/example/parametrize.txt
@@ -68,6 +68,81 @@
 As expected when running the full range of ``param1`` values
 we'll get an error on the last one.
 
+
+Different options for test IDs
+------------------------------------
+
+pytest will build a string that is the test ID for each set of values in a
+parametrized test. These IDs can be used with ``-k`` to select specific cases
+to run, and they will also identify the specific case when one is failing.
+Running pytest with ``--collect-only`` will show the generated IDs.
+
+Numbers, strings, booleans and None will have their usual string representation
+used in the test ID. For other objects, pytest will make a string based on
+the argument name::
+
+    # contents of test_time.py
+
+    from datetime import datetime, timedelta
+
+    testdata = [(datetime(2001, 12, 12), datetime(2001, 12, 11), timedelta(1)),
+               (datetime(2001, 12, 11), datetime(2001, 12, 12), timedelta(-1)),
+               ]
+
+
+    @pytest.mark.parametrize("a,b,expected", testdata)
+    def test_timedistance_v0(a, b, expected):
+       diff = a - b
+       assert diff == expected
+
+
+    @pytest.mark.parametrize("a,b,expected", testdata, ids=["forward", 
"backward"])
+    def test_timedistance_v1(a, b, expected):
+       diff = a - b
+       assert diff == expected
+
+
+    def idfn(val):
+       if isinstance(val, (datetime,)):
+           # note this wouldn't show any hours/minutes/seconds
+           return val.strftime('%Y%m%d')
+
+
+    @pytest.mark.parametrize("a,b,expected", testdata, ids=idfn)
+    def test_timedistance_v2(a, b, expected):
+       diff = a - b
+       assert diff == expected
+
+
+In ``test_timedistance_v0``, we let pytest generate the test IDs.
+
+In ``test_timedistance_v1``, we specified ``ids`` as a list of strings which 
were
+used as the test IDs. These are succinct, but can be a pain to maintain.
+
+In ``test_timedistance_v2``, we specified ``ids`` as a function that can 
generate a
+string representation to make part of the test ID. So our ``datetime`` values 
use the
+label generated by ``idfn``, but because we didn't generate a label for 
``timedelta``
+objects, they are still using the default pytest representation::
+
+
+    $ py.test test_time.py --collect-only
+    ============================ test session starts 
=============================
+    platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.6.0.dev1
+    plugins: cache
+    collected 6 items
+    <Module 'test_time.py'>
+      <Function 'test_timedistance_v0[a0-b0-expected0]'>
+      <Function 'test_timedistance_v0[a1-b1-expected1]'>
+      <Function 'test_timedistance_v1[forward]'>
+      <Function 'test_timedistance_v1[backward]'>
+      <Function 'test_timedistance_v2[20011212-20011211-expected0]'>
+      <Function 'test_timedistance_v2[20011211-20011212-expected1]'>
+
+    ============================== in 0.04 seconds 
===============================
+
+
+
+
 A quick port of "testscenarios"
 ------------------------------------
 

diff -r e9bfc62abed3c6151cd6978167377f4bb1566802 -r 
c710cf744edc7053cae1c5a08903d15df5e82679 doc/en/fixture.txt
--- a/doc/en/fixture.txt
+++ b/doc/en/fixture.txt
@@ -429,6 +429,61 @@
 connection the second test fails in ``test_ehlo`` because a
 different server string is expected than what arrived.
 
+pytest will build a string that is the test ID for each fixture value
+in a parametrized fixture, e.g. ``test_ehlo[merlinux.eu]`` and
+``test_ehlo[mail.python.org]`` in the above examples.  These IDs can
+be used with ``-k`` to select specific cases to run, and they will
+also identify the specific case when one is failing.  Running pytest
+with ``--collect-only`` will show the generated IDs.
+
+Numbers, strings, booleans and None will have their usual string
+representation used in the test ID. For other objects, pytest will
+make a string based on the argument name.  It is possible to customise
+the string used in a test ID for a certain fixture value by using the
+``ids`` keyword argument::
+
+   import pytest
+
+   @pytest.fixture(params=[0, 1], ids=["spam", "ham"])
+   def a(request):
+       return request.param
+
+   def test_a(a):
+       pass
+
+   def idfn(fixture_value):
+       if fixture_value == 0:
+           return "eggs"
+       else:
+           return None
+
+   @pytest.fixture(params=[0, 1], ids=idfn)
+   def b(request):
+       return request.param
+
+   def test_b(b):
+       pass
+
+The above shows how ``ids`` can be either a list of strings to use or
+a function which will be called with the fixture value and then
+has to return a string to use.  In the latter case if the function
+return ``None`` then pytest's auto-generated ID will be used.
+
+Running the above tests results in the following test IDs being used::
+
+   $ py.test --collect-only
+   ========================== test session starts ==========================
+   platform linux2 -- Python 2.7.6 -- py-1.4.25.dev2 -- pytest-2.6.0.dev1
+   plugins: xdist
+   collected 4 items
+   <Module 'test_ids.py'>
+     <Function 'test_a[spam]'>
+     <Function 'test_a[ham]'>
+     <Function 'test_b[eggs]'>
+     <Function 'test_b[1]'>
+
+   ===========================  in 0.05 seconds ============================
+
 
 .. _`interdependent fixtures`:
 

diff -r e9bfc62abed3c6151cd6978167377f4bb1566802 -r 
c710cf744edc7053cae1c5a08903d15df5e82679 testing/python/integration.py
--- a/testing/python/integration.py
+++ b/testing/python/integration.py
@@ -282,5 +282,58 @@
         call = reprec.getcalls("pytest_collection_modifyitems")[0]
         assert len(call.items) == 1
         assert call.items[0].cls.__name__ == "TC"
-        
 
+
+@pytest.mark.issue351
+class TestParameterize:
+
+    def test_idfn_marker(self, testdir):
+        testdir.makepyfile("""
+            import pytest
+
+            def idfn(param):
+                if param == 0:
+                    return 'spam'
+                elif param == 1:
+                    return 'ham'
+                else:
+                    return None
+
+            @pytest.mark.parametrize('a,b', [(0, 2), (1, 2)], ids=idfn)
+            def test_params(a, b):
+                pass
+        """)
+        res = testdir.runpytest('--collect-only')
+        res.stdout.fnmatch_lines([
+            "*spam-2*",
+            "*ham-2*",
+        ])
+
+    def test_idfn_fixture(self, testdir):
+        testdir.makepyfile("""
+            import pytest
+
+            def idfn(param):
+                if param == 0:
+                    return 'spam'
+                elif param == 1:
+                    return 'ham'
+                else:
+                    return None
+
+            @pytest.fixture(params=[0, 1], ids=idfn)
+            def a(request):
+                return request.param
+
+            @pytest.fixture(params=[1, 2], ids=idfn)
+            def b(request):
+                return request.param
+
+            def test_params(a, b):
+                pass
+        """)
+        res = testdir.runpytest('--collect-only')
+        res.stdout.fnmatch_lines([
+            "*spam-2*",
+            "*ham-2*",
+        ])

diff -r e9bfc62abed3c6151cd6978167377f4bb1566802 -r 
c710cf744edc7053cae1c5a08903d15df5e82679 testing/python/metafunc.py
--- a/testing/python/metafunc.py
+++ b/testing/python/metafunc.py
@@ -151,6 +151,52 @@
                           "a6-b6",
                           "a7-b7"]
 
+    @pytest.mark.issue351
+    def test_idmaker_idfn(self):
+        from _pytest.python import idmaker
+        def ids(val):
+            if isinstance(val, Exception):
+                return repr(val)
+
+        result = idmaker(("a", "b"), [(10.0, IndexError()),
+                                      (20, KeyError()),
+                                      ("three", [1, 2, 3]),
+        ], idfn=ids)
+        assert result == ["10.0-IndexError()",
+                          "20-KeyError()",
+                          "three-b2",
+                         ]
+
+    @pytest.mark.issue351
+    def test_idmaker_idfn_unique_names(self):
+        from _pytest.python import idmaker
+        def ids(val):
+            return 'a'
+
+        result = idmaker(("a", "b"), [(10.0, IndexError()),
+                                      (20, KeyError()),
+                                      ("three", [1, 2, 3]),
+        ], idfn=ids)
+        assert result == ["0a-a",
+                          "1a-a",
+                          "2a-a",
+                         ]
+
+    @pytest.mark.issue351
+    def test_idmaker_idfn_exception(self):
+        from _pytest.python import idmaker
+        def ids(val):
+            raise Exception("bad code")
+
+        result = idmaker(("a", "b"), [(10.0, IndexError()),
+                                      (20, KeyError()),
+                                      ("three", [1, 2, 3]),
+        ], idfn=ids)
+        assert result == ["10.0-b0",
+                          "20-b1",
+                          "three-b2",
+                         ]
+
     def test_addcall_and_parametrize(self):
         def func(x, y): pass
         metafunc = self.Metafunc(func)


https://bitbucket.org/hpk42/pytest/commits/3b0a3f176786/
Changeset:   3b0a3f176786
User:        flub
Date:        2014-10-22 22:20:27+00:00
Summary:     Mention issue351/PR161 in changelog
Affected #:  1 file

diff -r c710cf744edc7053cae1c5a08903d15df5e82679 -r 
3b0a3f1767860c9efd2d4e3467187f85985bbf49 CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,10 @@
 2.7.0.dev
 ----------
 
+- implement issue351: add ability to specify parametrize ids as a callable
+  to generate custom test ids.  Thanks Brianna Laugher for the idea and
+  implementation.
+
 - introduce and document new hookwrapper mechanism useful for plugins
   which want to wrap the execution of certain hooks for their purposes.
   This supersedes the undocumented ``__multicall__`` protocol which


https://bitbucket.org/hpk42/pytest/commits/0baa494c9d7a/
Changeset:   0baa494c9d7a
Branch:      issue351
User:        flub
Date:        2014-10-22 22:21:42+00:00
Summary:     closing branch
Affected #:  0 files



https://bitbucket.org/hpk42/pytest/commits/7f1df35743c6/
Changeset:   7f1df35743c6
Branch:      python-classes-glob
User:        flub
Date:        2014-10-22 22:21:58+00:00
Summary:     closing branch
Affected #:  0 files

Repository URL: https://bitbucket.org/hpk42/pytest/

--

This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
_______________________________________________
pytest-commit mailing list
pytest-commit@python.org
https://mail.python.org/mailman/listinfo/pytest-commit

Reply via email to