Validate xunit2 files against the schema (#5605)
Validate xunit2 files against the schema
This commit is contained in:
commit
65e6038111
|
@ -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"},
|
||||
setup_requires=["setuptools-scm", "setuptools>=40.0"],
|
||||
package_dir={"": "src"},
|
||||
# fmt: off
|
||||
extras_require={
|
||||
"testing": [
|
||||
"argcomplete",
|
||||
|
@ -29,9 +28,9 @@ def main():
|
|||
"mock",
|
||||
"nose",
|
||||
"requests",
|
||||
],
|
||||
"xmlschema",
|
||||
]
|
||||
},
|
||||
# fmt: on
|
||||
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 platform
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from xml.dom import minidom
|
||||
|
||||
import py
|
||||
import xmlschema
|
||||
|
||||
import pytest
|
||||
from _pytest.junitxml import LogXML
|
||||
from _pytest.reports import BaseReport
|
||||
|
||||
|
||||
def runandparse(testdir, *args):
|
||||
resultpath = testdir.tmpdir.join("junit.xml")
|
||||
result = testdir.runpytest("--junitxml=%s" % resultpath, *args)
|
||||
xmldoc = minidom.parse(str(resultpath))
|
||||
return result, DomNode(xmldoc)
|
||||
@pytest.fixture(scope="session")
|
||||
def schema():
|
||||
"""Returns a xmlschema.XMLSchema object for the junit-10.xsd file"""
|
||||
fn = Path(__file__).parent / "example_scripts/junit-10.xsd"
|
||||
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):
|
||||
|
@ -91,8 +118,12 @@ class DomNode:
|
|||
return type(self)(self.__node.nextSibling)
|
||||
|
||||
|
||||
parametrize_families = pytest.mark.parametrize("xunit_family", ["xunit1", "xunit2"])
|
||||
|
||||
|
||||
class TestPython:
|
||||
def test_summing_simple(self, testdir):
|
||||
@parametrize_families
|
||||
def test_summing_simple(self, testdir, run_and_parse, xunit_family):
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
|
@ -110,12 +141,13 @@ class TestPython:
|
|||
assert 1
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse(family=xunit_family)
|
||||
assert result.ret
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
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(
|
||||
"""
|
||||
import pytest
|
||||
|
@ -136,23 +168,25 @@ class TestPython:
|
|||
assert True
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse(family=xunit_family)
|
||||
assert result.ret
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
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(
|
||||
"""
|
||||
def test_pass():
|
||||
pass
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse(family=xunit_family)
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
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(
|
||||
"""
|
||||
def test_pass():
|
||||
|
@ -160,12 +194,12 @@ class TestPython:
|
|||
"""
|
||||
)
|
||||
start_time = datetime.now()
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse(family=xunit_family)
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
timestamp = datetime.strptime(node["timestamp"], "%Y-%m-%dT%H:%M:%S.%f")
|
||||
assert start_time <= timestamp < datetime.now()
|
||||
|
||||
def test_timing_function(self, testdir):
|
||||
def test_timing_function(self, testdir, run_and_parse):
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import time, pytest
|
||||
|
@ -177,14 +211,16 @@ class TestPython:
|
|||
time.sleep(0.01)
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse()
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
tnode = node.find_first_by_tag("testcase")
|
||||
val = tnode["time"]
|
||||
assert round(float(val), 2) >= 0.03
|
||||
|
||||
@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
|
||||
original_node_reporter = LogXML.node_reporter
|
||||
|
@ -202,8 +238,8 @@ class TestPython:
|
|||
pass
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(
|
||||
testdir, "-o", "junit_duration_report={}".format(duration_report)
|
||||
result, dom = run_and_parse(
|
||||
"-o", "junit_duration_report={}".format(duration_report)
|
||||
)
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
tnode = node.find_first_by_tag("testcase")
|
||||
|
@ -214,7 +250,8 @@ class TestPython:
|
|||
assert duration_report == "call"
|
||||
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(
|
||||
"""
|
||||
import pytest
|
||||
|
@ -226,7 +263,7 @@ class TestPython:
|
|||
pass
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse(family=xunit_family)
|
||||
assert result.ret
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
node.assert_attr(errors=1, tests=1)
|
||||
|
@ -236,7 +273,8 @@ class TestPython:
|
|||
fnode.assert_attr(message="test setup failure")
|
||||
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(
|
||||
"""
|
||||
import pytest
|
||||
|
@ -249,7 +287,7 @@ class TestPython:
|
|||
pass
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse(family=xunit_family)
|
||||
assert result.ret
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
tnode = node.find_first_by_tag("testcase")
|
||||
|
@ -258,7 +296,8 @@ class TestPython:
|
|||
fnode.assert_attr(message="test teardown failure")
|
||||
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(
|
||||
"""
|
||||
import pytest
|
||||
|
@ -271,7 +310,7 @@ class TestPython:
|
|||
raise Exception("Call Exception")
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse(family=xunit_family)
|
||||
assert result.ret
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
node.assert_attr(errors=1, failures=1, tests=1)
|
||||
|
@ -283,7 +322,8 @@ class TestPython:
|
|||
snode = second.find_first_by_tag("error")
|
||||
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(
|
||||
"""
|
||||
import pytest
|
||||
|
@ -291,7 +331,7 @@ class TestPython:
|
|||
pytest.skip("hello23")
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse(family=xunit_family)
|
||||
assert result.ret == 0
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
node.assert_attr(skipped=1)
|
||||
|
@ -300,7 +340,8 @@ class TestPython:
|
|||
snode = tnode.find_first_by_tag("skipped")
|
||||
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(
|
||||
"""
|
||||
import pytest
|
||||
|
@ -309,7 +350,7 @@ class TestPython:
|
|||
assert True
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse(family=xunit_family)
|
||||
assert result.ret == 0
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
node.assert_attr(skipped=1)
|
||||
|
@ -320,7 +361,10 @@ class TestPython:
|
|||
snode = tnode.find_first_by_tag("skipped")
|
||||
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(
|
||||
"""
|
||||
import pytest
|
||||
|
@ -330,7 +374,7 @@ class TestPython:
|
|||
assert True
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse(family=xunit_family)
|
||||
assert result.ret == 0
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
node.assert_attr(skipped=1)
|
||||
|
@ -341,7 +385,10 @@ class TestPython:
|
|||
snode = tnode.find_first_by_tag("skipped")
|
||||
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(
|
||||
"""
|
||||
import pytest
|
||||
|
@ -350,12 +397,13 @@ class TestPython:
|
|||
print("bar!")
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse(family=xunit_family)
|
||||
assert result.ret == 0
|
||||
node_xml = dom.find_first_by_tag("testsuite").toxml()
|
||||
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(
|
||||
"""
|
||||
class TestClass(object):
|
||||
|
@ -363,7 +411,7 @@ class TestPython:
|
|||
assert 0
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse(family=xunit_family)
|
||||
assert result.ret
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
node.assert_attr(failures=1)
|
||||
|
@ -372,20 +420,22 @@ class TestPython:
|
|||
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.write("def test_func(): 0/0")
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse(family=xunit_family)
|
||||
assert result.ret
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
node.assert_attr(failures=1)
|
||||
tnode = node.find_first_by_tag("testcase")
|
||||
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.makepyfile("def test_function(): pass")
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse(family=xunit_family)
|
||||
assert result.ret
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
node.assert_attr(errors=1, tests=1)
|
||||
|
@ -396,7 +446,10 @@ class TestPython:
|
|||
assert "Division" in fnode.toxml()
|
||||
|
||||
@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(
|
||||
"""
|
||||
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
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
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 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(
|
||||
"""
|
||||
import sys
|
||||
|
@ -447,14 +503,14 @@ class TestPython:
|
|||
assert 0, "An error"
|
||||
"""
|
||||
)
|
||||
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse(family=xunit_family)
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
tnode = node.find_first_by_tag("testcase")
|
||||
fnode = tnode.find_first_by_tag("failure")
|
||||
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(
|
||||
"""
|
||||
import pytest
|
||||
|
@ -464,7 +520,7 @@ class TestPython:
|
|||
assert 0
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse(family=xunit_family)
|
||||
assert result.ret
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
node.assert_attr(failures=3, tests=3)
|
||||
|
@ -479,7 +535,8 @@ class TestPython:
|
|||
text = sysout.text
|
||||
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(
|
||||
"""
|
||||
def test_func():
|
||||
|
@ -489,7 +546,7 @@ class TestPython:
|
|||
pass
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir, "--junitprefix=xyz")
|
||||
result, dom = run_and_parse("--junitprefix=xyz", family=xunit_family)
|
||||
assert result.ret
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
node.assert_attr(failures=1, tests=2)
|
||||
|
@ -500,7 +557,8 @@ class TestPython:
|
|||
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(
|
||||
"""
|
||||
import pytest
|
||||
|
@ -508,7 +566,7 @@ class TestPython:
|
|||
pytest.xfail("42")
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse(family=xunit_family)
|
||||
assert not result.ret
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
node.assert_attr(skipped=1, tests=1)
|
||||
|
@ -516,9 +574,9 @@ class TestPython:
|
|||
tnode.assert_attr(classname="test_xfailure_function", name="test_xfail")
|
||||
fnode = tnode.find_first_by_tag("skipped")
|
||||
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(
|
||||
"""
|
||||
import pytest
|
||||
|
@ -527,7 +585,7 @@ class TestPython:
|
|||
assert False
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse(family=xunit_family)
|
||||
assert not result.ret
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
node.assert_attr(skipped=1, tests=1)
|
||||
|
@ -536,7 +594,7 @@ class TestPython:
|
|||
fnode = tnode.find_first_by_tag("skipped")
|
||||
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(
|
||||
"""
|
||||
import sys
|
||||
|
@ -549,13 +607,14 @@ class TestPython:
|
|||
assert 0
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse()
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
tnode = node.find_first_by_tag("testcase")
|
||||
assert len(tnode.find_by_tag("system-err")) == 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(
|
||||
"""
|
||||
import pytest
|
||||
|
@ -564,14 +623,15 @@ class TestPython:
|
|||
pass
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse(family=xunit_family)
|
||||
# assert result.ret
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
node.assert_attr(skipped=0, tests=1)
|
||||
tnode = node.find_first_by_tag("testcase")
|
||||
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(
|
||||
"""
|
||||
import pytest
|
||||
|
@ -580,7 +640,7 @@ class TestPython:
|
|||
pass
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse(family=xunit_family)
|
||||
# assert result.ret
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
node.assert_attr(skipped=0, tests=1)
|
||||
|
@ -589,9 +649,10 @@ class TestPython:
|
|||
fnode = tnode.find_first_by_tag("failure")
|
||||
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")
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse(family=xunit_family)
|
||||
assert result.ret
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
node.assert_attr(errors=1, tests=1)
|
||||
|
@ -600,7 +661,7 @@ class TestPython:
|
|||
fnode.assert_attr(message="collection failure")
|
||||
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"
|
||||
testdir.makepyfile(
|
||||
"""\
|
||||
|
@ -611,14 +672,14 @@ class TestPython:
|
|||
"""
|
||||
% value
|
||||
)
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse()
|
||||
assert result.ret == 1
|
||||
tnode = dom.find_first_by_tag("testcase")
|
||||
fnode = tnode.find_first_by_tag("failure")
|
||||
assert "hx" in fnode.toxml()
|
||||
|
||||
def test_assertion_binchars(self, testdir):
|
||||
"""this test did fail when the escaping wasn't strict"""
|
||||
def test_assertion_binchars(self, testdir, run_and_parse):
|
||||
"""this test did fail when the escaping wasnt strict"""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
|
||||
|
@ -629,23 +690,23 @@ class TestPython:
|
|||
assert M1 == M2
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse()
|
||||
print(dom.toxml())
|
||||
|
||||
def test_pass_captures_stdout(self, testdir):
|
||||
def test_pass_captures_stdout(self, testdir, run_and_parse):
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def test_pass():
|
||||
print('hello-stdout')
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse()
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
pnode = node.find_first_by_tag("testcase")
|
||||
systemout = pnode.find_first_by_tag("system-out")
|
||||
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(
|
||||
"""
|
||||
import sys
|
||||
|
@ -653,13 +714,13 @@ class TestPython:
|
|||
sys.stderr.write('hello-stderr')
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse()
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
pnode = node.find_first_by_tag("testcase")
|
||||
systemout = pnode.find_first_by_tag("system-err")
|
||||
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(
|
||||
"""
|
||||
import pytest
|
||||
|
@ -672,13 +733,13 @@ class TestPython:
|
|||
pass
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse()
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
pnode = node.find_first_by_tag("testcase")
|
||||
systemout = pnode.find_first_by_tag("system-out")
|
||||
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(
|
||||
"""
|
||||
import sys
|
||||
|
@ -692,13 +753,13 @@ class TestPython:
|
|||
pass
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse()
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
pnode = node.find_first_by_tag("testcase")
|
||||
systemout = pnode.find_first_by_tag("system-err")
|
||||
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(
|
||||
"""
|
||||
import sys
|
||||
|
@ -713,7 +774,7 @@ class TestPython:
|
|||
sys.stdout.write('hello-stdout call')
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse()
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
pnode = node.find_first_by_tag("testcase")
|
||||
systemout = pnode.find_first_by_tag("system-out")
|
||||
|
@ -756,7 +817,8 @@ def test_dont_configure_on_slaves(tmpdir):
|
|||
|
||||
|
||||
class TestNonPython:
|
||||
def test_summing_simple(self, testdir):
|
||||
@parametrize_families
|
||||
def test_summing_simple(self, testdir, run_and_parse, xunit_family):
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
import pytest
|
||||
|
@ -774,7 +836,7 @@ class TestNonPython:
|
|||
"""
|
||||
)
|
||||
testdir.tmpdir.join("myfile.xyz").write("hello")
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse(family=xunit_family)
|
||||
assert result.ret
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
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():
|
||||
# Test some more invalid xml chars, the full range should be
|
||||
# tested really but let's just thest the edges of the ranges
|
||||
# intead.
|
||||
# tested really but let's just test the edges of the ranges
|
||||
# instead.
|
||||
# XXX This only tests low unicode character points for now as
|
||||
# there are some issues with the testing infrastructure for
|
||||
# the higher ones.
|
||||
|
@ -907,7 +969,7 @@ def test_logxml_check_isdir(testdir):
|
|||
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(
|
||||
"""\
|
||||
import pytest
|
||||
|
@ -916,13 +978,13 @@ def test_escaped_parametrized_names_xml(testdir):
|
|||
assert char
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse()
|
||||
assert result.ret == 0
|
||||
node = dom.find_first_by_tag("testcase")
|
||||
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(
|
||||
"""
|
||||
import pytest
|
||||
|
@ -931,14 +993,14 @@ def test_double_colon_split_function_issue469(testdir):
|
|||
pass
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse()
|
||||
assert result.ret == 0
|
||||
node = dom.find_first_by_tag("testcase")
|
||||
node.assert_attr(classname="test_double_colon_split_function_issue469")
|
||||
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(
|
||||
"""
|
||||
import pytest
|
||||
|
@ -948,7 +1010,7 @@ def test_double_colon_split_method_issue469(testdir):
|
|||
pass
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse()
|
||||
assert result.ret == 0
|
||||
node = dom.find_first_by_tag("testcase")
|
||||
node.assert_attr(classname="test_double_colon_split_method_issue469.TestClass")
|
||||
|
@ -984,7 +1046,7 @@ def test_unicode_issue368(testdir):
|
|||
log.pytest_sessionfinish()
|
||||
|
||||
|
||||
def test_record_property(testdir):
|
||||
def test_record_property(testdir, run_and_parse):
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
|
@ -996,7 +1058,7 @@ def test_record_property(testdir):
|
|||
record_property("foo", "<1");
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir, "-rwv")
|
||||
result, dom = run_and_parse("-rwv")
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
tnode = node.find_first_by_tag("testcase")
|
||||
psnode = tnode.find_first_by_tag("properties")
|
||||
|
@ -1005,7 +1067,7 @@ def test_record_property(testdir):
|
|||
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(
|
||||
"""
|
||||
def test_record_with_same_name(record_property):
|
||||
|
@ -1013,7 +1075,7 @@ def test_record_property_same_name(testdir):
|
|||
record_property("foo", "baz")
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir, "-rw")
|
||||
result, dom = run_and_parse("-rw")
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
tnode = node.find_first_by_tag("testcase")
|
||||
psnode = tnode.find_first_by_tag("properties")
|
||||
|
@ -1037,7 +1099,7 @@ def test_record_fixtures_without_junitxml(testdir, fixture_name):
|
|||
|
||||
|
||||
@pytest.mark.filterwarnings("default")
|
||||
def test_record_attribute(testdir):
|
||||
def test_record_attribute(testdir, run_and_parse):
|
||||
testdir.makeini(
|
||||
"""
|
||||
[pytest]
|
||||
|
@ -1055,7 +1117,7 @@ def test_record_attribute(testdir):
|
|||
record_xml_attribute("foo", "<1");
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir, "-rw")
|
||||
result, dom = run_and_parse("-rw")
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
tnode = node.find_first_by_tag("testcase")
|
||||
tnode.assert_attr(bar="1")
|
||||
|
@ -1067,7 +1129,7 @@ def test_record_attribute(testdir):
|
|||
|
||||
@pytest.mark.filterwarnings("default")
|
||||
@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
|
||||
"""
|
||||
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 = []
|
||||
if fixture_name == "record_xml_attribute":
|
||||
expected_lines.append(
|
||||
|
@ -1105,7 +1167,7 @@ def test_record_fixtures_xunit2(testdir, fixture_name):
|
|||
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,
|
||||
with nodes from several nodes overlapping, so junitxml must cope with that
|
||||
to produce correct reports. #1064
|
||||
|
@ -1120,7 +1182,7 @@ def test_random_report_log_xdist(testdir, monkeypatch):
|
|||
assert i != 22
|
||||
"""
|
||||
)
|
||||
_, dom = runandparse(testdir, "-n2")
|
||||
_, dom = run_and_parse("-n2")
|
||||
suite_node = dom.find_first_by_tag("testsuite")
|
||||
failed = []
|
||||
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]"]
|
||||
|
||||
|
||||
def test_root_testsuites_tag(testdir):
|
||||
@parametrize_families
|
||||
def test_root_testsuites_tag(testdir, run_and_parse, xunit_family):
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def test_x():
|
||||
pass
|
||||
"""
|
||||
)
|
||||
_, dom = runandparse(testdir)
|
||||
_, dom = run_and_parse(family=xunit_family)
|
||||
root = dom.get_unique_child
|
||||
assert root.tag == "testsuites"
|
||||
suite_node = root.get_unique_child
|
||||
assert suite_node.tag == "testsuite"
|
||||
|
||||
|
||||
def test_runs_twice(testdir):
|
||||
def test_runs_twice(testdir, run_and_parse):
|
||||
f = testdir.makepyfile(
|
||||
"""
|
||||
def test_pass():
|
||||
|
@ -1152,14 +1215,13 @@ 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()
|
||||
first, second = [x["classname"] for x in dom.find_by_tag("testcase")]
|
||||
assert first == second
|
||||
|
||||
|
||||
@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")
|
||||
f = testdir.makepyfile(
|
||||
"""
|
||||
|
@ -1168,13 +1230,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()
|
||||
first, second = [x["classname"] for x in dom.find_by_tag("testcase")]
|
||||
assert first == second
|
||||
|
||||
|
||||
def test_fancy_items_regression(testdir):
|
||||
def test_fancy_items_regression(testdir, run_and_parse):
|
||||
# issue 1259
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
|
@ -1207,7 +1269,7 @@ def test_fancy_items_regression(testdir):
|
|||
"""
|
||||
)
|
||||
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse()
|
||||
|
||||
assert "INTERNALERROR" not in result.stdout.str()
|
||||
|
||||
|
@ -1226,9 +1288,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")
|
||||
log = LogXML(str(path), None)
|
||||
log = LogXML(str(path), None, family=xunit_family)
|
||||
|
||||
class Report(BaseReport):
|
||||
sections = []
|
||||
|
@ -1286,7 +1349,8 @@ def test_url_property(testdir):
|
|||
), "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(
|
||||
"""
|
||||
def test_func1(record_testsuite_property):
|
||||
|
@ -1296,7 +1360,7 @@ def test_record_testsuite_property(testdir):
|
|||
record_testsuite_property("stats", 10)
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse(family=xunit_family)
|
||||
assert result.ret == 0
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
properties_node = node.find_first_by_tag("properties")
|
||||
|
@ -1334,14 +1398,16 @@ def test_record_testsuite_property_type_checking(testdir, junit):
|
|||
|
||||
|
||||
@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:
|
||||
testdir.makeini(
|
||||
"""
|
||||
[pytest]
|
||||
junit_suite_name={}
|
||||
junit_suite_name={suite_name}
|
||||
junit_family={family}
|
||||
""".format(
|
||||
suite_name
|
||||
suite_name=suite_name, family=xunit_family
|
||||
)
|
||||
)
|
||||
expected = suite_name
|
||||
|
@ -1355,13 +1421,13 @@ def test_set_suite_name(testdir, suite_name):
|
|||
pass
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse(family=xunit_family)
|
||||
assert result.ret == 0
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
node.assert_attr(name=expected)
|
||||
|
||||
|
||||
def test_escaped_skipreason_issue3533(testdir):
|
||||
def test_escaped_skipreason_issue3533(testdir, run_and_parse):
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
|
@ -1370,20 +1436,26 @@ def test_escaped_skipreason_issue3533(testdir):
|
|||
pass
|
||||
"""
|
||||
)
|
||||
_, dom = runandparse(testdir)
|
||||
_, dom = run_and_parse()
|
||||
node = dom.find_first_by_tag("testcase")
|
||||
snode = node.find_first_by_tag("skipped")
|
||||
assert "1 <> 2" in snode.text
|
||||
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(
|
||||
"""
|
||||
[pytest]
|
||||
junit_log_passing_tests=False
|
||||
junit_logging=system-out
|
||||
"""
|
||||
junit_family={family}
|
||||
""".format(
|
||||
family=xunit_family
|
||||
)
|
||||
)
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
|
@ -1397,7 +1469,7 @@ def test_logging_passing_tests_disabled_does_not_log_test_output(testdir):
|
|||
logging.warning('hello')
|
||||
"""
|
||||
)
|
||||
result, dom = runandparse(testdir)
|
||||
result, dom = run_and_parse(family=xunit_family)
|
||||
assert result.ret == 0
|
||||
node = dom.find_first_by_tag("testcase")
|
||||
assert len(node.find_by_tag("system-err")) == 0
|
||||
|
|
Loading…
Reference in New Issue