I am trying to create an XML file using a groovy script for running tests using mvn+TestNG, so the XML should have a basic testNG.xml structure. The groovy script will be executed in the Jenkins pipeline. Test methods and test classes are received in JSON format from external service and inserted into the XML for further execution. XML should be saved and then executed by maven. First I have tried to use MarkupBuilder, but there is an issue regarding this class in Jenkins https://issues.jenkins.io/browse/JENKINS-32766 so it's not compiling. So I decided to try DOMBuilder, but I don't know how to set the DOCTYPE parameter for my XML. Moreover, nodes aren't formatted well by DOMBuilder - code is written in one line without line breakers.
What I am trying to get
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name='Recommended tests to run'>
<test name='tests'>
<classes>
<class name='com.epam.automation.api.AverageScoreTest'>
<methods>
<include name='averageScoreUpdateInterviewType' />
</methods>
</class>
<class name='com.epam.automation.api.DifferentTypesFilesAttachmentTest'>
<methods>
<include name='differentTypesFilesInterviewTest' />
</methods>
</class>
<class name='com.epam.automation.api.smartscheduling.STSRecruitersTest'>
<methods>
<include name='suggestedSlotsWithInterviewsDefaultTest' />
</methods>
</class>
</classes>
</test>
</suite>
Code sample using MarkupBuilder.
import groovy.json.JsonSlurper
// final String url = "http://host.docker.internal:8091/api/agents/hit-auto/plugins/test2code/data/tests-to-run"
// final String response =
// sh(script: "curl -H 'Accept: application/json' -H 'Content-Type:application/json' -w '
' -X GET $url", returnStdout: true).trim()
final String response = "{
" +
" "byType": {
" +
" "AUTO": [
" +
" "",
" +
" "[engine:testng]/[class:com.epam.automation.api.AverageScoreTest]/[method:averageScoreUpdateInterviewType[COMPLETED]]",
" +
" "[engine:testng]/[class:com.epam.automation.api.DifferentTypesFilesAttachmentTest]/[method:differentTypesFilesInterviewTest]",
" +
" "[engine:testng]/[class:com.epam.automation.api.smartscheduling.STSRecruitersTest]/[method:suggestedSlotsWithInterviewsDefaultTest]"
" +
" ]
" +
" },
" +
" "totalCount": 33
" +
"}"
JsonSlurper json = new JsonSlurper()
Map<String,String> parseJson = json.parseText(response) as Map
if (parseJson.totalCount > 0){
ArrayList tests = parseJson.byType.AUTO
Map<String,String> classMethodMap = [:]
def patternMethod = ~/(?<=method:)([w]+)/
def patternClass = ~/(?<=class:)(.*?)(?=])/
for (String item : tests) {
def matchMethod = (item =~ patternMethod)
def matchClass = (item =~ patternClass)
if (matchClass && matchMethod) {
classMethodMap.put(matchMethod.group(1), matchClass.group(1))
}
}
classMethodMap.each{ k, v -> println "${k}:${v}" }
def writer = new StringWriter()
def location = "C:\Users\Valiantsin_Dorum\Documents\hit-automation\test-suites\recommended_tests.xml"
def fileXmlOut = new File(location)
if (fileXmlOut.exists()){
boolean fileSuccessfullyDeleted = new File(location).delete()
println fileSuccessfullyDeleted
}
def xml = new MarkupBuilder(writer)
def helper = new MarkupBuilderHelper(xml)
helper.xmlDeclaration([version:'1.0', encoding:'UTF-8'])
helper.yieldUnescaped """<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >"""+"
"
xml.suite(name:'Recommended tests to run'){
test(name:'tests'){
classes(){
classMethodMap.forEach{method,classes -> /class/(name:classes){
methods(){/include/(name:method)
}
}
}
}
}
}
fileXmlOut << writer.toString()
Code sample using DomBuilder.
Document doc = DOMBuilder.newInstance().createDocument()
Element suite = doc.createElement('suite')
suite.setAttribute('name', 'Recommended suite')
doc.appendChild(suite)
Element test = doc.createElement('test')
test.setAttribute('name', 'Recommended tests')
suite.appendChild(test)
classMethodMap.forEach() { method,testClasses ->
Element classes = doc.createElement('classes')
test.appendChild(classes)
Element testClass = doc.createElement('class')
testClass.setAttribute('name',testClasses)
classes.appendChild(testClass)
Element testMethod = doc.createElement('include')
testMethod.setAttribute('name',method)
testClass.appendChild(testMethod)
}
println doc.getDoctype();
DOMSource source = new DOMSource(doc);
FileWriter write = new FileWriter(new File(location));
StreamResult result = new StreamResult(write);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(source, result)
question from:
https://stackoverflow.com/questions/65625856/how-to-set-doctype-in-xml-file-using-groovy-dombuilder 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…