burnst14
burnst14

Reputation: 115

How can I reuse methods in TestNG?

I am an intern automating testing of a large corporation's website and honestly, I'm in over my head. I'm trying to learn everything and use it at the same time and no one else in this firm knows how to use the tools I'm using, so I don't have many options as far as asking people for help. So this may be fairly obvious. Anyway, I'm using TestNG with Selenium in Eclipse, using Java. I wrote a pretty significant number of tests before I found TestNG, so now I'm trying to rewrite them all with TestNG because it gives much better feedback and doesn't fail the whole test because of one test. The problem is, my tests have a lot of methods that I reuse many, many times. One of my tests is about 140 lines of code and if I wrote it with my current knowledge of TestNG, it'd be 1000's of lines of code. So my question is, is there a way to call the same method repeatedly and throughout a test with TestNG or am I condemned to copy and pasting for hours?

TL;DR - How can I reuse code with TestNG? Can you point me toward some examples of effective and efficient structure using TestNG?

Here is some of my current code without TestNG:

public static void sideBarNavAll(WebDriver driver, String site){
    driver.get(site);
    List<WebElement> topNavLinks = driver.findElement(By.className("topNavigationMenu")).findElements(By.className("menuLink"));
    int numLinks = topNavLinks.size();
    String[] topNavTitlesAndLinks = new String[numLinks*2];
    topNavTitlesAndLinks = createArray(topNavLinks);
    System.out.println("Filled titles and links array.");
    for (int x=1; x<topNavTitlesAndLinks.length; x+=2){
        driver.get(topNavTitlesAndLinks[x]);
        openDropDowns(driver);
        try{
            List<WebElement> menu = driver.findElement(By.className("asideNavigationMenu")).findElements(By.className("itemLink"));
            String[] menuArray = new String[menu.size()*2];
            menuArray = createArray(menu);
            checkValidity(menuArray, driver);
        }
        catch (Exception e){
            if (topNavTitlesAndLinks[x-1].contains("Endodontics")){
                WebElement element = driver.findElement(By.linkText("Endodontics"));
                Actions action = new Actions(driver);
                action.moveToElement(element).perform();
                WebElement subElement = driver.findElement(By.partialLinkText("Access"));
                action.moveToElement(subElement);
                action.click();
                action.perform();
                openDropDowns(driver);
                List<WebElement> menu = driver.findElement(By.className("asideNavigationMenu")).findElements(By.className("itemLink"));
                String[] menuArray = new String[menu.size()*2];
                menuArray = createArray(menu);
                checkValidity(menuArray, driver);
            }
        }
    }
}

public static void checkValidity(String[] array, WebDriver driver){
    String partialURL = "";
    int brokenLinks = 0;
    for (int x=1; x<array.length; x+=2){
        partialURL = anonUserSitemapExperience.getPartialURL(driver, array[x]);
        if (partialURL.isEmpty()){
            System.err.println("The link \""+array[x]+"\" intended for the "+array[x-1]+" page is either broken or an external site.");
            brokenLinks++;
            brokenLinksTot++;
        }
        else{
            int found = anonUserSitemapExperience.findMatch(array, array.length, partialURL);
            if (found<1){
                System.err.println("A match was not found for "+array[x-1]+".\n"+array[x]+"\n"+partialURL);
                brokenLinks++;
                brokenLinksTot++;
            }
        }
    }
    System.err.println("\n"+brokenLinks+" broken link(s) was/were found.\n");
}

public static void openDropDowns(WebDriver driver){
    List<WebElement> dropdownArrows = driver.findElements(By.className("dropdownToggler"));
    Iterator<WebElement> itr = dropdownArrows.iterator();
    while(itr.hasNext()){
        try{
            itr.next().click();
        }
        catch(ElementNotVisibleException e){
        }
    }
}

public static String[] createArray(List<WebElement> list){
    String[] linkArray = new String[list.size()*2];
    int counter = 0;
    for (int x=1; x<linkArray.length; x+=2){
        linkArray[x] = list.get(counter).getAttribute("href");
        try{
            linkArray[x] = linkArray[x].replaceAll("%C2%AE", "®");
            linkArray[x] = linkArray[x].replaceAll("%20", " ");
            linkArray[x] = linkArray[x].replaceAll("%27", "'");
            linkArray[x] = linkArray[x].replaceAll("%C3%A4", "ä");
            linkArray[x] = linkArray[x].replaceAll("%C3%B6", "ö");
            linkArray[x] = linkArray[x].replaceAll("%C3%BC", "ü");
            linkArray[x] = linkArray[x].replaceAll("%C3%84", "Ä");
            linkArray[x] = linkArray[x].replaceAll("%C3%96", "Ö");
            linkArray[x] = linkArray[x].replaceAll("%C3%9C", "Ü");
            linkArray[x] = linkArray[x].replaceAll("%E2%80%93", "–");
            linkArray[x] = linkArray[x].replaceAll("%E2%84%A2", "™");
            linkArray[x] = linkArray[x].replaceAll("%25", "%");
            counter++;
        }
        catch(Exception e){
        }
    }
    int counter2 = 0;
    for (int x=0; x<linkArray.length; x+=2){
        linkArray[x] = list.get(counter2).getText();
        counter2++;
    }
    return linkArray;
}

}

The method openDropDowns is called multiple times and the checkValidity method has a huge for loop in it (over 1300 iterations total). I would like to be able to write what the for loop does into a method, then call it over and over so that I can get a pass/fail from TestNG. Hopefully this clarifies what I'm asking for. Thanks!

Upvotes: 1

Views: 3333

Answers (2)

Greg
Greg

Reputation: 4035

@burnst14, here is an example of a test case i have, this is an End-to-End scenario, it covers sequentially executing 5 REST API calls. Don't worry about what exactly it is doing, just know that I am creating methods, and reusing them in multiple tests. I am sure some will disagree with the way i have done a few things below, but know that each method below, is being reused multiple times. In fact, the structure is pretty much repeated, the "RunProvision()" is what often gets replaced.

@DataProvider(name = "data1")
public Object[][] data1() throws Exception{
    Object[][] retObj = Utils.getExcelData(DATAFILE, sheet, "xxx", "yyy");
    return retObj;
}


@Test(priority=1, dataProvider="data1", groups={"group1"})
public void TestCase1(Integer id, Map<String,String> hmData, ITestContext ctx) throws Exception {
    try {
        Utils.logTitle(1);
        setAttribute(hmData, ctx);
        populateMaps(hmData);
        runProvision();
        buildSummaryPassed();
    } catch (Exception e) {
        buildReporterSummary(e.getMessage());
        buildSummaryFailed(e.getMessage());
    }
}

Upvotes: 1

Cathal
Cathal

Reputation: 1338

What you're looking for is the Page Object Model. Using this model its easy to maintain and reuse your classes and methods as much as possible.

The basic concept is that you create a page object for each page you want to test . This page object encapsulates all information and methods for the page and if the page changes in anyway you'll only have to update the code here. This in turn allows your TestNG tests to focus solely on the actual testing. Theres loads of information about the page object model available online, here is one i had bookmarked.

Upvotes: 0

Related Questions