From a9193a15310138981b2b56f7db69c1c2a6471ea1 Mon Sep 17 00:00:00 2001
From: Rafael Bertoldi <bertoldi@esss.com.br>
Date: Fri, 30 Dec 2016 15:37:09 -0200
Subject: [PATCH] No longer silently ignore errors in parametrize callable ids

---
 CHANGELOG.rst              |  3 ++
 _pytest/python.py          | 11 ++++++--
 testing/python/metafunc.py | 58 ++++++++++++++++++++++++++++++++------
 3 files changed, 60 insertions(+), 12 deletions(-)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 0efd9c92e..aab0ae6e3 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -8,6 +8,8 @@ New Features
 * Added an ini option ``doctest_encoding`` to specify which encoding to use for doctest files.
   Thanks `@wheerd`_ for the PR (`#2101`_).
 
+* pytest now warns when a callable ids raises in a parametrized test. Thanks `@fogo`_ for the PR.
+
 *
 
 
@@ -39,6 +41,7 @@ Changes
 .. _@fushi: https://github.com/fushi
 .. _@mattduck: https://github.com/mattduck
 .. _@wheerd: https://github.com/wheerd
+.. _@fogo: https://github.com/fogo
 
 .. _#1512: https://github.com/pytest-dev/pytest/issues/1512
 .. _#1874: https://github.com/pytest-dev/pytest/pull/1874
diff --git a/_pytest/python.py b/_pytest/python.py
index 205ca472f..fee68251d 100644
--- a/_pytest/python.py
+++ b/_pytest/python.py
@@ -928,12 +928,17 @@ def _find_parametrized_scope(argnames, arg2fixturedefs, indirect):
 
 def _idval(val, argname, idx, idfn, config=None):
     if idfn:
+        s = None
         try:
             s = idfn(val)
-            if s:
-                return _escape_strings(s)
         except Exception:
-            pass
+            # See issue https://github.com/pytest-dev/pytest/issues/2169
+            import warnings
+            msg = "Raised while trying to determine id of parameter %s at position %d." % (argname, idx)
+            msg += '\nUpdate your code as this will raise an error in pytest-4.0.'
+            warnings.warn(msg)
+        if s:
+            return _escape_strings(s)
 
     if config:
         hook_id = config.hook.pytest_make_parametrize_id(config=config, val=val)
diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py
index a7e1d5699..e88107d0b 100644
--- a/testing/python/metafunc.py
+++ b/testing/python/metafunc.py
@@ -296,18 +296,58 @@ class TestMetafunc:
     @pytest.mark.issue351
     def test_idmaker_idfn_exception(self):
         from _pytest.python import idmaker
+        from _pytest.recwarn import WarningsRecorder
+
+        class BadIdsException(Exception):
+            pass
 
         def ids(val):
-            raise Exception("bad code")
+            raise BadIdsException("ids raised")
 
-        result = idmaker(("a", "b"), [(10.0, IndexError()),
-                                      (20, KeyError()),
-                                      ("three", [1, 2, 3]),
-        ], idfn=ids)
-        assert result == ["10.0-b0",
-                          "20-b1",
-                          "three-b2",
-                         ]
+        rec = WarningsRecorder()
+        with rec:
+            idmaker(("a", "b"), [(10.0, IndexError()),
+                                          (20, KeyError()),
+                                          ("three", [1, 2, 3]),
+            ], idfn=ids)
+
+        assert [str(i.message) for i in rec.list] == [
+            "Raised while trying to determine id of parameter a at position 0."
+            "\nUpdate your code as this will raise an error in pytest-4.0.",
+            "Raised while trying to determine id of parameter b at position 0."
+            "\nUpdate your code as this will raise an error in pytest-4.0.",
+            "Raised while trying to determine id of parameter a at position 1."
+            "\nUpdate your code as this will raise an error in pytest-4.0.",
+            "Raised while trying to determine id of parameter b at position 1."
+            "\nUpdate your code as this will raise an error in pytest-4.0.",
+            "Raised while trying to determine id of parameter a at position 2."
+            "\nUpdate your code as this will raise an error in pytest-4.0.",
+            "Raised while trying to determine id of parameter b at position 2."
+            "\nUpdate your code as this will raise an error in pytest-4.0.",
+        ]
+
+
+    def test_parametrize_ids_exception(self, testdir):
+        """
+        :param testdir: the instance of Testdir class, a temporary
+        test directory.
+        """
+        testdir.makepyfile("""
+                import pytest
+
+                def ids(arg):
+                    raise Exception("bad ids")
+
+                @pytest.mark.parametrize("arg", ["a", "b"], ids=ids)
+                def test_foo(arg):
+                    pass
+            """)
+        result = testdir.runpytest("--collect-only")
+        result.stdout.fnmatch_lines([
+            "<Module 'test_parametrize_ids_exception.py'>",
+            "  <Function 'test_foo[a]'>",
+            "  <Function 'test_foo[b]'>",
+        ])
 
     def test_idmaker_with_ids(self):
         from _pytest.python import idmaker