parent
f5fab2bfa1
commit
ba76080b59
|
@ -0,0 +1,2 @@
|
||||||
|
XML files of the ``xunit2`` family are now validated against the schema by pytest's own test suite
|
||||||
|
to avoid future regressions.
|
5
setup.py
5
setup.py
|
@ -21,7 +21,6 @@ def main():
|
||||||
use_scm_version={"write_to": "src/_pytest/_version.py"},
|
use_scm_version={"write_to": "src/_pytest/_version.py"},
|
||||||
setup_requires=["setuptools-scm", "setuptools>=40.0"],
|
setup_requires=["setuptools-scm", "setuptools>=40.0"],
|
||||||
package_dir={"": "src"},
|
package_dir={"": "src"},
|
||||||
# fmt: off
|
|
||||||
extras_require={
|
extras_require={
|
||||||
"testing": [
|
"testing": [
|
||||||
"argcomplete",
|
"argcomplete",
|
||||||
|
@ -29,9 +28,9 @@ def main():
|
||||||
"mock",
|
"mock",
|
||||||
"nose",
|
"nose",
|
||||||
"requests",
|
"requests",
|
||||||
],
|
"xmlschema",
|
||||||
|
]
|
||||||
},
|
},
|
||||||
# fmt: on
|
|
||||||
install_requires=INSTALL_REQUIRES,
|
install_requires=INSTALL_REQUIRES,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,147 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!--
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014, Gregory Boissinot
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
-->
|
||||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||||
|
<xs:simpleType name="SUREFIRE_TIME">
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:pattern value="(([0-9]{0,3},)*[0-9]{3}|[0-9]{0,3})*(\.[0-9]{0,3})?"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:complexType name="rerunType" mixed="true"> <!-- mixed (XML contains text) to be compatible with version previous than 2.22.1 -->
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="stackTrace" type="xs:string" minOccurs="0" /> <!-- optional to be compatible with version previous than 2.22.1 -->
|
||||||
|
<xs:element name="system-out" type="xs:string" minOccurs="0" />
|
||||||
|
<xs:element name="system-err" type="xs:string" minOccurs="0" />
|
||||||
|
</xs:sequence>
|
||||||
|
<xs:attribute name="message" type="xs:string" />
|
||||||
|
<xs:attribute name="type" type="xs:string" use="required" />
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
|
<xs:element name="failure">
|
||||||
|
<xs:complexType mixed="true">
|
||||||
|
<xs:attribute name="type" type="xs:string"/>
|
||||||
|
<xs:attribute name="message" type="xs:string"/>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
|
||||||
|
<xs:element name="error">
|
||||||
|
<xs:complexType mixed="true">
|
||||||
|
<xs:attribute name="type" type="xs:string"/>
|
||||||
|
<xs:attribute name="message" type="xs:string"/>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
|
||||||
|
<xs:element name="skipped">
|
||||||
|
<xs:complexType mixed="true">
|
||||||
|
<xs:attribute name="type" type="xs:string"/>
|
||||||
|
<xs:attribute name="message" type="xs:string"/>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
|
||||||
|
<xs:element name="properties">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element ref="property" minOccurs="0" maxOccurs="unbounded"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
|
||||||
|
<xs:element name="property">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:attribute name="name" type="xs:string" use="required"/>
|
||||||
|
<xs:attribute name="value" type="xs:string" use="required"/>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
|
||||||
|
<xs:element name="system-err" type="xs:string"/>
|
||||||
|
<xs:element name="system-out" type="xs:string"/>
|
||||||
|
<xs:element name="rerunFailure" type="rerunType"/>
|
||||||
|
<xs:element name="rerunError" type="rerunType"/>
|
||||||
|
<xs:element name="flakyFailure" type="rerunType"/>
|
||||||
|
<xs:element name="flakyError" type="rerunType"/>
|
||||||
|
|
||||||
|
<xs:element name="testcase">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||||
|
<xs:element ref="skipped"/>
|
||||||
|
<xs:element ref="error"/>
|
||||||
|
<xs:element ref="failure"/>
|
||||||
|
<xs:element ref="rerunFailure" minOccurs="0" maxOccurs="unbounded"/>
|
||||||
|
<xs:element ref="rerunError" minOccurs="0" maxOccurs="unbounded"/>
|
||||||
|
<xs:element ref="flakyFailure" minOccurs="0" maxOccurs="unbounded"/>
|
||||||
|
<xs:element ref="flakyError" minOccurs="0" maxOccurs="unbounded"/>
|
||||||
|
<xs:element ref="system-out"/>
|
||||||
|
<xs:element ref="system-err"/>
|
||||||
|
</xs:choice>
|
||||||
|
</xs:sequence>
|
||||||
|
<xs:attribute name="name" type="xs:string" use="required"/>
|
||||||
|
<xs:attribute name="time" type="xs:string"/>
|
||||||
|
<xs:attribute name="classname" type="xs:string"/>
|
||||||
|
<xs:attribute name="group" type="xs:string"/>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
|
||||||
|
<xs:element name="testsuite">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||||
|
<xs:element ref="testsuite"/>
|
||||||
|
<xs:element ref="properties"/>
|
||||||
|
<xs:element ref="testcase"/>
|
||||||
|
<xs:element ref="system-out"/>
|
||||||
|
<xs:element ref="system-err"/>
|
||||||
|
</xs:choice>
|
||||||
|
<xs:attribute name="name" type="xs:string" use="required"/>
|
||||||
|
<xs:attribute name="tests" type="xs:string" use="required"/>
|
||||||
|
<xs:attribute name="failures" type="xs:string" use="required"/>
|
||||||
|
<xs:attribute name="errors" type="xs:string" use="required"/>
|
||||||
|
<xs:attribute name="group" type="xs:string" />
|
||||||
|
<xs:attribute name="time" type="SUREFIRE_TIME"/>
|
||||||
|
<xs:attribute name="skipped" type="xs:string" />
|
||||||
|
<xs:attribute name="timestamp" type="xs:string" />
|
||||||
|
<xs:attribute name="hostname" type="xs:string" />
|
||||||
|
<xs:attribute name="id" type="xs:string" />
|
||||||
|
<xs:attribute name="package" type="xs:string" />
|
||||||
|
<xs:attribute name="file" type="xs:string"/>
|
||||||
|
<xs:attribute name="log" type="xs:string"/>
|
||||||
|
<xs:attribute name="url" type="xs:string"/>
|
||||||
|
<xs:attribute name="version" type="xs:string"/>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
|
||||||
|
<xs:element name="testsuites">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element ref="testsuite" minOccurs="0" maxOccurs="unbounded" />
|
||||||
|
</xs:sequence>
|
||||||
|
<xs:attribute name="name" type="xs:string" />
|
||||||
|
<xs:attribute name="time" type="SUREFIRE_TIME"/>
|
||||||
|
<xs:attribute name="tests" type="xs:string" />
|
||||||
|
<xs:attribute name="failures" type="xs:string" />
|
||||||
|
<xs:attribute name="errors" type="xs:string" />
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
|
||||||
|
</xs:schema>
|
|
@ -1,20 +1,47 @@
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from pathlib import Path
|
||||||
from xml.dom import minidom
|
from xml.dom import minidom
|
||||||
|
|
||||||
import py
|
import py
|
||||||
|
import xmlschema
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from _pytest.junitxml import LogXML
|
from _pytest.junitxml import LogXML
|
||||||
from _pytest.reports import BaseReport
|
from _pytest.reports import BaseReport
|
||||||
|
|
||||||
|
|
||||||
def runandparse(testdir, *args):
|
@pytest.fixture(scope="session")
|
||||||
resultpath = testdir.tmpdir.join("junit.xml")
|
def schema():
|
||||||
result = testdir.runpytest("--junitxml=%s" % resultpath, *args)
|
"""Returns a xmlschema.XMLSchema object for the junit-10.xsd file"""
|
||||||
xmldoc = minidom.parse(str(resultpath))
|
fn = Path(__file__).parent / "example_scripts/junit-10.xsd"
|
||||||
return result, DomNode(xmldoc)
|
with fn.open() as f:
|
||||||
|
return xmlschema.XMLSchema(f)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def run_and_parse(testdir, schema):
|
||||||
|
"""
|
||||||
|
Fixture that returns a function that can be used to execute pytest and return
|
||||||
|
the parsed ``DomNode`` of the root xml node.
|
||||||
|
|
||||||
|
The ``family`` parameter is used to configure the ``junit_family`` of the written report.
|
||||||
|
"xunit2" is also automatically validated against the schema.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def run(*args, family="xunit1"):
|
||||||
|
if family:
|
||||||
|
args = ("-o", "junit_family=" + family) + args
|
||||||
|
xml_path = testdir.tmpdir.join("junit.xml")
|
||||||
|
result = testdir.runpytest("--junitxml=%s" % xml_path, *args)
|
||||||
|
if family == "xunit2":
|
||||||
|
with xml_path.open() as f:
|
||||||
|
schema.validate(f)
|
||||||
|
xmldoc = minidom.parse(str(xml_path))
|
||||||
|
return result, DomNode(xmldoc)
|
||||||
|
|
||||||
|
return run
|
||||||
|
|
||||||
|
|
||||||
def assert_attr(node, **kwargs):
|
def assert_attr(node, **kwargs):
|
||||||
|
@ -91,8 +118,12 @@ class DomNode:
|
||||||
return type(self)(self.__node.nextSibling)
|
return type(self)(self.__node.nextSibling)
|
||||||
|
|
||||||
|
|
||||||
|
parametrize_families = pytest.mark.parametrize("xunit_family", ["xunit1", "xunit2"])
|
||||||
|
|
||||||
|
|
||||||
class TestPython:
|
class TestPython:
|
||||||
def test_summing_simple(self, testdir):
|
@parametrize_families
|
||||||
|
def test_summing_simple(self, testdir, run_and_parse, xunit_family):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -110,12 +141,13 @@ class TestPython:
|
||||||
assert 1
|
assert 1
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse(family=xunit_family)
|
||||||
assert result.ret
|
assert result.ret
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
node.assert_attr(name="pytest", errors=0, failures=1, skipped=2, tests=5)
|
node.assert_attr(name="pytest", errors=0, failures=1, skipped=2, tests=5)
|
||||||
|
|
||||||
def test_summing_simple_with_errors(self, testdir):
|
@parametrize_families
|
||||||
|
def test_summing_simple_with_errors(self, testdir, run_and_parse, xunit_family):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -136,23 +168,25 @@ class TestPython:
|
||||||
assert True
|
assert True
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse(family=xunit_family)
|
||||||
assert result.ret
|
assert result.ret
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
node.assert_attr(name="pytest", errors=1, failures=2, skipped=1, tests=5)
|
node.assert_attr(name="pytest", errors=1, failures=2, skipped=1, tests=5)
|
||||||
|
|
||||||
def test_hostname_in_xml(self, testdir):
|
@parametrize_families
|
||||||
|
def test_hostname_in_xml(self, testdir, run_and_parse, xunit_family):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
def test_pass():
|
def test_pass():
|
||||||
pass
|
pass
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse(family=xunit_family)
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
node.assert_attr(hostname=platform.node())
|
node.assert_attr(hostname=platform.node())
|
||||||
|
|
||||||
def test_timestamp_in_xml(self, testdir):
|
@parametrize_families
|
||||||
|
def test_timestamp_in_xml(self, testdir, run_and_parse, xunit_family):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
def test_pass():
|
def test_pass():
|
||||||
|
@ -160,12 +194,12 @@ class TestPython:
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
start_time = datetime.now()
|
start_time = datetime.now()
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse(family=xunit_family)
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
timestamp = datetime.strptime(node["timestamp"], "%Y-%m-%dT%H:%M:%S.%f")
|
timestamp = datetime.strptime(node["timestamp"], "%Y-%m-%dT%H:%M:%S.%f")
|
||||||
assert start_time <= timestamp < datetime.now()
|
assert start_time <= timestamp < datetime.now()
|
||||||
|
|
||||||
def test_timing_function(self, testdir):
|
def test_timing_function(self, testdir, run_and_parse):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
import time, pytest
|
import time, pytest
|
||||||
|
@ -177,14 +211,16 @@ class TestPython:
|
||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse()
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
tnode = node.find_first_by_tag("testcase")
|
tnode = node.find_first_by_tag("testcase")
|
||||||
val = tnode["time"]
|
val = tnode["time"]
|
||||||
assert round(float(val), 2) >= 0.03
|
assert round(float(val), 2) >= 0.03
|
||||||
|
|
||||||
@pytest.mark.parametrize("duration_report", ["call", "total"])
|
@pytest.mark.parametrize("duration_report", ["call", "total"])
|
||||||
def test_junit_duration_report(self, testdir, monkeypatch, duration_report):
|
def test_junit_duration_report(
|
||||||
|
self, testdir, monkeypatch, duration_report, run_and_parse
|
||||||
|
):
|
||||||
|
|
||||||
# mock LogXML.node_reporter so it always sets a known duration to each test report object
|
# mock LogXML.node_reporter so it always sets a known duration to each test report object
|
||||||
original_node_reporter = LogXML.node_reporter
|
original_node_reporter = LogXML.node_reporter
|
||||||
|
@ -202,8 +238,8 @@ class TestPython:
|
||||||
pass
|
pass
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(
|
result, dom = run_and_parse(
|
||||||
testdir, "-o", "junit_duration_report={}".format(duration_report)
|
"-o", "junit_duration_report={}".format(duration_report)
|
||||||
)
|
)
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
tnode = node.find_first_by_tag("testcase")
|
tnode = node.find_first_by_tag("testcase")
|
||||||
|
@ -214,7 +250,8 @@ class TestPython:
|
||||||
assert duration_report == "call"
|
assert duration_report == "call"
|
||||||
assert val == 1.0
|
assert val == 1.0
|
||||||
|
|
||||||
def test_setup_error(self, testdir):
|
@parametrize_families
|
||||||
|
def test_setup_error(self, testdir, run_and_parse, xunit_family):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -226,7 +263,7 @@ class TestPython:
|
||||||
pass
|
pass
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse(family=xunit_family)
|
||||||
assert result.ret
|
assert result.ret
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
node.assert_attr(errors=1, tests=1)
|
node.assert_attr(errors=1, tests=1)
|
||||||
|
@ -236,7 +273,8 @@ class TestPython:
|
||||||
fnode.assert_attr(message="test setup failure")
|
fnode.assert_attr(message="test setup failure")
|
||||||
assert "ValueError" in fnode.toxml()
|
assert "ValueError" in fnode.toxml()
|
||||||
|
|
||||||
def test_teardown_error(self, testdir):
|
@parametrize_families
|
||||||
|
def test_teardown_error(self, testdir, run_and_parse, xunit_family):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -249,7 +287,7 @@ class TestPython:
|
||||||
pass
|
pass
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse(family=xunit_family)
|
||||||
assert result.ret
|
assert result.ret
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
tnode = node.find_first_by_tag("testcase")
|
tnode = node.find_first_by_tag("testcase")
|
||||||
|
@ -258,7 +296,8 @@ class TestPython:
|
||||||
fnode.assert_attr(message="test teardown failure")
|
fnode.assert_attr(message="test teardown failure")
|
||||||
assert "ValueError" in fnode.toxml()
|
assert "ValueError" in fnode.toxml()
|
||||||
|
|
||||||
def test_call_failure_teardown_error(self, testdir):
|
@parametrize_families
|
||||||
|
def test_call_failure_teardown_error(self, testdir, run_and_parse, xunit_family):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -271,7 +310,7 @@ class TestPython:
|
||||||
raise Exception("Call Exception")
|
raise Exception("Call Exception")
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse(family=xunit_family)
|
||||||
assert result.ret
|
assert result.ret
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
node.assert_attr(errors=1, failures=1, tests=1)
|
node.assert_attr(errors=1, failures=1, tests=1)
|
||||||
|
@ -283,7 +322,8 @@ class TestPython:
|
||||||
snode = second.find_first_by_tag("error")
|
snode = second.find_first_by_tag("error")
|
||||||
snode.assert_attr(message="test teardown failure")
|
snode.assert_attr(message="test teardown failure")
|
||||||
|
|
||||||
def test_skip_contains_name_reason(self, testdir):
|
@parametrize_families
|
||||||
|
def test_skip_contains_name_reason(self, testdir, run_and_parse, xunit_family):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -291,7 +331,7 @@ class TestPython:
|
||||||
pytest.skip("hello23")
|
pytest.skip("hello23")
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse(family=xunit_family)
|
||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
node.assert_attr(skipped=1)
|
node.assert_attr(skipped=1)
|
||||||
|
@ -300,7 +340,8 @@ class TestPython:
|
||||||
snode = tnode.find_first_by_tag("skipped")
|
snode = tnode.find_first_by_tag("skipped")
|
||||||
snode.assert_attr(type="pytest.skip", message="hello23")
|
snode.assert_attr(type="pytest.skip", message="hello23")
|
||||||
|
|
||||||
def test_mark_skip_contains_name_reason(self, testdir):
|
@parametrize_families
|
||||||
|
def test_mark_skip_contains_name_reason(self, testdir, run_and_parse, xunit_family):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -309,7 +350,7 @@ class TestPython:
|
||||||
assert True
|
assert True
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse(family=xunit_family)
|
||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
node.assert_attr(skipped=1)
|
node.assert_attr(skipped=1)
|
||||||
|
@ -320,7 +361,10 @@ class TestPython:
|
||||||
snode = tnode.find_first_by_tag("skipped")
|
snode = tnode.find_first_by_tag("skipped")
|
||||||
snode.assert_attr(type="pytest.skip", message="hello24")
|
snode.assert_attr(type="pytest.skip", message="hello24")
|
||||||
|
|
||||||
def test_mark_skipif_contains_name_reason(self, testdir):
|
@parametrize_families
|
||||||
|
def test_mark_skipif_contains_name_reason(
|
||||||
|
self, testdir, run_and_parse, xunit_family
|
||||||
|
):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -330,7 +374,7 @@ class TestPython:
|
||||||
assert True
|
assert True
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse(family=xunit_family)
|
||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
node.assert_attr(skipped=1)
|
node.assert_attr(skipped=1)
|
||||||
|
@ -341,7 +385,10 @@ class TestPython:
|
||||||
snode = tnode.find_first_by_tag("skipped")
|
snode = tnode.find_first_by_tag("skipped")
|
||||||
snode.assert_attr(type="pytest.skip", message="hello25")
|
snode.assert_attr(type="pytest.skip", message="hello25")
|
||||||
|
|
||||||
def test_mark_skip_doesnt_capture_output(self, testdir):
|
@parametrize_families
|
||||||
|
def test_mark_skip_doesnt_capture_output(
|
||||||
|
self, testdir, run_and_parse, xunit_family
|
||||||
|
):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -350,12 +397,13 @@ class TestPython:
|
||||||
print("bar!")
|
print("bar!")
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse(family=xunit_family)
|
||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
node_xml = dom.find_first_by_tag("testsuite").toxml()
|
node_xml = dom.find_first_by_tag("testsuite").toxml()
|
||||||
assert "bar!" not in node_xml
|
assert "bar!" not in node_xml
|
||||||
|
|
||||||
def test_classname_instance(self, testdir):
|
@parametrize_families
|
||||||
|
def test_classname_instance(self, testdir, run_and_parse, xunit_family):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
class TestClass(object):
|
class TestClass(object):
|
||||||
|
@ -363,7 +411,7 @@ class TestPython:
|
||||||
assert 0
|
assert 0
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse(family=xunit_family)
|
||||||
assert result.ret
|
assert result.ret
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
node.assert_attr(failures=1)
|
node.assert_attr(failures=1)
|
||||||
|
@ -372,20 +420,22 @@ class TestPython:
|
||||||
classname="test_classname_instance.TestClass", name="test_method"
|
classname="test_classname_instance.TestClass", name="test_method"
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_classname_nested_dir(self, testdir):
|
@parametrize_families
|
||||||
|
def test_classname_nested_dir(self, testdir, run_and_parse, xunit_family):
|
||||||
p = testdir.tmpdir.ensure("sub", "test_hello.py")
|
p = testdir.tmpdir.ensure("sub", "test_hello.py")
|
||||||
p.write("def test_func(): 0/0")
|
p.write("def test_func(): 0/0")
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse(family=xunit_family)
|
||||||
assert result.ret
|
assert result.ret
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
node.assert_attr(failures=1)
|
node.assert_attr(failures=1)
|
||||||
tnode = node.find_first_by_tag("testcase")
|
tnode = node.find_first_by_tag("testcase")
|
||||||
tnode.assert_attr(classname="sub.test_hello", name="test_func")
|
tnode.assert_attr(classname="sub.test_hello", name="test_func")
|
||||||
|
|
||||||
def test_internal_error(self, testdir):
|
@parametrize_families
|
||||||
|
def test_internal_error(self, testdir, run_and_parse, xunit_family):
|
||||||
testdir.makeconftest("def pytest_runtest_protocol(): 0 / 0")
|
testdir.makeconftest("def pytest_runtest_protocol(): 0 / 0")
|
||||||
testdir.makepyfile("def test_function(): pass")
|
testdir.makepyfile("def test_function(): pass")
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse(family=xunit_family)
|
||||||
assert result.ret
|
assert result.ret
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
node.assert_attr(errors=1, tests=1)
|
node.assert_attr(errors=1, tests=1)
|
||||||
|
@ -396,7 +446,10 @@ class TestPython:
|
||||||
assert "Division" in fnode.toxml()
|
assert "Division" in fnode.toxml()
|
||||||
|
|
||||||
@pytest.mark.parametrize("junit_logging", ["no", "system-out", "system-err"])
|
@pytest.mark.parametrize("junit_logging", ["no", "system-out", "system-err"])
|
||||||
def test_failure_function(self, testdir, junit_logging):
|
@parametrize_families
|
||||||
|
def test_failure_function(
|
||||||
|
self, testdir, junit_logging, run_and_parse, xunit_family
|
||||||
|
):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
|
@ -411,7 +464,9 @@ class TestPython:
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
result, dom = runandparse(testdir, "-o", "junit_logging=%s" % junit_logging)
|
result, dom = run_and_parse(
|
||||||
|
"-o", "junit_logging=%s" % junit_logging, family=xunit_family
|
||||||
|
)
|
||||||
assert result.ret
|
assert result.ret
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
node.assert_attr(failures=1, tests=1)
|
node.assert_attr(failures=1, tests=1)
|
||||||
|
@ -439,7 +494,8 @@ class TestPython:
|
||||||
assert "warning msg" not in systemout.toxml()
|
assert "warning msg" not in systemout.toxml()
|
||||||
assert "warning msg" not in systemerr.toxml()
|
assert "warning msg" not in systemerr.toxml()
|
||||||
|
|
||||||
def test_failure_verbose_message(self, testdir):
|
@parametrize_families
|
||||||
|
def test_failure_verbose_message(self, testdir, run_and_parse, xunit_family):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
import sys
|
import sys
|
||||||
|
@ -447,14 +503,14 @@ class TestPython:
|
||||||
assert 0, "An error"
|
assert 0, "An error"
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
result, dom = run_and_parse(family=xunit_family)
|
||||||
result, dom = runandparse(testdir)
|
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
tnode = node.find_first_by_tag("testcase")
|
tnode = node.find_first_by_tag("testcase")
|
||||||
fnode = tnode.find_first_by_tag("failure")
|
fnode = tnode.find_first_by_tag("failure")
|
||||||
fnode.assert_attr(message="AssertionError: An error assert 0")
|
fnode.assert_attr(message="AssertionError: An error assert 0")
|
||||||
|
|
||||||
def test_failure_escape(self, testdir):
|
@parametrize_families
|
||||||
|
def test_failure_escape(self, testdir, run_and_parse, xunit_family):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -464,7 +520,7 @@ class TestPython:
|
||||||
assert 0
|
assert 0
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse(family=xunit_family)
|
||||||
assert result.ret
|
assert result.ret
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
node.assert_attr(failures=3, tests=3)
|
node.assert_attr(failures=3, tests=3)
|
||||||
|
@ -479,7 +535,8 @@ class TestPython:
|
||||||
text = sysout.text
|
text = sysout.text
|
||||||
assert text == "%s\n" % char
|
assert text == "%s\n" % char
|
||||||
|
|
||||||
def test_junit_prefixing(self, testdir):
|
@parametrize_families
|
||||||
|
def test_junit_prefixing(self, testdir, run_and_parse, xunit_family):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
def test_func():
|
def test_func():
|
||||||
|
@ -489,7 +546,7 @@ class TestPython:
|
||||||
pass
|
pass
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir, "--junitprefix=xyz")
|
result, dom = run_and_parse("--junitprefix=xyz", family=xunit_family)
|
||||||
assert result.ret
|
assert result.ret
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
node.assert_attr(failures=1, tests=2)
|
node.assert_attr(failures=1, tests=2)
|
||||||
|
@ -500,7 +557,8 @@ class TestPython:
|
||||||
classname="xyz.test_junit_prefixing.TestHello", name="test_hello"
|
classname="xyz.test_junit_prefixing.TestHello", name="test_hello"
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_xfailure_function(self, testdir):
|
@parametrize_families
|
||||||
|
def test_xfailure_function(self, testdir, run_and_parse, xunit_family):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -508,7 +566,7 @@ class TestPython:
|
||||||
pytest.xfail("42")
|
pytest.xfail("42")
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse(family=xunit_family)
|
||||||
assert not result.ret
|
assert not result.ret
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
node.assert_attr(skipped=1, tests=1)
|
node.assert_attr(skipped=1, tests=1)
|
||||||
|
@ -516,9 +574,9 @@ class TestPython:
|
||||||
tnode.assert_attr(classname="test_xfailure_function", name="test_xfail")
|
tnode.assert_attr(classname="test_xfailure_function", name="test_xfail")
|
||||||
fnode = tnode.find_first_by_tag("skipped")
|
fnode = tnode.find_first_by_tag("skipped")
|
||||||
fnode.assert_attr(type="pytest.xfail", message="42")
|
fnode.assert_attr(type="pytest.xfail", message="42")
|
||||||
# assert "ValueError" in fnode.toxml()
|
|
||||||
|
|
||||||
def test_xfailure_marker(self, testdir):
|
@parametrize_families
|
||||||
|
def test_xfailure_marker(self, testdir, run_and_parse, xunit_family):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -527,7 +585,7 @@ class TestPython:
|
||||||
assert False
|
assert False
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse(family=xunit_family)
|
||||||
assert not result.ret
|
assert not result.ret
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
node.assert_attr(skipped=1, tests=1)
|
node.assert_attr(skipped=1, tests=1)
|
||||||
|
@ -536,7 +594,7 @@ class TestPython:
|
||||||
fnode = tnode.find_first_by_tag("skipped")
|
fnode = tnode.find_first_by_tag("skipped")
|
||||||
fnode.assert_attr(type="pytest.xfail", message="42")
|
fnode.assert_attr(type="pytest.xfail", message="42")
|
||||||
|
|
||||||
def test_xfail_captures_output_once(self, testdir):
|
def test_xfail_captures_output_once(self, testdir, run_and_parse):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
import sys
|
import sys
|
||||||
|
@ -549,13 +607,14 @@ class TestPython:
|
||||||
assert 0
|
assert 0
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse()
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
tnode = node.find_first_by_tag("testcase")
|
tnode = node.find_first_by_tag("testcase")
|
||||||
assert len(tnode.find_by_tag("system-err")) == 1
|
assert len(tnode.find_by_tag("system-err")) == 1
|
||||||
assert len(tnode.find_by_tag("system-out")) == 1
|
assert len(tnode.find_by_tag("system-out")) == 1
|
||||||
|
|
||||||
def test_xfailure_xpass(self, testdir):
|
@parametrize_families
|
||||||
|
def test_xfailure_xpass(self, testdir, run_and_parse, xunit_family):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -564,14 +623,15 @@ class TestPython:
|
||||||
pass
|
pass
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse(family=xunit_family)
|
||||||
# assert result.ret
|
# assert result.ret
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
node.assert_attr(skipped=0, tests=1)
|
node.assert_attr(skipped=0, tests=1)
|
||||||
tnode = node.find_first_by_tag("testcase")
|
tnode = node.find_first_by_tag("testcase")
|
||||||
tnode.assert_attr(classname="test_xfailure_xpass", name="test_xpass")
|
tnode.assert_attr(classname="test_xfailure_xpass", name="test_xpass")
|
||||||
|
|
||||||
def test_xfailure_xpass_strict(self, testdir):
|
@parametrize_families
|
||||||
|
def test_xfailure_xpass_strict(self, testdir, run_and_parse, xunit_family):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -580,7 +640,7 @@ class TestPython:
|
||||||
pass
|
pass
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse(family=xunit_family)
|
||||||
# assert result.ret
|
# assert result.ret
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
node.assert_attr(skipped=0, tests=1)
|
node.assert_attr(skipped=0, tests=1)
|
||||||
|
@ -589,9 +649,10 @@ class TestPython:
|
||||||
fnode = tnode.find_first_by_tag("failure")
|
fnode = tnode.find_first_by_tag("failure")
|
||||||
fnode.assert_attr(message="[XPASS(strict)] This needs to fail!")
|
fnode.assert_attr(message="[XPASS(strict)] This needs to fail!")
|
||||||
|
|
||||||
def test_collect_error(self, testdir):
|
@parametrize_families
|
||||||
|
def test_collect_error(self, testdir, run_and_parse, xunit_family):
|
||||||
testdir.makepyfile("syntax error")
|
testdir.makepyfile("syntax error")
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse(family=xunit_family)
|
||||||
assert result.ret
|
assert result.ret
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
node.assert_attr(errors=1, tests=1)
|
node.assert_attr(errors=1, tests=1)
|
||||||
|
@ -600,7 +661,7 @@ class TestPython:
|
||||||
fnode.assert_attr(message="collection failure")
|
fnode.assert_attr(message="collection failure")
|
||||||
assert "SyntaxError" in fnode.toxml()
|
assert "SyntaxError" in fnode.toxml()
|
||||||
|
|
||||||
def test_unicode(self, testdir):
|
def test_unicode(self, testdir, run_and_parse):
|
||||||
value = "hx\xc4\x85\xc4\x87\n"
|
value = "hx\xc4\x85\xc4\x87\n"
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""\
|
"""\
|
||||||
|
@ -611,14 +672,14 @@ class TestPython:
|
||||||
"""
|
"""
|
||||||
% value
|
% value
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse()
|
||||||
assert result.ret == 1
|
assert result.ret == 1
|
||||||
tnode = dom.find_first_by_tag("testcase")
|
tnode = dom.find_first_by_tag("testcase")
|
||||||
fnode = tnode.find_first_by_tag("failure")
|
fnode = tnode.find_first_by_tag("failure")
|
||||||
assert "hx" in fnode.toxml()
|
assert "hx" in fnode.toxml()
|
||||||
|
|
||||||
def test_assertion_binchars(self, testdir):
|
def test_assertion_binchars(self, testdir, run_and_parse):
|
||||||
"""this test did fail when the escaping wasn't strict"""
|
"""this test did fail when the escaping wasnt strict"""
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -629,23 +690,23 @@ class TestPython:
|
||||||
assert M1 == M2
|
assert M1 == M2
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse()
|
||||||
print(dom.toxml())
|
print(dom.toxml())
|
||||||
|
|
||||||
def test_pass_captures_stdout(self, testdir):
|
def test_pass_captures_stdout(self, testdir, run_and_parse):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
def test_pass():
|
def test_pass():
|
||||||
print('hello-stdout')
|
print('hello-stdout')
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse()
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
pnode = node.find_first_by_tag("testcase")
|
pnode = node.find_first_by_tag("testcase")
|
||||||
systemout = pnode.find_first_by_tag("system-out")
|
systemout = pnode.find_first_by_tag("system-out")
|
||||||
assert "hello-stdout" in systemout.toxml()
|
assert "hello-stdout" in systemout.toxml()
|
||||||
|
|
||||||
def test_pass_captures_stderr(self, testdir):
|
def test_pass_captures_stderr(self, testdir, run_and_parse):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
import sys
|
import sys
|
||||||
|
@ -653,13 +714,13 @@ class TestPython:
|
||||||
sys.stderr.write('hello-stderr')
|
sys.stderr.write('hello-stderr')
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse()
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
pnode = node.find_first_by_tag("testcase")
|
pnode = node.find_first_by_tag("testcase")
|
||||||
systemout = pnode.find_first_by_tag("system-err")
|
systemout = pnode.find_first_by_tag("system-err")
|
||||||
assert "hello-stderr" in systemout.toxml()
|
assert "hello-stderr" in systemout.toxml()
|
||||||
|
|
||||||
def test_setup_error_captures_stdout(self, testdir):
|
def test_setup_error_captures_stdout(self, testdir, run_and_parse):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -672,13 +733,13 @@ class TestPython:
|
||||||
pass
|
pass
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse()
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
pnode = node.find_first_by_tag("testcase")
|
pnode = node.find_first_by_tag("testcase")
|
||||||
systemout = pnode.find_first_by_tag("system-out")
|
systemout = pnode.find_first_by_tag("system-out")
|
||||||
assert "hello-stdout" in systemout.toxml()
|
assert "hello-stdout" in systemout.toxml()
|
||||||
|
|
||||||
def test_setup_error_captures_stderr(self, testdir):
|
def test_setup_error_captures_stderr(self, testdir, run_and_parse):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
import sys
|
import sys
|
||||||
|
@ -692,13 +753,13 @@ class TestPython:
|
||||||
pass
|
pass
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse()
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
pnode = node.find_first_by_tag("testcase")
|
pnode = node.find_first_by_tag("testcase")
|
||||||
systemout = pnode.find_first_by_tag("system-err")
|
systemout = pnode.find_first_by_tag("system-err")
|
||||||
assert "hello-stderr" in systemout.toxml()
|
assert "hello-stderr" in systemout.toxml()
|
||||||
|
|
||||||
def test_avoid_double_stdout(self, testdir):
|
def test_avoid_double_stdout(self, testdir, run_and_parse):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
import sys
|
import sys
|
||||||
|
@ -713,7 +774,7 @@ class TestPython:
|
||||||
sys.stdout.write('hello-stdout call')
|
sys.stdout.write('hello-stdout call')
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse()
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
pnode = node.find_first_by_tag("testcase")
|
pnode = node.find_first_by_tag("testcase")
|
||||||
systemout = pnode.find_first_by_tag("system-out")
|
systemout = pnode.find_first_by_tag("system-out")
|
||||||
|
@ -756,7 +817,8 @@ def test_dont_configure_on_slaves(tmpdir):
|
||||||
|
|
||||||
|
|
||||||
class TestNonPython:
|
class TestNonPython:
|
||||||
def test_summing_simple(self, testdir):
|
@parametrize_families
|
||||||
|
def test_summing_simple(self, testdir, run_and_parse, xunit_family):
|
||||||
testdir.makeconftest(
|
testdir.makeconftest(
|
||||||
"""
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -774,7 +836,7 @@ class TestNonPython:
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
testdir.tmpdir.join("myfile.xyz").write("hello")
|
testdir.tmpdir.join("myfile.xyz").write("hello")
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse(family=xunit_family)
|
||||||
assert result.ret
|
assert result.ret
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
node.assert_attr(errors=0, failures=1, skipped=0, tests=1)
|
node.assert_attr(errors=0, failures=1, skipped=0, tests=1)
|
||||||
|
@ -822,8 +884,8 @@ def test_nullbyte_replace(testdir):
|
||||||
|
|
||||||
def test_invalid_xml_escape():
|
def test_invalid_xml_escape():
|
||||||
# Test some more invalid xml chars, the full range should be
|
# Test some more invalid xml chars, the full range should be
|
||||||
# tested really but let's just thest the edges of the ranges
|
# tested really but let's just test the edges of the ranges
|
||||||
# intead.
|
# instead.
|
||||||
# XXX This only tests low unicode character points for now as
|
# XXX This only tests low unicode character points for now as
|
||||||
# there are some issues with the testing infrastructure for
|
# there are some issues with the testing infrastructure for
|
||||||
# the higher ones.
|
# the higher ones.
|
||||||
|
@ -907,7 +969,7 @@ def test_logxml_check_isdir(testdir):
|
||||||
result.stderr.fnmatch_lines(["*--junitxml must be a filename*"])
|
result.stderr.fnmatch_lines(["*--junitxml must be a filename*"])
|
||||||
|
|
||||||
|
|
||||||
def test_escaped_parametrized_names_xml(testdir):
|
def test_escaped_parametrized_names_xml(testdir, run_and_parse):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""\
|
"""\
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -916,13 +978,13 @@ def test_escaped_parametrized_names_xml(testdir):
|
||||||
assert char
|
assert char
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse()
|
||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
node = dom.find_first_by_tag("testcase")
|
node = dom.find_first_by_tag("testcase")
|
||||||
node.assert_attr(name="test_func[\\x00]")
|
node.assert_attr(name="test_func[\\x00]")
|
||||||
|
|
||||||
|
|
||||||
def test_double_colon_split_function_issue469(testdir):
|
def test_double_colon_split_function_issue469(testdir, run_and_parse):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -931,14 +993,14 @@ def test_double_colon_split_function_issue469(testdir):
|
||||||
pass
|
pass
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse()
|
||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
node = dom.find_first_by_tag("testcase")
|
node = dom.find_first_by_tag("testcase")
|
||||||
node.assert_attr(classname="test_double_colon_split_function_issue469")
|
node.assert_attr(classname="test_double_colon_split_function_issue469")
|
||||||
node.assert_attr(name="test_func[double::colon]")
|
node.assert_attr(name="test_func[double::colon]")
|
||||||
|
|
||||||
|
|
||||||
def test_double_colon_split_method_issue469(testdir):
|
def test_double_colon_split_method_issue469(testdir, run_and_parse):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -948,7 +1010,7 @@ def test_double_colon_split_method_issue469(testdir):
|
||||||
pass
|
pass
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse()
|
||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
node = dom.find_first_by_tag("testcase")
|
node = dom.find_first_by_tag("testcase")
|
||||||
node.assert_attr(classname="test_double_colon_split_method_issue469.TestClass")
|
node.assert_attr(classname="test_double_colon_split_method_issue469.TestClass")
|
||||||
|
@ -984,7 +1046,7 @@ def test_unicode_issue368(testdir):
|
||||||
log.pytest_sessionfinish()
|
log.pytest_sessionfinish()
|
||||||
|
|
||||||
|
|
||||||
def test_record_property(testdir):
|
def test_record_property(testdir, run_and_parse):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -996,7 +1058,7 @@ def test_record_property(testdir):
|
||||||
record_property("foo", "<1");
|
record_property("foo", "<1");
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir, "-rwv")
|
result, dom = run_and_parse("-rwv")
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
tnode = node.find_first_by_tag("testcase")
|
tnode = node.find_first_by_tag("testcase")
|
||||||
psnode = tnode.find_first_by_tag("properties")
|
psnode = tnode.find_first_by_tag("properties")
|
||||||
|
@ -1005,7 +1067,7 @@ def test_record_property(testdir):
|
||||||
pnodes[1].assert_attr(name="foo", value="<1")
|
pnodes[1].assert_attr(name="foo", value="<1")
|
||||||
|
|
||||||
|
|
||||||
def test_record_property_same_name(testdir):
|
def test_record_property_same_name(testdir, run_and_parse):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
def test_record_with_same_name(record_property):
|
def test_record_with_same_name(record_property):
|
||||||
|
@ -1013,7 +1075,7 @@ def test_record_property_same_name(testdir):
|
||||||
record_property("foo", "baz")
|
record_property("foo", "baz")
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir, "-rw")
|
result, dom = run_and_parse("-rw")
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
tnode = node.find_first_by_tag("testcase")
|
tnode = node.find_first_by_tag("testcase")
|
||||||
psnode = tnode.find_first_by_tag("properties")
|
psnode = tnode.find_first_by_tag("properties")
|
||||||
|
@ -1037,7 +1099,7 @@ def test_record_fixtures_without_junitxml(testdir, fixture_name):
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.filterwarnings("default")
|
@pytest.mark.filterwarnings("default")
|
||||||
def test_record_attribute(testdir):
|
def test_record_attribute(testdir, run_and_parse):
|
||||||
testdir.makeini(
|
testdir.makeini(
|
||||||
"""
|
"""
|
||||||
[pytest]
|
[pytest]
|
||||||
|
@ -1055,7 +1117,7 @@ def test_record_attribute(testdir):
|
||||||
record_xml_attribute("foo", "<1");
|
record_xml_attribute("foo", "<1");
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir, "-rw")
|
result, dom = run_and_parse("-rw")
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
tnode = node.find_first_by_tag("testcase")
|
tnode = node.find_first_by_tag("testcase")
|
||||||
tnode.assert_attr(bar="1")
|
tnode.assert_attr(bar="1")
|
||||||
|
@ -1067,7 +1129,7 @@ def test_record_attribute(testdir):
|
||||||
|
|
||||||
@pytest.mark.filterwarnings("default")
|
@pytest.mark.filterwarnings("default")
|
||||||
@pytest.mark.parametrize("fixture_name", ["record_xml_attribute", "record_property"])
|
@pytest.mark.parametrize("fixture_name", ["record_xml_attribute", "record_property"])
|
||||||
def test_record_fixtures_xunit2(testdir, fixture_name):
|
def test_record_fixtures_xunit2(testdir, fixture_name, run_and_parse):
|
||||||
"""Ensure record_xml_attribute and record_property drop values when outside of legacy family
|
"""Ensure record_xml_attribute and record_property drop values when outside of legacy family
|
||||||
"""
|
"""
|
||||||
testdir.makeini(
|
testdir.makeini(
|
||||||
|
@ -1090,7 +1152,7 @@ def test_record_fixtures_xunit2(testdir, fixture_name):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
result, dom = runandparse(testdir, "-rw")
|
result, dom = run_and_parse("-rw", family=None)
|
||||||
expected_lines = []
|
expected_lines = []
|
||||||
if fixture_name == "record_xml_attribute":
|
if fixture_name == "record_xml_attribute":
|
||||||
expected_lines.append(
|
expected_lines.append(
|
||||||
|
@ -1105,7 +1167,7 @@ def test_record_fixtures_xunit2(testdir, fixture_name):
|
||||||
result.stdout.fnmatch_lines(expected_lines)
|
result.stdout.fnmatch_lines(expected_lines)
|
||||||
|
|
||||||
|
|
||||||
def test_random_report_log_xdist(testdir, monkeypatch):
|
def test_random_report_log_xdist(testdir, monkeypatch, run_and_parse):
|
||||||
"""xdist calls pytest_runtest_logreport as they are executed by the slaves,
|
"""xdist calls pytest_runtest_logreport as they are executed by the slaves,
|
||||||
with nodes from several nodes overlapping, so junitxml must cope with that
|
with nodes from several nodes overlapping, so junitxml must cope with that
|
||||||
to produce correct reports. #1064
|
to produce correct reports. #1064
|
||||||
|
@ -1120,7 +1182,7 @@ def test_random_report_log_xdist(testdir, monkeypatch):
|
||||||
assert i != 22
|
assert i != 22
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
_, dom = runandparse(testdir, "-n2")
|
_, dom = run_and_parse("-n2")
|
||||||
suite_node = dom.find_first_by_tag("testsuite")
|
suite_node = dom.find_first_by_tag("testsuite")
|
||||||
failed = []
|
failed = []
|
||||||
for case_node in suite_node.find_by_tag("testcase"):
|
for case_node in suite_node.find_by_tag("testcase"):
|
||||||
|
@ -1130,21 +1192,22 @@ def test_random_report_log_xdist(testdir, monkeypatch):
|
||||||
assert failed == ["test_x[22]"]
|
assert failed == ["test_x[22]"]
|
||||||
|
|
||||||
|
|
||||||
def test_root_testsuites_tag(testdir):
|
@parametrize_families
|
||||||
|
def test_root_testsuites_tag(testdir, run_and_parse, xunit_family):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
def test_x():
|
def test_x():
|
||||||
pass
|
pass
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
_, dom = runandparse(testdir)
|
_, dom = run_and_parse(family=xunit_family)
|
||||||
root = dom.get_unique_child
|
root = dom.get_unique_child
|
||||||
assert root.tag == "testsuites"
|
assert root.tag == "testsuites"
|
||||||
suite_node = root.get_unique_child
|
suite_node = root.get_unique_child
|
||||||
assert suite_node.tag == "testsuite"
|
assert suite_node.tag == "testsuite"
|
||||||
|
|
||||||
|
|
||||||
def test_runs_twice(testdir):
|
def test_runs_twice(testdir, run_and_parse):
|
||||||
f = testdir.makepyfile(
|
f = testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
def test_pass():
|
def test_pass():
|
||||||
|
@ -1152,14 +1215,14 @@ def test_runs_twice(testdir):
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
result, dom = runandparse(testdir, f, f)
|
result, dom = run_and_parse(f, f)
|
||||||
assert "INTERNALERROR" not in result.stdout.str()
|
assert "INTERNALERROR" not in result.stdout.str()
|
||||||
first, second = [x["classname"] for x in dom.find_by_tag("testcase")]
|
first, second = [x["classname"] for x in dom.find_by_tag("testcase")]
|
||||||
assert first == second
|
assert first == second
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.xfail(reason="hangs", run=False)
|
@pytest.mark.xfail(reason="hangs", run=False)
|
||||||
def test_runs_twice_xdist(testdir):
|
def test_runs_twice_xdist(testdir, run_and_parse):
|
||||||
pytest.importorskip("xdist")
|
pytest.importorskip("xdist")
|
||||||
f = testdir.makepyfile(
|
f = testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
|
@ -1168,13 +1231,13 @@ def test_runs_twice_xdist(testdir):
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
result, dom = runandparse(testdir, f, "--dist", "each", "--tx", "2*popen")
|
result, dom = run_and_parse(f, "--dist", "each", "--tx", "2*popen")
|
||||||
assert "INTERNALERROR" not in result.stdout.str()
|
assert "INTERNALERROR" not in result.stdout.str()
|
||||||
first, second = [x["classname"] for x in dom.find_by_tag("testcase")]
|
first, second = [x["classname"] for x in dom.find_by_tag("testcase")]
|
||||||
assert first == second
|
assert first == second
|
||||||
|
|
||||||
|
|
||||||
def test_fancy_items_regression(testdir):
|
def test_fancy_items_regression(testdir, run_and_parse):
|
||||||
# issue 1259
|
# issue 1259
|
||||||
testdir.makeconftest(
|
testdir.makeconftest(
|
||||||
"""
|
"""
|
||||||
|
@ -1207,7 +1270,7 @@ def test_fancy_items_regression(testdir):
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse()
|
||||||
|
|
||||||
assert "INTERNALERROR" not in result.stdout.str()
|
assert "INTERNALERROR" not in result.stdout.str()
|
||||||
|
|
||||||
|
@ -1226,9 +1289,10 @@ def test_fancy_items_regression(testdir):
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def test_global_properties(testdir):
|
@parametrize_families
|
||||||
|
def test_global_properties(testdir, xunit_family):
|
||||||
path = testdir.tmpdir.join("test_global_properties.xml")
|
path = testdir.tmpdir.join("test_global_properties.xml")
|
||||||
log = LogXML(str(path), None)
|
log = LogXML(str(path), None, family=xunit_family)
|
||||||
|
|
||||||
class Report(BaseReport):
|
class Report(BaseReport):
|
||||||
sections = []
|
sections = []
|
||||||
|
@ -1286,7 +1350,8 @@ def test_url_property(testdir):
|
||||||
), "The URL did not get written to the xml"
|
), "The URL did not get written to the xml"
|
||||||
|
|
||||||
|
|
||||||
def test_record_testsuite_property(testdir):
|
@parametrize_families
|
||||||
|
def test_record_testsuite_property(testdir, run_and_parse, xunit_family):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
def test_func1(record_testsuite_property):
|
def test_func1(record_testsuite_property):
|
||||||
|
@ -1296,7 +1361,7 @@ def test_record_testsuite_property(testdir):
|
||||||
record_testsuite_property("stats", 10)
|
record_testsuite_property("stats", 10)
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse(family=xunit_family)
|
||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
properties_node = node.find_first_by_tag("properties")
|
properties_node = node.find_first_by_tag("properties")
|
||||||
|
@ -1334,14 +1399,16 @@ def test_record_testsuite_property_type_checking(testdir, junit):
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("suite_name", ["my_suite", ""])
|
@pytest.mark.parametrize("suite_name", ["my_suite", ""])
|
||||||
def test_set_suite_name(testdir, suite_name):
|
@parametrize_families
|
||||||
|
def test_set_suite_name(testdir, suite_name, run_and_parse, xunit_family):
|
||||||
if suite_name:
|
if suite_name:
|
||||||
testdir.makeini(
|
testdir.makeini(
|
||||||
"""
|
"""
|
||||||
[pytest]
|
[pytest]
|
||||||
junit_suite_name={}
|
junit_suite_name={suite_name}
|
||||||
|
junit_family={family}
|
||||||
""".format(
|
""".format(
|
||||||
suite_name
|
suite_name=suite_name, family=xunit_family
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
expected = suite_name
|
expected = suite_name
|
||||||
|
@ -1355,13 +1422,13 @@ def test_set_suite_name(testdir, suite_name):
|
||||||
pass
|
pass
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse(family=xunit_family)
|
||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
node.assert_attr(name=expected)
|
node.assert_attr(name=expected)
|
||||||
|
|
||||||
|
|
||||||
def test_escaped_skipreason_issue3533(testdir):
|
def test_escaped_skipreason_issue3533(testdir, run_and_parse):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -1370,20 +1437,26 @@ def test_escaped_skipreason_issue3533(testdir):
|
||||||
pass
|
pass
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
_, dom = runandparse(testdir)
|
_, dom = run_and_parse()
|
||||||
node = dom.find_first_by_tag("testcase")
|
node = dom.find_first_by_tag("testcase")
|
||||||
snode = node.find_first_by_tag("skipped")
|
snode = node.find_first_by_tag("skipped")
|
||||||
assert "1 <> 2" in snode.text
|
assert "1 <> 2" in snode.text
|
||||||
snode.assert_attr(message="1 <> 2")
|
snode.assert_attr(message="1 <> 2")
|
||||||
|
|
||||||
|
|
||||||
def test_logging_passing_tests_disabled_does_not_log_test_output(testdir):
|
@parametrize_families
|
||||||
|
def test_logging_passing_tests_disabled_does_not_log_test_output(
|
||||||
|
testdir, run_and_parse, xunit_family
|
||||||
|
):
|
||||||
testdir.makeini(
|
testdir.makeini(
|
||||||
"""
|
"""
|
||||||
[pytest]
|
[pytest]
|
||||||
junit_log_passing_tests=False
|
junit_log_passing_tests=False
|
||||||
junit_logging=system-out
|
junit_logging=system-out
|
||||||
"""
|
junit_family={family}
|
||||||
|
""".format(
|
||||||
|
family=xunit_family
|
||||||
|
)
|
||||||
)
|
)
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
|
@ -1397,7 +1470,7 @@ def test_logging_passing_tests_disabled_does_not_log_test_output(testdir):
|
||||||
logging.warning('hello')
|
logging.warning('hello')
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result, dom = runandparse(testdir)
|
result, dom = run_and_parse(family=xunit_family)
|
||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
node = dom.find_first_by_tag("testcase")
|
node = dom.find_first_by_tag("testcase")
|
||||||
assert len(node.find_by_tag("system-err")) == 0
|
assert len(node.find_by_tag("system-err")) == 0
|
||||||
|
|
Loading…
Reference in New Issue