Category Archives: automation

Artifacts to store in your test automation project

Most of the times your automation code project travels around, from machine to machine, to where the tests inside it need to run. Sometimes it might be your colleague’s machine, who also wants to run/update/add tests, but other times it will be some CI/CD entities, like physical or virtual machines, containers, and so on.

Continue reading Artifacts to store in your test automation project

Joining multiple for loops in Python with ‘chain’ for repeating the same check for multiple groups of indexes

I will start with an example: say you have a page table with 2 columns. You want to check, in your UI testing, that the values in the second column are the expected ones. By looking at the table you see that the first 2 and the last 5 values are the same. You have to iterate the table values to compare to the expected ones, but what is the simplest way to do this? You could use 2 for loops to check for those identical values, but you would just be repeating the code inside those for loops, as you would be writing the exact same checks. Even if it’s calling a separate method, it would still be a code repeat. Let me exemplify solving this situation using ‘chained’ for loops. Continue reading Joining multiple for loops in Python with ‘chain’ for repeating the same check for multiple groups of indexes

Check out my mini-interview for Browserstack’s Icon of quality feature

Check out this mini interview i did for Browserstack’s Icon of quality feature, as part of their celebration of International Tester’s day: https://www.browserstack.com/blog/honoring-iconsofquality-corina-pip-qa-lead/

Adding testing to your test automation

Automated tests are supposed to help validate that the product under test is working as expected. For that, a key ingredient is required in your automation: the actual testing. Just as, when you are performing a test case yourself, you are visually inspecting that the expected behavior occurred, so does your automation need to have verification in place. And that verification needs to be implemented by you. Here are some thoughts on this.

Continue reading Adding testing to your test automation

waiter2: Useful methods for working with dropdowns and Select

When it comes to selecting values from a classic HTML dropdown, in Selenium you need to perform a few tasks: first, define a WebElement that represents the dropdown as page element; then, using the WebElement, create a Select object; using the Select object, you can then choose an option from the dropdown. This latter option can be done by: visible text (specifying the option’s label), ‘value’ attribute (of the <option> HTML tag found under the <select> tag representing the dropdown, corresponding to which option you want to choose), or by index (position in the list of <option> tags).

Continue reading waiter2: Useful methods for working with dropdowns and Select

Watch me talk about testing with Java, Junit5, Selenium and best practices

Here is a recent recording with some good advice on testing with Java, Junit5, Selenium and best practices: https://www.youtube.com/watch?v=Glrn9jcJCuc. Enjoy.

Watch this Selenium all stars discussion that i am also a part of

Checkout the recording we made with Joe Colantonio for TestGuild, where we talked about Selenium and the upcoming Selenium Conference: https://www.youtube.com/watch?v=uxczD4fgxiQ. Including an all star lineup of Selenium Project members and committers. Enjoy!

waiter2: Typing into fields

When it comes to typing, in the ‘waiter2’ library there are quite a few methods dedicated to this task. But there is a reason why there are so many (32 to be precise): they are different variations, given certain parameters, as the name suggests for each of them. Here are the considerations, whose combinations will give the method signatures:

Continue reading waiter2: Typing into fields

waiter2: Clicking on page elements

Clicking on a page element is easy to do, however sometimes this action might fail. This can be either because the element we want to click is not yet present on the page, or is not visible, or does not yet allow interactions. To help make sure the click succeeds, here are my dedicated wait based click methods.

Clicking a page element: click

There are 4 methods for clicking on a page element in the ‘waiter2’ library: 2 of them take the timeout parameter, 2 don’t. Additionally, 2 of them take a WebElement (defined with @FindBy) as parameter, 2 take a By variable:

public void click(WebElement elementToClick)
public void click(WebElement elementToClick, int specificTimeout)
public void click(By selectorForElementToClick)
public void click(By selectorForElementToClick, int specificTimeout) 

It is worth mentioning that there will never be a ‘waitForElementToBeDisplayed’ method in the library, simply because it is not needed. For example, when trying to click on a page element, there is no need to wait for it to be displayed before clicking. The logic inside the ‘click’ method from ‘waiter2’ retries clicking the element any time an Exception is encountered. If the element would not be present, the NoSuchElementException would be thrown for each click, until it either is displayed, or the timeout value has elapsed. Similarly, if the page element were present but not visible, or not clickable, the click action is tried until it succeeds or the timeout elapses. Any Exception that can be encountered while clicking is treated the same, because the generic ‘Exception’ is checked for and treated.

So basically, calling the click method while the element to be clicked is not yet ready, but in the process of being ready, will reliably click on it (given it loads within the specified timeout).

In case the element is not clickable for any reason within the specified timeout, a RunTimeException is thrown, with the message:

"waiter2.FAILURE: Could not successfully click on '" + elementToClick + "' within "
        + specificTimeout + " seconds."

The provided selector will be displayed, so that the tester knows what selector was looked for. This helps debug the failure.

Since version: 1.0

The code

The ‘click’ method variants that take a WebElement as parameter are:

public void click(WebElement elementToClick) {
    click(elementToClick, TIMEOUT);
}
public void click(WebElement elementToClick, int specificTimeout) {
    WebDriverWait wait = new WebDriverWait(driver,
            Duration.ofSeconds(specificTimeout));
    try {
        ExpectedCondition<Boolean> condition = arg -> {
            try {
                elementToClick.click();
                return true;
            } catch (Exception e) {
                return false;
            }
        };
        wait.until(condition);
    }
    catch (TimeoutException e) {
        throw new RuntimeException("waiter2.FAILURE: Could not successfully click on '" + elementToClick + "' within "
                + specificTimeout + " seconds.");
    }
}

The ‘click’ method variants that take a By as parameter are:

public void click(By selectorForElementToClick) {
    click(selectorForElementToClick, TIMEOUT);
}
public void click(By selectorForElementToClick, int specificTimeout) {
    WebDriverWait wait = new WebDriverWait(driver,
            Duration.ofSeconds(specificTimeout));
    try {
        ExpectedCondition<Boolean> condition = arg -> {
            try {
                driver.findElement(selectorForElementToClick).click();
                return true;
            } catch (Exception e) {
                return false;
            }
        };
        wait.until(condition);
    }
    catch (TimeoutException e) {
        throw new RuntimeException("waiter2.FAILURE: Could not successfully click on '" + selectorForElementToClick + "' within "
                + specificTimeout + " seconds.");
    }
}

Usage examples

The best usage for the ‘click’ method would be: providing a WebElement defined in a page object class with an @FindBy annotation. For example, for a page on which there is a button to click, whose id is “buttonToClick”, the corresponding WebElement is:

@FindBy(id = "buttonToClick") public WebElement buttonToClick;

Don’t forget that as per the setup, you need to do a PageFactory.initElements before using the WebElement. In the test, in order to click on this page element, you would just need to pass the WebElement as parameter to the ‘click’ method (shown here with the default timeout value):

waiter.click(page.buttonToClick);

In case you cannot create the WebElement through the @FindBy annotation, because it gets generated dynamically in the test, you can pass a By variable to the ‘click’ method. There are 2 ways you can do that: either by creating a By variable somewhere in the test and passing it to the method once it has the correct value. Or by creating a String variable somewhere in the test that represents the selector, then passing it to a By.yourSelectorType once it gets assigned the correct value. Below are some examples for the same button as above.

If you want to create a By variable, it would look like the following one (here obviously it represents an id):

By byForButtonToClick = By.id("buttonToClick");

You can now use it in the ‘click’ method:

waiter.click(byForButtonToClick);

If instead you want to create a variable only for the String representing a selector:

String selectorForButtonToClick = "buttonToClick";

Then, to click the corresponding element:

waiter.click(By.id(selectorForButtonToClick));

Note1: If the selector value is static (it is always the same), use the @FindBy approach. Only use the By approach if you cannot use the @FindBy one, due to not knowing at the beginning of the test what the selector will be (as it gets generated along the way).

Note 2: If you are using the By or the corresponding String only to click that item once, and not anywhere else in the test, DO NOT create a separate variable to store these. Just pass them inline, directly into the ‘click’ method, like, for example:

waiter.click(By.id("buttonToClick"));

In case the element specified with @FindBy cannot be clicked due to any reason within the specified timeout, the following RunTimeException is thrown:

java.lang.RuntimeException: waiter2.FAILURE: Could not successfully click on 'Proxy element for: DefaultElementLocator 'By.cssSelector: nonExistentElement'' within 30 seconds.

In case the element specified with By cannot be clicked on due to any reason within the specified timeout, the following RunTimeException is thrown:

java.lang.RuntimeException: waiter2.FAILURE: Could not successfully click on 'By.cssSelector: nonExistentElement' within 30 seconds.

Incorrect usage!

Never do the following:

WebElement buttonToClick = driver.findElement(By.id("buttonToClick"));
waiter.click(buttonToClick);

Why? Because if the button to click is not displayed when the ‘findElement’ method runs, the test fails at that step, and the ‘click’ method never executes.

So that’s it for clicking on page elements, which of course, include more than just a button. The test code can be found here. Next up i will discuss some further useful methods, so stay tuned!

waiter2: Opening a page and waiting for it to load

In this post I will describe what the get, wait for page load and wait for jquery to load methods from the ‘waiter2’ library do, and how to use them in your tests. For setup details, please read the previous post.

Waiting for a page to load: waitForPageLoadComplete

There are 2 methods with the name ‘waitForPageLoadComplete’. The first one does not take any parameters. The second one takes an int as parameter, corresponding to how many seconds to wait for the page to finish loading successfully. I will refer to the no parameter variant in the following paragraph.

This method simply waits for the page document and corresponding static resources to finish loading for up to 30 seconds (the default timeout set in the method). The method uses the ‘document.readyState’ property to check for this. When the value of this property is ‘complete’, the wait method exits successfully. If the condition is not met within the specified timeout, the method throws a RunTimeException, with the following message: “waiter2.FAILURE: Page did not finish loading within 30 seconds.”. This message should make it easy to identify, in the test output, why the test failed (in case the page did not load successfully during the specified timeout period).

Since version: 1.0

The code

The code of this method is:

public void waitForPageLoadComplete() {
    waitForPageLoadComplete(TIMEOUT);
}

This method actually calls the method variant that takes a specified timeout as parameter. It sets that timeout to the default value of 30 seconds, defined in the Waiter class through the TIMEOUT constant. This latter method is:

public void waitForPageLoadComplete(int specificTimeout) {
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(specificTimeout));
    try {
        wait.until(driver -> String
                .valueOf(((JavascriptExecutor)
                        driver).executeScript("return document.readyState")).equals("complete"));
    } catch (TimeoutException e) {
        throw new RuntimeException("waiter2.FAILURE: Page did not finish loading within " + specificTimeout + " seconds.");
    }
}

Note: ideally you wouldn’t use this method directly. It is called from a method described below for opening a page (called ‘get’). Normally you would wait for a page to load after opening it.

Usage examples

Inside a test, once the waiter class was initialized and a driver instance was created, calling this method is simply done as:

waiter.waitForPageLoadComplete();

Waiting for jQuery to load: waitForJQuery

In order to wait for jQuery to finish loading, one of the 2 variants of the waitForJQuery method can be used: one without passing the timeout value as parameter (whose default timeout is 30 seconds) and another one that takes an int timeout value. If there is no jQuery on the page, the method exits immediately, successfully. Otherwise, in case it is present, the jQuery.active property is waited for, up to the defined timeout, to equal 0.

Since version: 1.0

The code

The method without parameters is as follows (and calls the other variant of the method, passing to it the TIMEOUT constant to specify 30 seconds as timeout):

public void waitForJQuery() {
    waitForJQuery(TIMEOUT);
}

The variant which takes an int parameter for the timeout is as follows:

public void waitForJQuery(int specificTimeout) {
    WebDriverWait wait = new WebDriverWait(driver,
            Duration.ofSeconds(specificTimeout));
    try {
        ExpectedCondition<Boolean> condition = arg -> {
            try {
                return (Boolean) ((JavascriptExecutor)
                       
                       driver).executeScript("return jQuery.active == 0");
            } catch (Exception e) {
                return true;
            }
        };
        wait.until(condition);
    } catch (TimeoutException e) {
        throw new RuntimeException("waiter2.FAILURE: JQuery did not finish loading within "
                + specificTimeout + " seconds.");
    }
}

Note: like with waitForPageLoadComplete ideally you wouldn’t use this method directly. It is also called from a method described below for opening a page (called ‘get’).

Opening a page and waiting for it to load, together with jQuery: get

The ‘get’ method will be used for: opening a URL in the browser, followed by waiting for the page to load (by calling the waitForPageLoadComplete method), followed by waiting for jQuery to finish loading if present (by calling the waitForJQuery method).

For ‘get’ there are also 2 variants: one without a timeout parameter, and one to which you can pass an int for the timeout. For the version without the timeout parameter, the method will wait for up to 30 seconds for the page to load after opening the URL (which is done by calling Selenium’s ‘get’ method), then for up to 30 seconds for jQuery. So in total there will be a wait of up to 60 seconds. The other parameter taken by the method is a String that represents the URL you want to open.

Since version: 1.0

The code

The variant of the ‘get’ method with default timeout is (this method calls the one described right below it):

public void get(String url) {
    get(url, TIMEOUT);
}

The variant of the ‘get’ method to which you need to pass an int timeout value is:

public void get(String url, int specificTimeout) {
    driver.get(url);
    waitForPageLoadComplete(specificTimeout);
    waitForJQuery(specificTimeout);
}

Usage examples

Due to the methods called inside the ‘get’ method, in your tests you never have to call those methods yourself. Here of course I am talking about the wait for page and jQuery to load ones. This helps reduce the code you write in each of your tests, since otherwise you would have to write 3 lines of code every time you opened a page. Now you just need to write 1. To open a valid URL, just pass in the valid URL, and either no timeout value or a desired int value, representing seconds. For the first case, you would proceed as follows:

waiter.get("https://www.selenium.dev/documentation/");

Or, to wait for 60 seconds instead of the default 30:

waiter.get("https://www.selenium.dev/documentation/", waiter.MEDIUM_TIMEOUT);

So that’s it regarding the methods for opening and waiting for the page to load. The test code can be found here. Next up I will discuss some further useful methods, so stay tuned!