diff --git a/CHANGELOG.rst b/CHANGELOG.rst index dd5c68123..7239cd662 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -13,6 +13,10 @@ New Features Changes ------- +* It is now possible to skip test classes from being collected by setting a + ``__test__`` attribute to ``False`` in the class body (`#2007`_). Thanks + to `@syre`_ for the report and `@lwm`_ for the PR. + * Testcase reports with a ``url`` attribute will now properly write this to junitxml. Thanks `@fushi`_ for the PR (`#1874`_). @@ -71,6 +75,7 @@ Changes * +.. _@syre: https://github.com/syre .. _@dupuy: https://bitbucket.org/dupuy/ .. _@lwm: https://github.com/lwm .. _@adler-j: https://github.com/adler-j @@ -83,6 +88,7 @@ Changes .. _#2038: https://github.com/pytest-dev/pytest/issues/2038 .. _#2078: https://github.com/pytest-dev/pytest/issues/2078 .. _#2082: https://github.com/pytest-dev/pytest/issues/2082 +.. _#2007: https://github.com/pytest-dev/pytest/issues/2007 3.0.4 diff --git a/_pytest/compat.py b/_pytest/compat.py index d5fa7aa84..6bed9e92a 100644 --- a/_pytest/compat.py +++ b/_pytest/compat.py @@ -200,7 +200,7 @@ def safe_getattr(object, name, default): """ Like getattr but return default upon any Exception. Attribute access can potentially fail for 'evil' Python objects. - See issue214 + See issue #214. """ try: return getattr(object, name, default) diff --git a/_pytest/python.py b/_pytest/python.py index 3f01d22ad..0936a6b68 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -503,6 +503,8 @@ def _get_xunit_func(obj, name): class Class(PyCollector): """ Collector for test methods. """ def collect(self): + if not safe_getattr(self.obj, "__test__", True): + return [] if hasinit(self.obj): self.warn("C1", "cannot collect test class %r because it has a " "__init__ constructor" % self.obj.__name__) diff --git a/testing/test_collection.py b/testing/test_collection.py index 9cf4de895..4e44874e1 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -85,6 +85,22 @@ class TestCollector: assert len(nodes) == 1 assert isinstance(nodes[0], pytest.File) + def test_can_skip_class_with_test_attr(self, testdir): + """Assure test class is skipped when using `__test__=False` (See #2007).""" + testdir.makepyfile(""" + class TestFoo(): + __test__ = False + def __init__(self): + pass + def test_foo(): + assert True + """) + result = testdir.runpytest() + result.stdout.fnmatch_lines([ + 'collected 0 items', + '*no tests ran in*', + ]) + class TestCollectFS: def test_ignored_certain_directories(self, testdir): tmpdir = testdir.tmpdir