Student
Student

Reputation: 531

Editing XML file not working properly

I am using this script to edit an XML file. This XML file is used by TestNG to run test with. It contains information about the test(s) that I want to run. After a test is run, I want to update the XML file with, for example, the location of the test results.

I wrote this script to do what I want;

public void editXMLFile(String nameOfTest, String resultLoc){
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true);
        DocumentBuilder builder;
        Document doc = null;
        try {
            builder = factory.newDocumentBuilder();
            doc = builder.parse("testng.xml");

            NodeList tests = doc.getElementsByTagName("test");
            Element test = null;
            for (int i = 0; i < tests.getLength(); i++) {
                test = (Element) tests.item(i);
                String testNames = test.getAttribute("name");
                if (testNames.equals(nameOfTest)) {
                    //System.out.println("Found element!");
                    NodeList params = test.getElementsByTagName("parameter");
                    Element runType = null, baselineLocation = null;
                    for (int i1 = 0; i1 < params.getLength(); i1++) {
                        runType = (Element) params.item(i1);
                        String paramNames = runType.getAttribute("name");
                        if (paramNames.equalsIgnoreCase("runType")) {
                            //System.out.println("Found the runType");
                            if (runType.getAttribute("value").equalsIgnoreCase(
                                    "baseline")) {
                                for (int j = 0; j < params.getLength(); j++) {
                                    baselineLocation = (Element) params.item(j);
                                    if (baselineLocation.getAttribute("name")
                                            .equalsIgnoreCase("baselineLocation")) {
                                        //System.out.println("Found baselineLocation!");
                                        runType.setAttribute("value", "actual");
                                        baselineLocation.setAttribute("value", resultLoc);
                                        System.out.println("resultLoc = " + resultLoc);
                                        System.out.println("Test name = " + _testName);
                                        // Prepare the DOM document for writing
                                        Source source = new DOMSource(doc);

                                        // Prepare the output file
                                        File file = new File("C:/Users/sfd/Desktop/testng.xml");
                                        StreamResult sr = new StreamResult(file);
                                        Result result = sr;


                                        // Write the DOM document to the file
                                        Transformer xformer = TransformerFactory
                                                .newInstance().newTransformer();
                                        xformer.transform(source, result);

                                    }
                                }
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

This is the XML file;

<?xml version="1.0" encoding="UTF-8"?>
<suite name="Test Suite Name" parallel="none">
<listeners>
    <listener class-name="testng.MyListener"></listener>
</listeners>
<test name="Test NOT on localhost">
    <parameter name="Browser" value="chrome"/> <!-- chrome or firefox or IE or Android Native-->
    <parameter name="url" value='' /> <!-- URL of the webpage you want to test -->
    <parameter name="CSV" value="testdata.csv"/> <!-- Location of the CSV file that you want to run tests with -->
    <parameter name="resultLocation" value="C:\Users\sfd\Desktop"/> <!-- TestNG will create two folder in this location, screenshots and test-output-datestamp -->
    <parameter name="baselineLocation" value=""/> <!-- Location of the baseline location -->
    <parameter name="runType" value="baseline" /> <!--  actual or baseline . baseline = first run. actual is second run, to do a compare for example -->
    <classes>
      <class name="testng.runTest"></class>
    </classes>
  </test> <!-- Test CAN YOU SEE THIS?-->
  <test name="Test localhost">
    <parameter name="Browser" value="chrome"/> <!-- chrome or firefox or IE or Android Native-->
    <parameter name="url" value='' />
    <parameter name="CSV" value="testdata.csv"/>
    <parameter name="resultLocation" value="C:\Users\sfd\Desktop\testmap"/> <!-- TestNG will create two folder in this location, screenshots and test-output-datestamp -->
    <parameter name="baselineLocation" value=""/> <!-- Location of the baseline run. leave value empty. This will be filled in by TestNG itself. -->
    <parameter name="runType" value="baseline" /> <!--  actual or baseline . baseline = first run. actual is second run, to do a compare for example -->
    <classes>
      <class name="testng.runTest"></class>
    </classes>
  </test>
</suite> <!-- Suite end of suite -->

The problem that I am facing is the follow; when I only have 1 test in the xml file, it works fine. But when I have more than 1 test in the XML file, only the last test will be updated. The baselineLocation of both tests should be updated, while only the last test gets updated. I think there is a flaw in the logic of this method, but I am not sure what exactly.

Upvotes: 0

Views: 304

Answers (1)

Vin
Vin

Reputation: 124

If you are calling the editXMLFile() multiple times to update for multiple test names, there is a problem. You are writing the updated XML file within the method. The XML created by one test name match will get overwritten by the subsequent test name match condition.

You need to defer writing the XML file till you have the doc object updated with all test names.

One possible solution to refactor

private Document createXMLDocument() // move the XML document for test.xml logic into this method

public Document editXMLFile(Document doc, String nameOfTest, String resultLoc) // assuming you don't have any constraint on method signature. Return back updated Document object.

private Document getUpdatedXMLDocument(Document doc) // move your filtering condition logic into this. Call this from editXMLFile()

private void writeUpdatedXMLFile(Document doc) // move out the logic of writing the new XML file here. Call this after final call to editXMLFile()

Hope this gives a fair idea.

Upvotes: 1

Related Questions