diff --git a/CHANGELOG b/CHANGELOG
index b1c7e32f4..e6d36aff5 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -17,6 +17,17 @@ Changes between 1.3.0 and 1.3.1
declarative approach with the @py.test.mark.xfail cannot
be used as it would mark all configurations as xfail.
+- improve and refine letter reporting in the progress bar:
+ . pass
+ f failed test
+ s skipped tests (reminder: use for dependency/platform mismatch only)
+ x xfailed test (test that was expected to fail)
+ X xpassed test (test that was expected to fail but passed)
+
+ You can use any combination of 'fsxX' with the '-r' extended
+ reporting option. The xfail/xpass results will show up as
+ skipped tests in the junitxml output.
+
- make py.test.cmdline.main() return the exitstatus
instead of raising (which is still done by py.cmdline.pytest())
and make it so that py.test.cmdline.main() can be called
diff --git a/py/_plugin/pytest_junitxml.py b/py/_plugin/pytest_junitxml.py
index c2673ce6c..94001b74e 100644
--- a/py/_plugin/pytest_junitxml.py
+++ b/py/_plugin/pytest_junitxml.py
@@ -56,10 +56,15 @@ class LogXML(object):
def append_failure(self, report):
self._opentestcase(report)
#msg = str(report.longrepr.reprtraceback.extraline)
- self.appendlog('%s',
- report.longrepr)
+ if "xfail" in report.keywords:
+ self.appendlog(
+ '')
+ self.skipped += 1
+ else:
+ self.appendlog('%s',
+ report.longrepr)
+ self.failed += 1
self._closetestcase()
- self.failed += 1
def _opentestcase_collectfailure(self, report):
node = report.collector
@@ -95,7 +100,12 @@ class LogXML(object):
def append_skipped(self, report):
self._opentestcase(report)
- self.appendlog("")
+ if "xfail" in report.keywords:
+ self.appendlog(
+ '%s',
+ report.keywords['xfail'])
+ else:
+ self.appendlog("")
self._closetestcase()
self.skipped += 1
diff --git a/py/_plugin/pytest_resultlog.py b/py/_plugin/pytest_resultlog.py
index 45225855e..6763ebfd0 100644
--- a/py/_plugin/pytest_resultlog.py
+++ b/py/_plugin/pytest_resultlog.py
@@ -73,7 +73,7 @@ class ResultLog(object):
code = report.shortrepr
if code == 'x':
longrepr = str(report.longrepr)
- elif code == 'P':
+ elif code == 'X':
longrepr = ''
elif report.passed:
longrepr = ""
diff --git a/py/_plugin/pytest_skipping.py b/py/_plugin/pytest_skipping.py
index dedff27ca..01548e5d3 100644
--- a/py/_plugin/pytest_skipping.py
+++ b/py/_plugin/pytest_skipping.py
@@ -225,7 +225,7 @@ def pytest_report_teststatus(report):
if report.skipped:
return "xfailed", "x", "xfail"
elif report.failed:
- return "xpassed", "P", "XPASS"
+ return "xpassed", "X", "XPASS"
# called by the terminalreporter instance/plugin
def pytest_terminal_summary(terminalreporter):
@@ -242,7 +242,7 @@ def pytest_terminal_summary(terminalreporter):
for char in tr.reportchars:
if char == "x":
show_xfailed(terminalreporter, lines)
- elif char == "P":
+ elif char == "X":
show_xpassed(terminalreporter, lines)
elif char == "f":
show_failed(terminalreporter, lines)
diff --git a/testing/plugin/test_pytest_junitxml.py b/testing/plugin/test_pytest_junitxml.py
index 5c0ce082f..6f64bd344 100644
--- a/testing/plugin/test_pytest_junitxml.py
+++ b/testing/plugin/test_pytest_junitxml.py
@@ -25,11 +25,17 @@ class TestPython:
assert 0
def test_skip():
py.test.skip("")
+ @py.test.mark.xfail
+ def test_xfail():
+ assert 0
+ @py.test.mark.xfail
+ def test_xpass():
+ assert 1
""")
result, dom = runandparse(testdir)
assert result.ret
node = dom.getElementsByTagName("testsuite")[0]
- assert_attr(node, errors=0, failures=1, skips=1, tests=2)
+ assert_attr(node, errors=0, failures=1, skips=3, tests=2)
def test_setup_error(self, testdir):
testdir.makepyfile("""
@@ -92,6 +98,43 @@ class TestPython:
assert_attr(fnode, message="test failure")
assert "ValueError" in fnode.toxml()
+ def test_xfailure_function(self, testdir):
+ testdir.makepyfile("""
+ import py
+ def test_xfail():
+ py.test.xfail("42")
+ """)
+ result, dom = runandparse(testdir)
+ assert not result.ret
+ node = dom.getElementsByTagName("testsuite")[0]
+ assert_attr(node, skips=1, tests=0)
+ tnode = node.getElementsByTagName("testcase")[0]
+ assert_attr(tnode,
+ classname="test_xfailure_function.test_xfailure_function",
+ name="test_xfail")
+ fnode = tnode.getElementsByTagName("skipped")[0]
+ assert_attr(fnode, message="expected test failure")
+ #assert "ValueError" in fnode.toxml()
+
+ def test_xfailure_xpass(self, testdir):
+ testdir.makepyfile("""
+ import py
+ @py.test.mark.xfail
+ def test_xpass():
+ pass
+ """)
+ result, dom = runandparse(testdir)
+ #assert result.ret
+ node = dom.getElementsByTagName("testsuite")[0]
+ assert_attr(node, skips=1, tests=0)
+ tnode = node.getElementsByTagName("testcase")[0]
+ assert_attr(tnode,
+ classname="test_xfailure_xpass.test_xfailure_xpass",
+ name="test_xpass")
+ fnode = tnode.getElementsByTagName("skipped")[0]
+ assert_attr(fnode, message="xfail-marked test passes unexpectedly")
+ #assert "ValueError" in fnode.toxml()
+
def test_collect_error(self, testdir):
testdir.makepyfile("syntax error")
result, dom = runandparse(testdir)
diff --git a/testing/plugin/test_pytest_resultlog.py b/testing/plugin/test_pytest_resultlog.py
index 3944114fb..7d41947d2 100644
--- a/testing/plugin/test_pytest_resultlog.py
+++ b/testing/plugin/test_pytest_resultlog.py
@@ -126,7 +126,7 @@ class TestWithFunctionIntegration:
tb = "".join(lines[8:14])
assert tb.find('raise ValueError("XFAIL")') != -1
- assert lines[14].startswith('P ')
+ assert lines[14].startswith('X ')
assert len(lines) == 15
def test_internal_exception(self):
diff --git a/testing/plugin/test_pytest_skipping.py b/testing/plugin/test_pytest_skipping.py
index f38239f45..ead1dd2c3 100644
--- a/testing/plugin/test_pytest_skipping.py
+++ b/testing/plugin/test_pytest_skipping.py
@@ -162,7 +162,7 @@ class TestXFail:
def test_that():
assert 1
""")
- result = testdir.runpytest(p, '-rP')
+ result = testdir.runpytest(p, '-rX')
result.stdout.fnmatch_lines([
"*XPASS*test_that*",
"*1 xpassed*"
@@ -331,7 +331,7 @@ def test_reportchars(testdir):
def test_4():
py.test.skip("four")
""")
- result = testdir.runpytest("-rfxPs")
+ result = testdir.runpytest("-rfxXs")
result.stdout.fnmatch_lines([
"FAIL*test_1*",
"XFAIL*test_2*",