如何完善Python脚本以生成指定格式的Junit XML?
Great to hear you've already built a base Python script for generating JUnit XML! Let's walk through two reliable approaches to refine it and produce the exact structure you shared—whether you prefer using a dedicated library (for simplicity) or Python's built-in tools (for no external dependencies).
Option 1: Use the junit-xml Library (Simplest Approach)
This library is purpose-built for creating JUnit XML, so it handles most formatting details out of the box.
First, install it if you haven't:
pip install junit-xml
Then, here's a script that generates your exact desired XML:
from junit_xml import TestSuite, TestCase # Create test cases test_cases = [ # Normal test case with no status TestCase("testcase09"), # Skipped test case TestCase("testcase10", skipped=True), # Failed test case to be updated with failure details TestCase("testcase11") ] # Add failure details to the third test case test_cases[2].add_failure(message="Failed 1 times.", failure_type="AssertionFailure") # Create the test suite with name and execution time test_suite = TestSuite("Scenario3", test_cases, time=0.015) # Write the XML to a file with UTF-8 encoding with open("test_results.xml", "w") as f: TestSuite.to_file(f, [test_suite], encoding="UTF-8")
When you run this, it will output XML that matches your sample—including the CDATA section for the failure message (the library handles this automatically).
Option 2: Use Python's Built-in xml.etree.ElementTree (No External Dependencies)
If you want to avoid third-party libraries, Python's standard XML module works well. You'll just need to handle a few details manually, like the CDATA section.
Here's a script that replicates your target format:
import xml.etree.ElementTree as ET from xml.dom import minidom # Create the root <testsuites> element testsuites = ET.Element("testsuites") # Create the <testsuite> element with required attributes testsuite = ET.SubElement(testsuites, "testsuite", name="Scenario3", time="0.015") # Add the first test case (no status) ET.SubElement(testsuite, "testcase", name="testcase09") # Add the skipped test case testcase10 = ET.SubElement(testsuite, "testcase", name="testcase10") ET.SubElement(testcase10, "skipped") # Add the failed test case with CDATA message testcase11 = ET.SubElement(testsuite, "testcase", name="testcase11") failure = ET.SubElement(testcase11, "failure", type="AssertionFailure") # Workaround to add CDATA (ElementTree doesn't support it natively) cdata = minidom.CDATASection("Failed 1 times.") failure.append(ET.fromstring(cdata.toxml())) # Generate formatted, human-readable XML xml_str = ET.tostring(testsuites, encoding="UTF-8", method="xml") pretty_xml = minidom.parseString(xml_str).toprettyxml(indent=" ") # Write to file with UTF-8 encoding with open("test_results.xml", "w", encoding="UTF-8") as f: f.write(pretty_xml)
Key Notes for Both Approaches:
- Encoding: Always specify
UTF-8to match your sample XML declaration. - Time Attribute: For the built-in approach, pass the time as a string (e.g.,
"0.015"); thejunit-xmllibrary accepts floats directly. - Failure Handling: Ensure the
failureelement includes the correcttypeattribute, and use CDATA for error messages to safely handle special characters. - Formatting: Use
minidom'stoprettyxmlmethod (as shown in the second example) to get clean, indented XML like your sample.
内容的提问来源于stack exchange,提问作者Manju Ramesh

