Test automation is a prominent part of testing. To improve your test automation code, you should look at development practices. Creating clean code is a good practice to improve the maintainability and readability of the test automation. Recognising clean code is quite easy. If it reads like prose and you understand the intent (almost) immediately even if you are not the author, then it’s probably clean. However, writing clean code is difficult. You will need a lot of practice to properly create clean code, but the following topics will help you along the way. Keep in mind that test automation is software development. So why not use good practices from the field of software development?
Naming
Let’s start with naming. Use proper names for everything that can be named, for instance variables, methods, classes, and packages. The test automation code you create will have to be maintained and read by others. So its intention should be clear. You can improve clarity comes by applying proper naming. If you want your naming to be clear to all the people you work with, use names from the problem domain. These make sense to the business and not only to the development team. When iterating over rows, name your loop variable to indicate what you are looping over:
WRONG:
for (int i = 0; i < rows.length; i++) {
CORRECT:
for (int row = 0; row < rows.length; row++) {
Another example is the naming of your methods. When you write a method printRows, it should only print the rows and for instance not also alter them. When you read the method name, it should do what you expect it to do from the name, no more, no less. To achieve this so called single responsibility of a method, you usually need to apply refactoring.
As a final tip on naming, use a coding convention and automate the verification of this convention. This ensures that naming is consistent throughout the complete solution. Conventions around naming have changes over the years. In the early days, the Hungarian notation (prefixing variable names with an abbreviation of the type) was useful, but current integrated development environments (IDEs) show the type of a variable, making prefixing the type no longer necessary.
Refactoring
While creating your code, it usually evolves gradually. This evolution adds or improves functionality, but this does not mean the new version of your code is clean. Given that you want to create a method login that logs into the application with a given user. When you first run your login method, you notice that you need a registered user to be able to log in. Then you decide to alter your login method and you get something like this:
public void login(String user, String password) { driver.findElement(By.className("register")).click(); driver.findElement(By.id("email")).sendKeys(user); driver.findElement(By.id("passwd")).sendKeys(password); driver.findElement(By.id("passwd2")).sendKeys(password); driver.findElement(By.id("SubmitRegistration")).click();
driver.findElement(By.className("login")).click(); driver.findElement(By.id("email")).sendKeys(user); driver.findElement(By.id("passwd")).sendKeys(password); driver.findElement(By.id("SubmitLogin")).click(); Assert.assertTrue(driver.findElement(By.cssSelector("ul.myaccount_lnk_list")).isDisplayed()); }
Obviously, you can refactor and take out the registration functionality into a different function as can be seen in the next piece of code. This appears to be quite nice, but now the method login , also does registration! In this case you can easily separate the responsibility to register from the responsibility to login. But the example shows how quickly the function name can become inconsistent with the function behavior.
public void login(String user, String password) { register(user, password); driver.findElement(By.className("login")).click(); driver.findElement(By.id("email")).sendKeys(user); driver.findElement(By.id("passwd")).sendKeys(password); driver.findElement(By.id("SubmitLogin")).click(); Assert.assertTrue(driver.findElement(By.cssSelector("ul.myaccount_lnk_list")).isDisplayed()); }
The caller should decide if it is needed to register, so if we create a test that needs to register and login, that test calls the register method followed by the login method.
Test Automation Code
Test automation is software development! So you can improve your test automation code by applying techniques that are already applied in software development. Proper naming keeps it easier to understand what is happening in the code. Refactoring is needed to keep the intent of the code clear. Separate the responsibilities into different functions, classes, and packages. Make sure that the caller of your code gets what they can expect from the naming, no more, no less.