A faster way to clean all inputs in an HTML form using Selenium WebDriver
Tags: testing, java, html, codequality
Published: 2021-01-16 08:59:44

## Introduction

Imagine you dealing with your functional/e2e tests where you want to clean the input fields. You will, probably, use your web test automation framework to do it, right?

It seems a good and easy approach, but is it fast?

In this post, I will show you basic comparisons based on the practices we do in web test automation. I will use Selenium WebDriver using Java, but I’m sure you can reproduce it in any framework + programming language.

## The problem

Let’s imagine you have a form where you need to clean all the fields to add new values (text). It is a common scenario when you are edition data.

### The form
The form we will use doesn’t have many fields but will give you an idea about the problem and the possible solutions.

This form is already loaded with some data in the 6 input fields, where you can access it here. We are going to ignore the State and Check me out elements.

![Form example](https://mlxotgzvm3ul.i.optimole.com/b8MB6YI.7fIz~494ed/w:auto/h:auto/q:auto/https://i1.wp.com/www.eliasnogueira.com/wp-content/uploads/2020/12/form.png?resize=750%2C540)

## The possible solutions

### The normal and not that fast one

Normally all the web test automation frameworks have a method to clean an input field, and it’s the first thing that came to our minds: clean the field before using it.

We have the following test (pre and post conditions ignored).

```java
// pre and post conditions ignored 

@Test
void cleanUsingSelenium() {
    WebElement email = driver.findElement(By.id("email"));
    email.clear();
    email.sendKeys("new@email.com");

    WebElement password = driver.findElement(By.id("password"));
    password.clear();
    password.sendKeys("987654321");

    WebElement address = driver.findElement(By.id("address"));
    address.clear();
    address.sendKeys("Viebrug");

    WebElement address2 = driver.findElement(By.id("address2"));
    address2.clear();
    address2.sendKeys("1");

    WebElement city = driver.findElement(By.id("city"));
    city.clear();
    city.sendKeys("Utrecht");

    WebElement zipCode = driver.findElement(By.id("zipcode"));
    zipCode.clear();
    zipCode.sendKeys("3511 AJ");
}
```

As you can see we are locating each element, assign it to a `WebElement`. After we send two commands: first the `clean()` to clean the value into the input field and after the `sendKeys()` to fill it in with a new value.

**This test took 1s 506ms to execute.**

### The first faster alternative

Instead of calling the clean using your favorite framework, you can send a Javascript command to clean all the fields. One of the ways to do this is finding the form element and then executing the `reset()` method to clean all the fields inside the form.

The Javascript code to clean all the fields in the form is:

```javascript
document.getElementById('my-form').reset()
```

We have the following test to clean the input fields using a Javascript command:

```java
// pre and post conditions ignored

@Test
void cleanByJSExecutor() {
    ((JavascriptExecutor) driver).executeScript("document.getElementById('my-form').reset()");

    driver.findElement(By.id("email")).sendKeys("new@email.com");
    driver.findElement(By.id("password")).sendKeys("987654321");
    driver.findElement(By.id("address")).sendKeys("Viebrug");
    driver.findElement(By.id("address2")).sendKeys("1");
    driver.findElement(By.id("city")).sendKeys("Utrecht");
    driver.findElement(By.id("zipcode")).sendKeys("3511 AJ");
}
```

You can see in the like 5 the Javascript code before starting to fill in the elements. As the code is using Selenium WebDriver + Java the `JavascriptExecutor` class is in use to enable the driver to execute a Javascript code.

On lines 7 to 12, you can see only the `sendKeys()` command because we already cleaned all the input fields, removing the necessity for the `clean()` method.

**This test took 845ms to execute.**

## Comparison

| Method | Time | 
|--------|------|
| Using `clean()` method | 1s 506ms |
| Using Javascript code | 845ms |
| **Differences** | **659ms (56%)** |

I know, it’s a basic comparison but we can see that the Javascript approach is 56% faster than the framework `clean() method`.

It’s happening because we are sending one additional command using the framework (Selenium WebDriver). So, probably your solution cleaning the field and after filling it in inside a Page Object method can slow down your test.

Imagine you with a lot of tests that require the input clean. You can same you sometime during the test execution, and it’s one of the automation focus: faster feedback!

## Things to take into consideration

### Loop into all the fields will take the same time in JS

Instead of finding the form element and trigger the `reset()` method, you could find all elements that are input fields and clean them. It’s a good alternative to clean it if you have multiple forms.

The following Javascript code can do the job:

```javascript
Array.from(document.getElementsByTagName('input')).forEach( 
   function(element) {
      element.value = '';
   }
);
```

### Loop into all the fields using a framework might be flaky
As an alternative, we could still use a web test framework to clean all the input fields. The logic is the same as the JS code above: find all the input fields and clean them.

The problem is that this alternative is flaky as the elements might have a different element internal reference, so when you try to either clean or fill an exception/problem might happen.

You can see this concrete example:

```javascript
driver.findElements(By.tagName("input")).forEach(WebElement::clear);
```

This code finds all the elements that are input fields and kill clean them all. The problem is an `InvalidElementStateException` that will be thrown because of a page refresh or data load during the page loading.

## Final considerations

This article is showing you alternatives to reduce the test execution time.

You can use any approach that works and that’s ok, but you seek improvements this is a good alternative.

A final Java code with all mentioned methods can be found at [https://gist.github.com/eliasnogueira/67da81c62cab3de2383052148e7ecafa](https://gist.github.com/eliasnogueira/67da81c62cab3de2383052148e7ecafa)