Created
September 7, 2017 07:24
-
-
Save sjethvani/d8538c41f351017c614e6d0b64f64502 to your computer and use it in GitHub Desktop.
Java Program to generate consolidated testng-results.xml from two executions (Normal execution testng-results.xml & Rerun failing tests execution testng-results.xml)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.mergeTestNgXml; | |
import java.util.List; | |
import java.io.BufferedWriter; | |
import java.io.File; | |
import java.io.FileInputStream; | |
import java.io.FileWriter; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.io.InputStreamReader; | |
import java.io.Reader; | |
import java.io.StringWriter; | |
import java.io.Writer; | |
import java.util.ArrayList; | |
import javax.xml.parsers.DocumentBuilder; | |
import javax.xml.parsers.DocumentBuilderFactory; | |
import javax.xml.parsers.ParserConfigurationException; | |
import javax.xml.transform.OutputKeys; | |
import javax.xml.transform.Transformer; | |
import javax.xml.transform.TransformerException; | |
import javax.xml.transform.TransformerFactory; | |
import javax.xml.transform.dom.DOMSource; | |
import javax.xml.transform.stream.StreamResult; | |
import javax.xml.xpath.XPath; | |
import javax.xml.xpath.XPathConstants; | |
import javax.xml.xpath.XPathExpressionException; | |
import javax.xml.xpath.XPathFactory; | |
import org.apache.log4j.LogManager; | |
import org.apache.log4j.Logger; | |
import org.w3c.dom.Document; | |
import org.w3c.dom.Element; | |
import org.w3c.dom.Node; | |
import org.w3c.dom.NodeList; | |
import org.xml.sax.InputSource; | |
import org.xml.sax.SAXException; | |
public class MergeTestNgXmlsAfterRetryingFailingTests | |
{ | |
public static Logger LOG = LogManager.getLogger(MergeTestNgXmlsAfterRetryingFailingTests.class); | |
public static void main(String[] testNgFiles) throws ParserConfigurationException, SAXException, IOException, TransformerException, XPathExpressionException | |
{ | |
if (testNgFiles.length != 3) | |
{ | |
System.out.println("No of parameters you passed as args is :- " + testNgFiles.length + " however it should be 3 only"); | |
System.out.println("Usage: run this programm with 3 arguments . Arguments : <testNg primaryFile> <testNg secondaryFile> <testNg mergeExpectedFile>"); | |
return; | |
} | |
LOG.info("Merging testng-files Start"); | |
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); | |
DocumentBuilder builder = dbFactory.newDocumentBuilder(); | |
LOG.info("Primary testng-results File is : "+testNgFiles[0]); | |
InputStream inputStream = new FileInputStream(new File(testNgFiles[0])); | |
Reader reader = new InputStreamReader(inputStream, "UTF-8"); | |
InputSource is = new InputSource(reader); | |
is.setEncoding("UTF-8"); | |
Document doc1 = builder.parse(is); //"test-output/testng-results-base.xml" | |
LOG.info("Secondary(failed) testng-results File is : "+testNgFiles[1]); | |
inputStream = new FileInputStream(new File(testNgFiles[1])); | |
reader = new InputStreamReader(inputStream, "UTF-8"); | |
is = new InputSource(reader); | |
is.setEncoding("UTF-8"); | |
Document doc2 = builder.parse(is); //"test-output/testng-results-retry.xml" | |
doc1.normalizeDocument(); | |
doc2.normalizeDocument(); | |
XPath pathToTests = XPathFactory.newInstance().newXPath(); | |
Element testNGResultTag = (Element) pathToTests.evaluate("/testng-results", doc1.getDocumentElement(), XPathConstants.NODE); | |
String skiipedCount = testNGResultTag.getAttribute("skipped"); | |
String failedCount = testNGResultTag.getAttribute("failed"); | |
String passedCount = testNGResultTag.getAttribute("passed"); | |
// NodeList of <test> tags | |
NodeList testTagNodeList_primaryFile = (NodeList) pathToTests.evaluate("/testng-results/suite/test", doc1.getDocumentElement(), XPathConstants.NODESET); | |
NodeList testTagNodeList_secondaryFile = (NodeList) pathToTests.evaluate("/testng-results/suite/test", doc2.getDocumentElement(), XPathConstants.NODESET); | |
// fetching 'name' attributes of all <test> tags from secondary(failed testng-results.xml) file & storing them in list | |
ArrayList<String> testNameList_secondaryFile = new ArrayList<>(); | |
for (int j = 0; j < testTagNodeList_secondaryFile.getLength(); j++) | |
{ | |
Element testTagElement = (Element) testTagNodeList_secondaryFile.item(j); | |
String testName = testTagElement.getAttribute("name"); | |
testNameList_secondaryFile.add(testName); | |
} | |
List<Node> testMethodWithFailStatusNodeListTobedeleted_primaryFile = new ArrayList<Node>(); | |
List<Node> testMethodWithSkipStatusNodeListTobedeleted_primaryFile = new ArrayList<Node>(); | |
// iterating through all '<test>' tags of primary file | |
for (int j = 0; j < testTagNodeList_primaryFile.getLength(); j++) | |
{ | |
//check if '<test>' tag of primary file exists in secondary file | |
Element testTagElement_primaryFile = (Element) testTagNodeList_primaryFile.item(j); | |
String testName_primaryFile = testTagElement_primaryFile.getAttribute("name"); | |
String testName_secondaryFile = null ; | |
boolean testFound = false; | |
for (int i = 0; i < testNameList_secondaryFile.size(); i++) | |
{ | |
if(testNameList_secondaryFile.get(i).contains(testName_primaryFile)) | |
{ | |
testFound = true; | |
testName_secondaryFile = testNameList_secondaryFile.get(i); | |
break; | |
} | |
} | |
// '<test>' tag of primary file is found in secondary file | |
if(testFound) | |
{ | |
NodeList testMethodTagNodeList_primaryFile = (NodeList) pathToTests.evaluate(getTestmethodXpath(testName_primaryFile), doc1.getDocumentElement(), XPathConstants.NODESET); | |
NodeList testMethodTagNodeList_secondaryFile = (NodeList) pathToTests.evaluate(getTestmethodXpath(testName_secondaryFile), doc2.getDocumentElement(), XPathConstants.NODESET); | |
// iterating through all '<test-method>' tags of above '<test>' tag of secondary file | |
for (int i = 0; i < testMethodTagNodeList_secondaryFile.getLength(); i++) | |
{ | |
Element testMethodTag_secondaryFile = (Element) testMethodTagNodeList_secondaryFile.item(i); | |
Element testMethodTag_primaryFile = getTestMethodElementByAttribute(testMethodTagNodeList_primaryFile, "name", testMethodTag_secondaryFile.getAttribute("name")); | |
// if '<test-method>' tag under primary file has status='FAIL' but same 'test-method' tag under secondary file has status='PASS' then override 'PASS' status over 'FAIL' | |
if(testMethodTag_primaryFile != null && testMethodTag_secondaryFile != null) | |
{ | |
if(testMethodTag_primaryFile.getAttribute("status").equals("FAIL") && testMethodTag_secondaryFile.getAttribute("status").equals("PASS")) | |
{ | |
Node n1 = (Node) doc1.importNode(testMethodTag_secondaryFile, true); | |
testMethodTagNodeList_primaryFile.item(0).getParentNode().appendChild(n1); | |
testMethodWithFailStatusNodeListTobedeleted_primaryFile.add(testMethodTag_primaryFile); | |
} | |
// if '<test-method>' tag under primary file has status='SKIP' but same 'test-method' tag under secondary file has status='PASS' then override 'PASS' status over 'SKIP' | |
else if(testMethodTag_primaryFile.getAttribute("status").equals("SKIP") && testMethodTag_secondaryFile.getAttribute("status").equals("PASS")) | |
{ | |
Node n1 = (Node) doc1.importNode(testMethodTag_secondaryFile, true); | |
testMethodTagNodeList_primaryFile.item(0).getParentNode().appendChild(n1); | |
testMethodWithSkipStatusNodeListTobedeleted_primaryFile.add(testMethodTag_primaryFile); | |
} | |
} | |
} | |
} | |
} | |
// delete all '<test-method>' nodes from primary file now | |
for( int i=0; i<testMethodWithFailStatusNodeListTobedeleted_primaryFile.size(); i++ ) { | |
Node node = testMethodWithFailStatusNodeListTobedeleted_primaryFile.get( i ); | |
node.getParentNode().removeChild( node ); | |
} | |
// delete all '<test-method>' nodes from primary file now | |
for( int i=0; i<testMethodWithSkipStatusNodeListTobedeleted_primaryFile.size(); i++ ) { | |
Node node = testMethodWithSkipStatusNodeListTobedeleted_primaryFile.get( i ); | |
node.getParentNode().removeChild( node ); | |
} | |
// setting pass , fail , skip count | |
testNGResultTag.setAttribute( "skipped", ""+(Integer.parseInt(skiipedCount) - testMethodWithSkipStatusNodeListTobedeleted_primaryFile.size()) ); | |
testNGResultTag.setAttribute( "failed", ""+(Integer.parseInt(failedCount) - testMethodWithFailStatusNodeListTobedeleted_primaryFile.size()) ); | |
testNGResultTag.setAttribute( "passed", ""+(Integer.parseInt(passedCount) + testMethodWithFailStatusNodeListTobedeleted_primaryFile.size() + testMethodWithSkipStatusNodeListTobedeleted_primaryFile.size()) ); | |
// generating consolidated merge file | |
Transformer transformer = TransformerFactory.newInstance().newTransformer(); | |
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); | |
StreamResult result = new StreamResult(new StringWriter()); | |
DOMSource source = new DOMSource(doc1); | |
transformer.transform(source, result); | |
Writer output = null; | |
output = new BufferedWriter(new FileWriter(testNgFiles[2])); //"/test-output/consolidatedResults/testng-mergedResults.xml" | |
String xmlOutput = result.getWriter().toString(); | |
output.write(xmlOutput); | |
output.close(); | |
LOG.info("Merging testng-files Completed"); | |
LOG.info("Merged testng-results file is " + testNgFiles[2]); | |
} | |
/* | |
* returns 'test-method' element matching attribute with its value passed as input | |
*/ | |
private static Element getTestMethodElementByAttribute(NodeList testMethodNodeList, String attributeName , String attributeValueToBeMatched) | |
{ | |
for (int k = 0; k < testMethodNodeList.getLength(); k++) | |
{ | |
Element testMethodElement = (Element) testMethodNodeList.item(k); | |
String testMethodElementAttributeValue = testMethodElement.getAttribute(attributeName); | |
if(testMethodElementAttributeValue.equals(attributeValueToBeMatched)) | |
{ | |
return testMethodElement; | |
} | |
} | |
return null; | |
} | |
/* | |
* returns xpath of 'test-method' attribute by 'test' tag's name attribute | |
*/ | |
private static String getTestmethodXpath(String testName) | |
{ | |
String TEST_METHOD_XPATH = "/testng-results/suite/test[@name ='" + testName | |
+ "']/class/test-method"; | |
return TEST_METHOD_XPATH; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment