Java Automation framework

Java Automation framework

My personal java project and it's uses

ยท

10 min read

Yes, this is where my automation project starting point other than my automation profession.

As all automation framework has their own unique features, I believe this also has some unique features.

Before, I want to accept the fact that this automation framework has poor code that exists, but it created some Unique/Nice methods to handle things during automation. Started to build this just with training after onboarding, some features may already be existing in some other frameworks which I don't know (Please mention any in the comments) but I still, learned a lot from this project.

Below I'll share its features, the mistakes I made and what I learned from this.

Features

Below are the features, which I'll explain in detail.

Users can start automating any website using a URL

Many frameworks are designed by only using certain URLs and their modifications. I just want to give a change so, I've created it by giving a global URL which can be changed later. With this, anyone can give a quick start to automation.

Where it'll be useful: It is useful when developing new screens and pages which can be accessed with direct or cookie links, to automate repetitive tasks.

Start writing your own test cases using existing methods

There are some common methods, which can be used to click, access, validate, send inputs etc., just by giving XPath, id, class name so on...

Users do not need to write repetitive methods like wait, highlight, or validate etc., It'll all be in existing methods from the base class itself. Anyone can use it by passing locators as parameters when calling function names. An example of such a method is below,

public void clickElement(By Locater, int Seconds, String LogStatement) {        
try {
            waitForPageToBeReady();
            waitForClickableElements(Locater, Seconds);
            TempElement = driver.findElement(Locater);
            highLighterMethod(TempElement);
            TempElement.click();
            logPass(LogStatement);
        } catch (Exception e) {
            logError(e.getMessage());
            e.printStackTrace();
        }
    }

Note: - Above is just an example, with method overloading arguments can be reduced and can be used according to user needs.

When clickElement is called the user needs to pass Locater, seconds to wait and what needs to be logged.

During execution, waitForPageToBeReady will apply all default page load waits. After that dynamic wait is applied as passed by the user. Then we are trying to highlight a given element to see what's happening during execution. Then the element is clicked and also logged into the report.

If any issues happen, they'll be caught by catch block and we'll get a clear error in the console and also in the report logs. This method is common for all clickable page elements. Most lines of code can be avoided with these pre-defined methods. There are many methods like this, we'll see them in a separate section.

Multi-Browser execution

All frameworks have this. Then what is special about this?

For this, No need to download the latest driver versions according to browsers. Whenever execution is started, with POM dependencies It'll download a new driver if we do not have one already, as per the browser version and browser specified by the user for execution. Once done it'll be saved in the cache until the browser version is updated or the cache is cleared.

Multiple options are available. This is available globally and can pass as a parameter to customize each test case.

Right now in this project, an external webdriver manager is used. But when I'm writing this, Selenium 4.6 is released and the good news is browsers are handled by selenium itself ๐ŸŽ‰. This will be upgraded in my redesign (explained below in detail).

Mobile view execution

Yes, In-browser mobile view execution is also supported. Some websites act differently on mobile browser scenarios. Those things can be automated with this feature. Users need to give mobile models from browser developer options. Currently, few are only supporting.

Headless and Incognito Mode

We can turn on Headless mode if needed, globally or for each test case that is executed in the background meaning, NO UI is presented during execution. Finally, results will be generated with reports and also displayed in the console.

Incognito mode is to avoid cache so, for every test case it'll be like executing freshly. As same as headless, this configuration can be given globally for all test cases or can be given to particular selected test cases.

Extent report

After all automated test case execution definitely we need results. For that here I've used Extent reports to generate results in HTML format so it can be opened in any browser. So, what are the special things I've added?

  1. All Automation actions are logged in the report, from browser start to close.

  2. User can generate both temporary reports to avoid miscellaneous results which will replace each report after execution and also can save permanent results which has the time of execution started which is attached to the name of the results.

  3. Warnings are given separately in the report to avoid unnecessary failures.

  4. For failures, screenshots are automatically logged in along with Error messages from the console. Users can give custom screenshots to log it in the report.

  5. Users can set reporting Theme as Dark which everyone knows and Standard which means a normal white theme.

Video recording

If the option is enabled, the video is recorded from the browser open to the browser close and will be saved in a separate folder with unique names. These options will be available in the project settings properties file.

Special Methods

  • I've implemented a Custom element highlight color feature. After understanding logic anyone can implement it in their code. Here I got color from properties files applied to the whole framework. After modifying can pass it as a parameter.

    Code snippet:

public void highLighterMethod(WebElement element) {
try {
  if (prop.getProperty("Need_To_HighLight_Element").equalsIgnoreCase("Yes")) {
  waitForPageToBeReady();
  JavascriptExecutor js = (JavascriptExecutor) driver;
  String color = prop.getProperty("HighlightElementColor");
  String arg = "arguments[0].setAttribute('style', 'border: 5px solid " + color + ";');";
  js.executeScript(arg, element);
        try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
              js.executeScript("arguments[0].style.border='0px solid blue'", element);
            }
        } catch (Exception m) {
            logError(m.getMessage());
            m.printStackTrace();
        }
    }
  • Method to Verify each URL in a page working fine in all pages which return status codes are logged in the report. With that in a single test case, we can find working and non-working URLs with codes returned.
public int statusCode(String argUrl) throws IOException {
        int httpStatusCode = 0;
        try {
            URL url = new URL(argUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.connect();
            httpStatusCode = connection.getResponseCode();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return httpStatusCode;
    }
//Below code is to validate and log it in the report.
    public void performOperationOnAnchor(String NormalOrDetailed) {
        for (int i = 0; i < anchorTag.size(); i++) {
            try {
                String url = anchorTag.get(i).getAttribute("href");
                if (isUrlValid(url)) {
                    int code = statusCode(url);
                    StatusCodes.add(code);
                    if (code == 200) {
                        logHref(url,code);
                    }  else {
                        logHref(url,code);
                    }
                } else {
                    notValidCount = notValidCount + 1;
                    logInfo("[" + url + "]" + " - Not Valid");
                }
                System.out.println("Verified - " + "[" + url + "]");
            } catch (Exception e) {
                logFailException(e.getMessage());
            }
        }
    }
  • User can Capture partial screenshots which mean, by passing an element or locater that particular item is captured as a screenshot that is logged in the report. This method will be helpful in verification steps where validating with a partial screenshot is much more useful.
// This is available only in selenium 4 + releases. 
WebElement Element = driver.findElement(Locater); 
File f = Element.getScreenshotAs(OutputType.FILE);

New try methods

  • Created some methods where the user can give default locator (Xpath, Id, class name, CSS selector) and alternate locators (Xpath, CSS selector etc.,) as a backup, so after a long time, if the default is changed, It'll continue trying to identify the element with alternate locators.

  • Hence the failure of test cases will be reduced to a certain point. This applies to actions like click, send, get, and verify elements. The below code is a sample.

public void clickElement(By Locater, By AlternateLocater, String LogStatement) {
        try {
            waitForPageToBeReady();
            TempElement = driver.findElement(Locater);
            highLighterMethod(TempElement);
            TempElement.click();
            logPass(LogStatement);
        } catch (Exception e) {
            try {
                waitForPageToBeReady();
                TempElement = driver.findElement(AlternateLocater);
                highLighterMethod(TempElement);
                TempElement.click();
                logPass(LogStatement);
                logInfo("Primary Locater Failed, Alternate Passed");
            } catch (Exception m) {
                logInfo("Both Primary, Alternate Locater Failed");
                logError(m.getMessage());
                m.printStackTrace();
            }
        }
    }
  • For Verification of elements, created this default function. By this re-usable verification method, most of the lines can be avoided.
    public boolean verifyElement(By Locater, int Seconds) {
        boolean value = false;
        try {
            waitForPageToBeReady();
            waitForVisibilityOfElement(Locater, Seconds);
            TempElement = driver.findElement(Locater);
            highLighterMethod(TempElement);
            if (TempElement.isDisplayed()) {
                screenshotVerification();
                value = true;
            } else {
                screenshotVerification();
                value = false;
            }
        } catch (Exception e) {
            logError(e.getMessage());
            e.printStackTrace();
            value = false;
        }
        return value;
    }
  • Created a re-usable method where XPath or any locater is no more needed. Yes, the user can give attributes as parameters to access those elements. Let me share a code sample and an example to use it.
public void clickElementUsingAttribute(String AttributeName, String AttributeValue) {
/*
* This method can be used with Class as AttributeName and its value as
* AttributeValue (or) This method can be used with id as AttributeName and its
* value as AttributeValue (or) This method can be used with Any Attribute
* property as AttributeName and its value as AttributeValue Eg :
* data-testid='royal_login_button'.*/

    try {
            waitForPageToBeReady();
        String path = "//*[@" + AttributeName + "='" + AttributeValue + "']";
            TempElement = driver.findElement(By.xpath(path));
            highLighterMethod(TempElement);
            TempElement.click();
        } catch (Exception e) {
            try {
                waitForPageToBeReady();
            String Altpath = "//*[contains(@" + AttributeName + ",'" + AttributeValue + "')]";
                TempElement = driver.findElement(By.xpath(Altpath));
                highLighterMethod(TempElement);
                TempElement.click();
                logInfo("Primary Attribute Failed, Alternate Passed");
            } catch (Exception m) {
                logInfo("Problem in Method : clickElementsUsingAttribute");
                logError(m.getMessage());
                m.printStackTrace();
            }
        }
    }

With the above function, users can pass parameters as AttributeName and AttributeValue which means clickElementUsingAttribute("id", "firstDiv") or clickElementUsingAttribute("class", "firstClassDiv")or not only id and class but also any attribute and its value like, clickElementUsingAttribute("data-testid", "royal_login_button") to click that element. There are similar methods for get, send, and verify etc., By this function, most of the XPath creation can be avoided.

Extras

1. Cross-platform - It'll work in windows and Linux. Initially, there are problems with Linux and I fixed them. Didn't get a chance to test in IOS or Mac's safari browser.

2. Has sample test cases, where pre-defined methods are used as a demonstration and also has comments about how to use it.

3. In branches there are different versions created. There is a lightweight branch, where unnecessary POM dependencies are removed. So the initial setup for automation can be easily done.

4. Entire framework is user-friendly, Easy to start for beginners and for most of the functions there are optional parameters.

For example, Parameters with and without waits, log statements, and Alternate locators are also available. so that users can choose their wish of doing activities with the element.

Learnings from this Project

1. Coding standards and Comment lines are a must, cause when I see my own code now I can't even understand some parts of the code. so it's definitely needed to follow some rules for upcoming projects.

2. Why assertions are important? - Assertions state confidently that application behavior is working as expected. I missed out on these in the project and used "==" to verify most scenarios.

3. POM implementation๐Ÿ˜’ - If you're already experienced in automation testing, you can think about how can someone implement something without a Page object model. Yes, Partially I did that but it's not up to industry standards and also code maintenance is hard. As I said earlier, these are planned to implement in the Framework redesign. Yup, after so many things redesigning from scratch is the only option. Post-completion of that, an article like this will be created with its unique features.

Enhancements

As I'm a newbie, didn't know about the below features. They are,

1. Integration with Grid and Jenkins.

2. Multithreaded execution or parallel execution

3. Proxy setup - Many organizations run under their VPNs or proxies. That part of the implementation is also needed for all browsers.

4. Implementation should be adaptable to AI-based BDD automation with python API. (Reg. this soon I'll attach the article once completed and published)

Finally, I know it's a pretty big article.

Thanks for reading this all way to the end.

Location of the project - GitHub repository

Take a look at the above link also I always appreciate your comments about my work.

ย