# coding=utf8 from __future__ import absolute_import from __future__ import division from __future__ import print_function import sys import pytest from _pytest.runner import runtestprotocol from _pytest.skipping import MarkEvaluator from _pytest.skipping import pytest_runtest_setup class TestEvaluator(object): def test_no_marker(self, testdir): item = testdir.getitem("def test_func(): pass") evalskipif = MarkEvaluator(item, "skipif") assert not evalskipif assert not evalskipif.istrue() def test_marked_no_args(self, testdir): item = testdir.getitem( """ import pytest @pytest.mark.xyz def test_func(): pass """ ) ev = MarkEvaluator(item, "xyz") assert ev assert ev.istrue() expl = ev.getexplanation() assert expl == "" assert not ev.get("run", False) def test_marked_one_arg(self, testdir): item = testdir.getitem( """ import pytest @pytest.mark.xyz("hasattr(os, 'sep')") def test_func(): pass """ ) ev = MarkEvaluator(item, "xyz") assert ev assert ev.istrue() expl = ev.getexplanation() assert expl == "condition: hasattr(os, 'sep')" @pytest.mark.skipif("sys.version_info[0] >= 3") def test_marked_one_arg_unicode(self, testdir): item = testdir.getitem( """ import pytest @pytest.mark.xyz(u"hasattr(os, 'sep')") def test_func(): pass """ ) ev = MarkEvaluator(item, "xyz") assert ev assert ev.istrue() expl = ev.getexplanation() assert expl == "condition: hasattr(os, 'sep')" def test_marked_one_arg_with_reason(self, testdir): item = testdir.getitem( """ import pytest @pytest.mark.xyz("hasattr(os, 'sep')", attr=2, reason="hello world") def test_func(): pass """ ) ev = MarkEvaluator(item, "xyz") assert ev assert ev.istrue() expl = ev.getexplanation() assert expl == "hello world" assert ev.get("attr") == 2 def test_marked_one_arg_twice(self, testdir): lines = [ """@pytest.mark.skipif("not hasattr(os, 'murks')")""", """@pytest.mark.skipif("hasattr(os, 'murks')")""", ] for i in range(0, 2): item = testdir.getitem( """ import pytest %s %s def test_func(): pass """ % (lines[i], lines[(i + 1) % 2]) ) ev = MarkEvaluator(item, "skipif") assert ev assert ev.istrue() expl = ev.getexplanation() assert expl == "condition: not hasattr(os, 'murks')" def test_marked_one_arg_twice2(self, testdir): item = testdir.getitem( """ import pytest @pytest.mark.skipif("hasattr(os, 'murks')") @pytest.mark.skipif("not hasattr(os, 'murks')") def test_func(): pass """ ) ev = MarkEvaluator(item, "skipif") assert ev assert ev.istrue() expl = ev.getexplanation() assert expl == "condition: not hasattr(os, 'murks')" def test_marked_skip_with_not_string(self, testdir): item = testdir.getitem( """ import pytest @pytest.mark.skipif(False) def test_func(): pass """ ) ev = MarkEvaluator(item, "skipif") exc = pytest.raises(pytest.fail.Exception, ev.istrue) assert ( """Failed: you need to specify reason=STRING when using booleans as conditions.""" in exc.value.msg ) def test_skipif_class(self, testdir): item, = testdir.getitems( """ import pytest class TestClass(object): pytestmark = pytest.mark.skipif("config._hackxyz") def test_func(self): pass """ ) item.config._hackxyz = 3 ev = MarkEvaluator(item, "skipif") assert ev.istrue() expl = ev.getexplanation() assert expl == "condition: config._hackxyz" class TestXFail(object): @pytest.mark.parametrize("strict", [True, False]) def test_xfail_simple(self, testdir, strict): item = testdir.getitem( """ import pytest @pytest.mark.xfail(strict=%s) def test_func(): assert 0 """ % strict ) reports = runtestprotocol(item, log=False) assert len(reports) == 3 callreport = reports[1] assert callreport.skipped assert callreport.wasxfail == "" def test_xfail_xpassed(self, testdir): item = testdir.getitem( """ import pytest @pytest.mark.xfail(reason="this is an xfail") def test_func(): assert 1 """ ) reports = runtestprotocol(item, log=False) assert len(reports) == 3 callreport = reports[1] assert callreport.passed assert callreport.wasxfail == "this is an xfail" def test_xfail_using_platform(self, testdir): """ Verify that platform can be used with xfail statements. """ item = testdir.getitem( """ import pytest @pytest.mark.xfail("platform.platform() == platform.platform()") def test_func(): assert 0 """ ) reports = runtestprotocol(item, log=False) assert len(reports) == 3 callreport = reports[1] assert callreport.wasxfail def test_xfail_xpassed_strict(self, testdir): item = testdir.getitem( """ import pytest @pytest.mark.xfail(strict=True, reason="nope") def test_func(): assert 1 """ ) reports = runtestprotocol(item, log=False) assert len(reports) == 3 callreport = reports[1] assert callreport.failed assert callreport.longrepr == "[XPASS(strict)] nope" assert not hasattr(callreport, "wasxfail") def test_xfail_run_anyway(self, testdir): testdir.makepyfile( """ import pytest @pytest.mark.xfail def test_func(): assert 0 def test_func2(): pytest.xfail("hello") """ ) result = testdir.runpytest("--runxfail") result.stdout.fnmatch_lines( ["*def test_func():*", "*assert 0*", "*1 failed*1 pass*"] ) def test_xfail_evalfalse_but_fails(self, testdir): item = testdir.getitem( """ import pytest @pytest.mark.xfail('False') def test_func(): assert 0 """ ) reports = runtestprotocol(item, log=False) callreport = reports[1] assert callreport.failed assert not hasattr(callreport, "wasxfail") assert "xfail" in callreport.keywords def test_xfail_not_report_default(self, testdir): p = testdir.makepyfile( test_one=""" import pytest @pytest.mark.xfail def test_this(): assert 0 """ ) testdir.runpytest(p, "-v") # result.stdout.fnmatch_lines([ # "*HINT*use*-r*" # ]) def test_xfail_not_run_xfail_reporting(self, testdir): p = testdir.makepyfile( test_one=""" import pytest @pytest.mark.xfail(run=False, reason="noway") def test_this(): assert 0 @pytest.mark.xfail("True", run=False) def test_this_true(): assert 0 @pytest.mark.xfail("False", run=False, reason="huh") def test_this_false(): assert 1 """ ) result = testdir.runpytest(p, "-rx") result.stdout.fnmatch_lines( [ "*test_one*test_this*", "*NOTRUN*noway", "*test_one*test_this_true*", "*NOTRUN*condition:*True*", "*1 passed*", ] ) def test_xfail_not_run_no_setup_run(self, testdir): p = testdir.makepyfile( test_one=""" import pytest @pytest.mark.xfail(run=False, reason="hello") def test_this(): assert 0 def setup_module(mod): raise ValueError(42) """ ) result = testdir.runpytest(p, "-rx") result.stdout.fnmatch_lines( ["*test_one*test_this*", "*NOTRUN*hello", "*1 xfailed*"] ) def test_xfail_xpass(self, testdir): p = testdir.makepyfile( test_one=""" import pytest @pytest.mark.xfail def test_that(): assert 1 """ ) result = testdir.runpytest(p, "-rX") result.stdout.fnmatch_lines(["*XPASS*test_that*", "*1 xpassed*"]) assert result.ret == 0 def test_xfail_imperative(self, testdir): p = testdir.makepyfile( """ import pytest def test_this(): pytest.xfail("hello") """ ) result = testdir.runpytest(p) result.stdout.fnmatch_lines(["*1 xfailed*"]) result = testdir.runpytest(p, "-rx") result.stdout.fnmatch_lines(["*XFAIL*test_this*", "*reason:*hello*"]) result = testdir.runpytest(p, "--runxfail") result.stdout.fnmatch_lines(["*1 pass*"]) def test_xfail_imperative_in_setup_function(self, testdir): p = testdir.makepyfile( """ import pytest def setup_function(function): pytest.xfail("hello") def test_this(): assert 0 """ ) result = testdir.runpytest(p) result.stdout.fnmatch_lines(["*1 xfailed*"]) result = testdir.runpytest(p, "-rx") result.stdout.fnmatch_lines(["*XFAIL*test_this*", "*reason:*hello*"]) result = testdir.runpytest(p, "--runxfail") result.stdout.fnmatch_lines( """ *def test_this* *1 fail* """ ) def xtest_dynamic_xfail_set_during_setup(self, testdir): p = testdir.makepyfile( """ import pytest def setup_function(function): pytest.mark.xfail(function) def test_this(): assert 0 def test_that(): assert 1 """ ) result = testdir.runpytest(p, "-rxX") result.stdout.fnmatch_lines(["*XFAIL*test_this*", "*XPASS*test_that*"]) def test_dynamic_xfail_no_run(self, testdir): p = testdir.makepyfile( """ import pytest @pytest.fixture def arg(request): request.applymarker(pytest.mark.xfail(run=False)) def test_this(arg): assert 0 """ ) result = testdir.runpytest(p, "-rxX") result.stdout.fnmatch_lines(["*XFAIL*test_this*", "*NOTRUN*"]) def test_dynamic_xfail_set_during_funcarg_setup(self, testdir): p = testdir.makepyfile( """ import pytest @pytest.fixture def arg(request): request.applymarker(pytest.mark.xfail) def test_this2(arg): assert 0 """ ) result = testdir.runpytest(p) result.stdout.fnmatch_lines(["*1 xfailed*"]) @pytest.mark.parametrize( "expected, actual, matchline", [ ("TypeError", "TypeError", "*1 xfailed*"), ("(AttributeError, TypeError)", "TypeError", "*1 xfailed*"), ("TypeError", "IndexError", "*1 failed*"), ("(AttributeError, TypeError)", "IndexError", "*1 failed*"), ], ) def test_xfail_raises(self, expected, actual, matchline, testdir): p = testdir.makepyfile( """ import pytest @pytest.mark.xfail(raises=%s) def test_raises(): raise %s() """ % (expected, actual) ) result = testdir.runpytest(p) result.stdout.fnmatch_lines([matchline]) def test_strict_sanity(self, testdir): """sanity check for xfail(strict=True): a failing test should behave exactly like a normal xfail. """ p = testdir.makepyfile( """ import pytest @pytest.mark.xfail(reason='unsupported feature', strict=True) def test_foo(): assert 0 """ ) result = testdir.runpytest(p, "-rxX") result.stdout.fnmatch_lines(["*XFAIL*", "*unsupported feature*"]) assert result.ret == 0 @pytest.mark.parametrize("strict", [True, False]) def test_strict_xfail(self, testdir, strict): p = testdir.makepyfile( """ import pytest @pytest.mark.xfail(reason='unsupported feature', strict=%s) def test_foo(): with open('foo_executed', 'w'): pass # make sure test executes """ % strict ) result = testdir.runpytest(p, "-rxX") if strict: result.stdout.fnmatch_lines( ["*test_foo*", "*XPASS(strict)*unsupported feature*"] ) else: result.stdout.fnmatch_lines( [ "*test_strict_xfail*", "XPASS test_strict_xfail.py::test_foo unsupported feature", ] ) assert result.ret == (1 if strict else 0) assert testdir.tmpdir.join("foo_executed").isfile() @pytest.mark.parametrize("strict", [True, False]) def test_strict_xfail_condition(self, testdir, strict): p = testdir.makepyfile( """ import pytest @pytest.mark.xfail(False, reason='unsupported feature', strict=%s) def test_foo(): pass """ % strict ) result = testdir.runpytest(p, "-rxX") result.stdout.fnmatch_lines(["*1 passed*"]) assert result.ret == 0 @pytest.mark.parametrize("strict", [True, False]) def test_xfail_condition_keyword(self, testdir, strict): p = testdir.makepyfile( """ import pytest @pytest.mark.xfail(condition=False, reason='unsupported feature', strict=%s) def test_foo(): pass """ % strict ) result = testdir.runpytest(p, "-rxX") result.stdout.fnmatch_lines(["*1 passed*"]) assert result.ret == 0 @pytest.mark.parametrize("strict_val", ["true", "false"]) def test_strict_xfail_default_from_file(self, testdir, strict_val): testdir.makeini( """ [pytest] xfail_strict = %s """ % strict_val ) p = testdir.makepyfile( """ import pytest @pytest.mark.xfail(reason='unsupported feature') def test_foo(): pass """ ) result = testdir.runpytest(p, "-rxX") strict = strict_val == "true" result.stdout.fnmatch_lines(["*1 failed*" if strict else "*1 xpassed*"]) assert result.ret == (1 if strict else 0) class TestXFailwithSetupTeardown(object): def test_failing_setup_issue9(self, testdir): testdir.makepyfile( """ import pytest def setup_function(func): assert 0 @pytest.mark.xfail def test_func(): pass """ ) result = testdir.runpytest() result.stdout.fnmatch_lines(["*1 xfail*"]) def test_failing_teardown_issue9(self, testdir): testdir.makepyfile( """ import pytest def teardown_function(func): assert 0 @pytest.mark.xfail def test_func(): pass """ ) result = testdir.runpytest() result.stdout.fnmatch_lines(["*1 xfail*"]) class TestSkip(object): def test_skip_class(self, testdir): testdir.makepyfile( """ import pytest @pytest.mark.skip class TestSomething(object): def test_foo(self): pass def test_bar(self): pass def test_baz(): pass """ ) rec = testdir.inline_run() rec.assertoutcome(skipped=2, passed=1) def test_skips_on_false_string(self, testdir): testdir.makepyfile( """ import pytest @pytest.mark.skip('False') def test_foo(): pass """ ) rec = testdir.inline_run() rec.assertoutcome(skipped=1) def test_arg_as_reason(self, testdir): testdir.makepyfile( """ import pytest @pytest.mark.skip('testing stuff') def test_bar(): pass """ ) result = testdir.runpytest("-rs") result.stdout.fnmatch_lines(["*testing stuff*", "*1 skipped*"]) def test_skip_no_reason(self, testdir): testdir.makepyfile( """ import pytest @pytest.mark.skip def test_foo(): pass """ ) result = testdir.runpytest("-rs") result.stdout.fnmatch_lines(["*unconditional skip*", "*1 skipped*"]) def test_skip_with_reason(self, testdir): testdir.makepyfile( """ import pytest @pytest.mark.skip(reason="for lolz") def test_bar(): pass """ ) result = testdir.runpytest("-rs") result.stdout.fnmatch_lines(["*for lolz*", "*1 skipped*"]) def test_only_skips_marked_test(self, testdir): testdir.makepyfile( """ import pytest @pytest.mark.skip def test_foo(): pass @pytest.mark.skip(reason="nothing in particular") def test_bar(): pass def test_baz(): assert True """ ) result = testdir.runpytest("-rs") result.stdout.fnmatch_lines(["*nothing in particular*", "*1 passed*2 skipped*"]) def test_strict_and_skip(self, testdir): testdir.makepyfile( """ import pytest @pytest.mark.skip def test_hello(): pass """ ) result = testdir.runpytest("-rs") result.stdout.fnmatch_lines(["*unconditional skip*", "*1 skipped*"]) class TestSkipif(object): def test_skipif_conditional(self, testdir): item = testdir.getitem( """ import pytest @pytest.mark.skipif("hasattr(os, 'sep')") def test_func(): pass """ ) x = pytest.raises(pytest.skip.Exception, lambda: pytest_runtest_setup(item)) assert x.value.msg == "condition: hasattr(os, 'sep')" @pytest.mark.parametrize( "params", ["\"hasattr(sys, 'platform')\"", 'True, reason="invalid platform"'] ) def test_skipif_reporting(self, testdir, params): p = testdir.makepyfile( test_foo=""" import pytest @pytest.mark.skipif(%(params)s) def test_that(): assert 0 """ % dict(params=params) ) result = testdir.runpytest(p, "-s", "-rs") result.stdout.fnmatch_lines(["*SKIP*1*test_foo.py*platform*", "*1 skipped*"]) assert result.ret == 0 def test_skipif_using_platform(self, testdir): item = testdir.getitem( """ import pytest @pytest.mark.skipif("platform.platform() == platform.platform()") def test_func(): pass """ ) pytest.raises(pytest.skip.Exception, lambda: pytest_runtest_setup(item)) @pytest.mark.parametrize( "marker, msg1, msg2", [("skipif", "SKIP", "skipped"), ("xfail", "XPASS", "xpassed")], ) def test_skipif_reporting_multiple(self, testdir, marker, msg1, msg2): testdir.makepyfile( test_foo=""" import pytest @pytest.mark.{marker}(False, reason='first_condition') @pytest.mark.{marker}(True, reason='second_condition') def test_foobar(): assert 1 """.format( marker=marker ) ) result = testdir.runpytest("-s", "-rsxX") result.stdout.fnmatch_lines( [ "*{msg1}*test_foo.py*second_condition*".format(msg1=msg1), "*1 {msg2}*".format(msg2=msg2), ] ) assert result.ret == 0 def test_skip_not_report_default(testdir): p = testdir.makepyfile( test_one=""" import pytest def test_this(): pytest.skip("hello") """ ) result = testdir.runpytest(p, "-v") result.stdout.fnmatch_lines( [ # "*HINT*use*-r*", "*1 skipped*" ] ) def test_skipif_class(testdir): p = testdir.makepyfile( """ import pytest class TestClass(object): pytestmark = pytest.mark.skipif("True") def test_that(self): assert 0 def test_though(self): assert 0 """ ) result = testdir.runpytest(p) result.stdout.fnmatch_lines(["*2 skipped*"]) def test_skipped_reasons_functional(testdir): testdir.makepyfile( test_one=""" from conftest import doskip def setup_function(func): doskip() def test_func(): pass class TestClass(object): def test_method(self): doskip() """, conftest=""" import pytest def doskip(): pytest.skip('test') """, ) result = testdir.runpytest("-rs") result.stdout.fnmatch_lines(["*SKIP*2*conftest.py:4: test"]) assert result.ret == 0 def test_skipped_folding(testdir): testdir.makepyfile( test_one=""" import pytest pytestmark = pytest.mark.skip("Folding") def setup_function(func): pass def test_func(): pass class TestClass(object): def test_method(self): pass """ ) result = testdir.runpytest("-rs") result.stdout.fnmatch_lines(["*SKIP*2*test_one.py: Folding"]) assert result.ret == 0 def test_reportchars(testdir): testdir.makepyfile( """ import pytest def test_1(): assert 0 @pytest.mark.xfail def test_2(): assert 0 @pytest.mark.xfail def test_3(): pass def test_4(): pytest.skip("four") """ ) result = testdir.runpytest("-rfxXs") result.stdout.fnmatch_lines( ["FAIL*test_1*", "XFAIL*test_2*", "XPASS*test_3*", "SKIP*four*"] ) def test_reportchars_error(testdir): testdir.makepyfile( conftest=""" def pytest_runtest_teardown(): assert 0 """, test_simple=""" def test_foo(): pass """, ) result = testdir.runpytest("-rE") result.stdout.fnmatch_lines(["ERROR*test_foo*"]) def test_reportchars_all(testdir): testdir.makepyfile( """ import pytest def test_1(): assert 0 @pytest.mark.xfail def test_2(): assert 0 @pytest.mark.xfail def test_3(): pass def test_4(): pytest.skip("four") @pytest.fixture def fail(): assert 0 def test_5(fail): pass """ ) result = testdir.runpytest("-ra") result.stdout.fnmatch_lines( [ "SKIP*four*", "XFAIL*test_2*", "XPASS*test_3*", "ERROR*test_5*", "FAIL*test_1*", ] ) def test_reportchars_all_error(testdir): testdir.makepyfile( conftest=""" def pytest_runtest_teardown(): assert 0 """, test_simple=""" def test_foo(): pass """, ) result = testdir.runpytest("-ra") result.stdout.fnmatch_lines(["ERROR*test_foo*"]) def test_errors_in_xfail_skip_expressions(testdir): testdir.makepyfile( """ import pytest @pytest.mark.skipif("asd") def test_nameerror(): pass @pytest.mark.xfail("syntax error") def test_syntax(): pass def test_func(): pass """ ) result = testdir.runpytest() markline = " ^" if sys.platform.startswith("java"): # XXX report this to java markline = "*" + markline[8:] elif hasattr(sys, "pypy_version_info") and sys.pypy_version_info < (6,): markline = markline[5:] elif sys.version_info >= (3, 8) or hasattr(sys, "pypy_version_info"): markline = markline[4:] result.stdout.fnmatch_lines( [ "*ERROR*test_nameerror*", "*evaluating*skipif*expression*", "*asd*", "*ERROR*test_syntax*", "*evaluating*xfail*expression*", " syntax error", markline, "SyntaxError: invalid syntax", "*1 pass*2 error*", ] ) def test_xfail_skipif_with_globals(testdir): testdir.makepyfile( """ import pytest x = 3 @pytest.mark.skipif("x == 3") def test_skip1(): pass @pytest.mark.xfail("x == 3") def test_boolean(): assert 0 """ ) result = testdir.runpytest("-rsx") result.stdout.fnmatch_lines(["*SKIP*x == 3*", "*XFAIL*test_boolean*", "*x == 3*"]) def test_direct_gives_error(testdir): testdir.makepyfile( """ import pytest @pytest.mark.skipif(True) def test_skip1(): pass """ ) result = testdir.runpytest() result.stdout.fnmatch_lines(["*1 error*"]) def test_default_markers(testdir): result = testdir.runpytest("--markers") result.stdout.fnmatch_lines( [ "*skipif(*condition)*skip*", "*xfail(*condition, reason=None, run=True, raises=None, strict=False)*expected failure*", ] ) def test_xfail_test_setup_exception(testdir): testdir.makeconftest( """ def pytest_runtest_setup(): 0 / 0 """ ) p = testdir.makepyfile( """ import pytest @pytest.mark.xfail def test_func(): assert 0 """ ) result = testdir.runpytest(p) assert result.ret == 0 assert "xfailed" in result.stdout.str() assert "xpassed" not in result.stdout.str() def test_imperativeskip_on_xfail_test(testdir): testdir.makepyfile( """ import pytest @pytest.mark.xfail def test_that_fails(): assert 0 @pytest.mark.skipif("True") def test_hello(): pass """ ) testdir.makeconftest( """ import pytest def pytest_runtest_setup(item): pytest.skip("abc") """ ) result = testdir.runpytest("-rsxX") result.stdout.fnmatch_lines_random( """ *SKIP*abc* *SKIP*condition: True* *2 skipped* """ ) class TestBooleanCondition(object): def test_skipif(self, testdir): testdir.makepyfile( """ import pytest @pytest.mark.skipif(True, reason="True123") def test_func1(): pass @pytest.mark.skipif(False, reason="True123") def test_func2(): pass """ ) result = testdir.runpytest() result.stdout.fnmatch_lines( """ *1 passed*1 skipped* """ ) def test_skipif_noreason(self, testdir): testdir.makepyfile( """ import pytest @pytest.mark.skipif(True) def test_func(): pass """ ) result = testdir.runpytest("-rs") result.stdout.fnmatch_lines( """ *1 error* """ ) def test_xfail(self, testdir): testdir.makepyfile( """ import pytest @pytest.mark.xfail(True, reason="True123") def test_func(): assert 0 """ ) result = testdir.runpytest("-rxs") result.stdout.fnmatch_lines( """ *XFAIL* *True123* *1 xfail* """ ) def test_xfail_item(testdir): # Ensure pytest.xfail works with non-Python Item testdir.makeconftest( """ import pytest class MyItem(pytest.Item): nodeid = 'foo' def runtest(self): pytest.xfail("Expected Failure") def pytest_collect_file(path, parent): return MyItem("foo", parent) """ ) result = testdir.inline_run() passed, skipped, failed = result.listoutcomes() 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 of a test is not allowed*"] ) def test_module_level_skip_with_allow_module_level(testdir): """ Verify that using pytest.skip(allow_module_level=True) is allowed """ testdir.makepyfile( """ import pytest pytest.skip("skip_module_level", allow_module_level=True) def test_func(): assert 0 """ ) result = testdir.runpytest("-rxs") result.stdout.fnmatch_lines(["*SKIP*skip_module_level"]) def test_invalid_skip_keyword_parameter(testdir): """ Verify that using pytest.skip() with unknown parameter raises an error """ testdir.makepyfile( """ import pytest pytest.skip("skip_module_level", unknown=1) def test_func(): assert 0 """ ) result = testdir.runpytest() result.stdout.fnmatch_lines(["*TypeError:*['unknown']*"]) def test_mark_xfail_item(testdir): # Ensure pytest.mark.xfail works with non-Python Item testdir.makeconftest( """ import pytest class MyItem(pytest.Item): nodeid = 'foo' def setup(self): marker = pytest.mark.xfail(True, reason="Expected failure") self.add_marker(marker) def runtest(self): assert False def pytest_collect_file(path, parent): return MyItem("foo", parent) """ ) result = testdir.inline_run() passed, skipped, failed = result.listoutcomes() assert not failed xfailed = [r for r in skipped if hasattr(r, "wasxfail")] assert xfailed def test_summary_list_after_errors(testdir): """Ensure the list of errors/fails/xfails/skips appears after tracebacks in terminal reporting.""" testdir.makepyfile( """ import pytest def test_fail(): assert 0 """ ) result = testdir.runpytest("-ra") result.stdout.fnmatch_lines( [ "=* FAILURES *=", "*= short test summary info =*", "FAILED test_summary_list_after_errors.py::test_fail - assert 0", ] )