From 13c545686844f2e09e6e459ec1d291bd8605d3b2 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 7 Aug 2015 07:31:04 +0200 Subject: [PATCH 1/6] Generate parametrize IDs for enum/re/class objects. --- _pytest/python.py | 15 +++++++++++++++ testing/python/metafunc.py | 18 +++++++++++++++--- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/_pytest/python.py b/_pytest/python.py index fe93c938e..c5a479aeb 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -1,4 +1,5 @@ """ Python test discovery, setup and run of test functions. """ +import re import fnmatch import functools import py @@ -976,8 +977,22 @@ def _idval(val, argname, idx, idfn): return s except Exception: pass + + try: + import enum + except ImportError: + # Only available in Python 3.4+ + enum = None + if isinstance(val, (float, int, str, bool, NoneType)): return str(val) + elif isinstance(val, type(re.compile(''))): + # The type of re.compile objects is not exposed in Python. + return val.pattern + elif enum is not None and isinstance(val, enum.Enum): + return str(val) + elif isinstance(val, type) and hasattr(val, '__name__'): + return val.__name__ return str(argname)+str(idx) def _idvalset(idx, valset, argnames, idfn): diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index 7a6d1eebf..90346a5b6 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -1,3 +1,4 @@ +import re import pytest, py from _pytest import python as funcargs @@ -138,6 +139,8 @@ class TestMetafunc: ("three", "three hundred"), (True, False), (None, None), + (re.compile('foo'), re.compile('bar')), + (str, int), (list("six"), [66, 66]), (set([7]), set("seven")), (tuple("eight"), (8, -8, 8)) @@ -147,9 +150,18 @@ class TestMetafunc: "three-three hundred", "True-False", "None-None", - "a5-b5", - "a6-b6", - "a7-b7"] + "foo-bar", + "str-int", + "a7-b7", + "a8-b8", + "a9-b9"] + + def test_idmaker_enum(self): + from _pytest.python import idmaker + enum = pytest.importorskip("enum") + e = enum.Enum("Foo", "one, two") + result = idmaker(("a", "b"), [(e.one, e.two)]) + assert result == ["Foo.one-Foo.two"] @pytest.mark.issue351 def test_idmaker_idfn(self): From 91a29932a6610cf9097d8bfd11aa6ea5b1247e7e Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 7 Aug 2015 07:58:13 +0200 Subject: [PATCH 2/6] Add CHANGELOG entry. --- CHANGELOG | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index bc4c74aa3..83376c44a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,9 @@ 2.8.0.dev (compared to 2.7.X) ----------------------------- +- parametrize now also generates meaningful test IDs for enum, regex and class + objects. + - Add 'warns' to assert that warnings are thrown (like 'raises'). Thanks to Eric Hunsberger for the PR. From 03d8a6c05ddaf754c02a8e317fa235c4b5cc4cc7 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 7 Aug 2015 23:08:22 +0200 Subject: [PATCH 3/6] Update CHANGELOG. --- CHANGELOG | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 83376c44a..ce75fced1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,7 +2,8 @@ ----------------------------- - parametrize now also generates meaningful test IDs for enum, regex and class - objects. + objects (as opposed to class instances). + Thanks to Florian Bruhin for the PR. - Add 'warns' to assert that warnings are thrown (like 'raises'). Thanks to Eric Hunsberger for the PR. From 18125c7d1f31771d33cb0210b156f729b37eb280 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 7 Aug 2015 23:10:22 +0200 Subject: [PATCH 4/6] Clean up type comparisons. --- _pytest/python.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/_pytest/python.py b/_pytest/python.py index c5a479aeb..36f3fb6ba 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -983,15 +983,16 @@ def _idval(val, argname, idx, idfn): except ImportError: # Only available in Python 3.4+ enum = None + # The type of re.compile objects is not exposed in Python. + RegexType = type(re.compile('')) if isinstance(val, (float, int, str, bool, NoneType)): return str(val) - elif isinstance(val, type(re.compile(''))): - # The type of re.compile objects is not exposed in Python. + elif isinstance(val, RegexType): return val.pattern elif enum is not None and isinstance(val, enum.Enum): return str(val) - elif isinstance(val, type) and hasattr(val, '__name__'): + elif inspect.isclass(val) and hasattr(val, '__name__'): return val.__name__ return str(argname)+str(idx) From 84fdba129a12ec9993e19b3a5636803c60848d81 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Sat, 8 Aug 2015 12:57:54 +0200 Subject: [PATCH 5/6] More style changes. --- _pytest/python.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/_pytest/python.py b/_pytest/python.py index 36f3fb6ba..b7c102a69 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -23,6 +23,8 @@ isclass = inspect.isclass callable = py.builtin.callable # used to work around a python2 exception info leak exc_clear = getattr(sys, 'exc_clear', lambda: None) +# The type of re.compile objects is not exposed in Python. +REGEX_TYPE = type(re.compile('')) def filter_traceback(entry): return entry.path != cutdir1 and not entry.path.relto(cutdir2) @@ -983,16 +985,14 @@ def _idval(val, argname, idx, idfn): except ImportError: # Only available in Python 3.4+ enum = None - # The type of re.compile objects is not exposed in Python. - RegexType = type(re.compile('')) if isinstance(val, (float, int, str, bool, NoneType)): return str(val) - elif isinstance(val, RegexType): + elif isinstance(val, REGEX_TYPE): return val.pattern elif enum is not None and isinstance(val, enum.Enum): return str(val) - elif inspect.isclass(val) and hasattr(val, '__name__'): + elif isclass(val) and hasattr(val, '__name__'): return val.__name__ return str(argname)+str(idx) From 4e21d1d77b5fc42cc9e9477190d4b1bf29223d25 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Sat, 8 Aug 2015 15:25:10 +0200 Subject: [PATCH 6/6] Move enum import and adjust comments. --- _pytest/python.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/_pytest/python.py b/_pytest/python.py index b7c102a69..cdd51a810 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -9,6 +9,12 @@ import pytest from _pytest.mark import MarkDecorator, MarkerError from py._code.code import TerminalRepr +try: + import enum +except ImportError: # pragma: no cover + # Only available in Python 3.4+ or as a backport + enum = None + import _pytest import pluggy @@ -980,12 +986,6 @@ def _idval(val, argname, idx, idfn): except Exception: pass - try: - import enum - except ImportError: - # Only available in Python 3.4+ - enum = None - if isinstance(val, (float, int, str, bool, NoneType)): return str(val) elif isinstance(val, REGEX_TYPE):