Skip to content

Commit

Permalink
Merge pull request #1519 from omarkohl/pytest_skip_decorator
Browse files Browse the repository at this point in the history
Raise CollectError if pytest.skip() is called during collection
  • Loading branch information
RonnyPfannschmidt committed Jun 25, 2016
2 parents 35cd12e + b3615ac commit 2af3a7a
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 53 deletions.
21 changes: 21 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
3.0.0.dev1
==========

**Changes**

*

*

*

* Fix (`#607`_): pytest.skip() is no longer allowed at module level to
prevent misleading use as test function decorator. When used at a module
level an error will be raised during collection.
Thanks `@omarkohl`_ for the complete PR (`#1519`_).

*

.. _#607: https://github.com/pytest-dev/pytest/issues/607
.. _#1519: https://github.com/pytest-dev/pytest/pull/1519

2.10.0.dev1
===========

Expand Down
6 changes: 6 additions & 0 deletions _pytest/python.py
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,12 @@ def _importtestmodule(self):
"Make sure your test modules/packages have valid Python names."
% (self.fspath, exc or exc_class)
)
except _pytest.runner.Skipped:
raise self.CollectError(
"Using @pytest.skip outside a test (e.g. as a test function "
"decorator) is not allowed. Use @pytest.mark.skip or "
"@pytest.mark.skipif instead."
)
#print "imported test module", mod
self.config.pluginmanager.consider_module(mod)
return mod
Expand Down
59 changes: 41 additions & 18 deletions testing/test_junitxml.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-

from xml.dom import minidom
from _pytest.main import EXIT_NOTESTSCOLLECTED
import py
import sys
import os
Expand Down Expand Up @@ -158,6 +157,47 @@ def test_skip():
snode = tnode.find_first_by_tag("skipped")
snode.assert_attr(type="pytest.skip", message="hello23", )

def test_mark_skip_contains_name_reason(self, testdir):
testdir.makepyfile("""
import pytest
@pytest.mark.skip(reason="hello24")
def test_skip():
assert True
""")
result, dom = runandparse(testdir)
assert result.ret == 0
node = dom.find_first_by_tag("testsuite")
node.assert_attr(skips=1)
tnode = node.find_first_by_tag("testcase")
tnode.assert_attr(
file="test_mark_skip_contains_name_reason.py",
line="1",
classname="test_mark_skip_contains_name_reason",
name="test_skip")
snode = tnode.find_first_by_tag("skipped")
snode.assert_attr(type="pytest.skip", message="hello24", )

def test_mark_skipif_contains_name_reason(self, testdir):
testdir.makepyfile("""
import pytest
GLOBAL_CONDITION = True
@pytest.mark.skipif(GLOBAL_CONDITION, reason="hello25")
def test_skip():
assert True
""")
result, dom = runandparse(testdir)
assert result.ret == 0
node = dom.find_first_by_tag("testsuite")
node.assert_attr(skips=1)
tnode = node.find_first_by_tag("testcase")
tnode.assert_attr(
file="test_mark_skipif_contains_name_reason.py",
line="2",
classname="test_mark_skipif_contains_name_reason",
name="test_skip")
snode = tnode.find_first_by_tag("skipped")
snode.assert_attr(type="pytest.skip", message="hello25", )

def test_classname_instance(self, testdir):
testdir.makepyfile("""
class TestClass:
Expand Down Expand Up @@ -351,23 +391,6 @@ def test_collect_error(self, testdir):
fnode.assert_attr(message="collection failure")
assert "SyntaxError" in fnode.toxml()

def test_collect_skipped(self, testdir):
testdir.makepyfile("import pytest; pytest.skip('xyz')")
result, dom = runandparse(testdir)
assert result.ret == EXIT_NOTESTSCOLLECTED
node = dom.find_first_by_tag("testsuite")
node.assert_attr(skips=1, tests=1)
tnode = node.find_first_by_tag("testcase")
tnode.assert_attr(
file="test_collect_skipped.py",
name="test_collect_skipped")

# pytest doesn't give us a line here.
assert tnode["line"] is None

fnode = tnode.find_first_by_tag("skipped")
fnode.assert_attr(message="collection skipped")

def test_unicode(self, testdir):
value = 'hx\xc4\x85\xc4\x87\n'
testdir.makepyfile("""
Expand Down
9 changes: 0 additions & 9 deletions testing/test_resultlog.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,19 +83,10 @@ def getresultlog(self, testdir, arg):

def test_collection_report(self, testdir):
ok = testdir.makepyfile(test_collection_ok="")
skip = testdir.makepyfile(test_collection_skip=
"import pytest ; pytest.skip('hello')")
fail = testdir.makepyfile(test_collection_fail="XXX")
lines = self.getresultlog(testdir, ok)
assert not lines

lines = self.getresultlog(testdir, skip)
assert len(lines) == 2
assert lines[0].startswith("S ")
assert lines[0].endswith("test_collection_skip.py")
assert lines[1].startswith(" ")
assert lines[1].endswith("test_collection_skip.py:1: Skipped: hello")

lines = self.getresultlog(testdir, fail)
assert lines
assert lines[0].startswith("F ")
Expand Down
12 changes: 0 additions & 12 deletions testing/test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,18 +365,6 @@ class TestClass:
assert res[0].name == "test_func1"
assert res[1].name == "TestClass"

def test_skip_at_module_scope(self, testdir):
col = testdir.getmodulecol("""
import pytest
pytest.skip("hello")
def test_func():
pass
""")
rep = main.collect_one_node(col)
assert not rep.failed
assert not rep.passed
assert rep.skipped


reporttypes = [
runner.BaseReport,
Expand Down
8 changes: 1 addition & 7 deletions testing/test_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,6 @@ def test_method_one(self):
class TestY(TestX):
pass
""",
test_two="""
import pytest
pytest.skip('xxx')
""",
test_three="xxxdsadsadsadsa",
__init__=""
)
Expand All @@ -189,11 +185,9 @@ class TestY(TestX):
started = reprec.getcalls("pytest_collectstart")
finished = reprec.getreports("pytest_collectreport")
assert len(started) == len(finished)
assert len(started) == 8 # XXX extra TopCollector
assert len(started) == 7 # XXX extra TopCollector
colfail = [x for x in finished if x.failed]
colskipped = [x for x in finished if x.skipped]
assert len(colfail) == 1
assert len(colskipped) == 1

def test_minus_x_import_error(self, testdir):
testdir.makepyfile(__init__="")
Expand Down
22 changes: 17 additions & 5 deletions testing/test_skipping.py
Original file line number Diff line number Diff line change
Expand Up @@ -682,10 +682,6 @@ class TestClass:
def test_method(self):
doskip()
""",
test_two = """
from conftest import doskip
doskip()
""",
conftest = """
import pytest
def doskip():
Expand All @@ -694,7 +690,7 @@ def doskip():
)
result = testdir.runpytest('--report=skipped')
result.stdout.fnmatch_lines([
"*SKIP*3*conftest.py:3: test",
"*SKIP*2*conftest.py:3: test",
])
assert result.ret == 0

Expand Down Expand Up @@ -941,3 +937,19 @@ def pytest_collect_file(path, parent):
assert not failed
xfailed = [r for r in skipped if hasattr(r, 'wasxfail')]
assert xfailed


def test_module_level_skip_error(testdir):
"""
Verify that using pytest.skip at module level causes a collection error
"""
testdir.makepyfile("""
import pytest
@pytest.skip
def test_func():
assert True
""")
result = testdir.runpytest()
result.stdout.fnmatch_lines(
"*Using @pytest.skip outside a test * is not allowed*"
)
3 changes: 1 addition & 2 deletions testing/test_terminal.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,7 @@ def test_collectonly_skipped_module(self, testdir):
""")
result = testdir.runpytest("--collect-only", "-rs")
result.stdout.fnmatch_lines([
"SKIP*hello*",
"*1 skip*",
"*ERROR collecting*",
])

def test_collectonly_failed_module(self, testdir):
Expand Down

0 comments on commit 2af3a7a

Please sign in to comment.