Browse Author: Oleh Husiev, Anastasia Husieva

Test Automation engineer at Namecheap, Kharkiv, Ukraine. Student of Kharkiv Politechnical University, Kharkiv, Ukraine.

A couple of words about Page Object

Often in the testing of web applications, every form on a page is described as a separate entity (object) – usually, one single form (in most cases it represents an isolated functionality) is equal to a separate class. All these objects/classes consist of web element instances (various web elements located on the related web form) and methods for interaction with the elements. Let’s imagine there is a Login form in a web application. The form may be described as:

public class Login
{
   IWebDriver driver;
   public Login(IWebDriver driver) { this.driver = driver; }
   //the class contains only one method
   //this is abridged example of the method. There is neither verification for null reference exception, nor check of driver’s actions, nor logging of events, nor handling of exceptions.
   //The method takes two strings as parameters: user name and password, and returns an instance of the web application start page - StartPage
   public StartPage LogIn(string userName, string pwd)
   {
      IWebElement name = driver.FindElement(By.nameTextboxLocator);
      name.SendKeys(userName);
      IWebElement pwd = driver.FindElement(By.passwordTextboxLocator);
      pwd.SendKeys(userPassword);
      IWebElement btnLogin = driver.FindElement(By.loginButtonLocator);
      btnLogin.Click();
      return new StartPage([parameters]);
   }
}

Therefore, the test would be looking like this:

[Test]
public class LogIn()
{
   driver.Navigate().GoTo(http://address-of-tested-login-page.com);
   var Page_Login = new Login(driver);
   var StartPage = Page_Login.LogIn(userName, password);
   Assert.IsTrue(StartPage.VerifyStartPageIsLoaded());
}

This approach allows you to create a big number of tests very fast and easy. But there are a number of underwater stones hidden inside as well. This way of writing new tests is good enough for little and simple projects where there are only a couple of hundreds of web elements and methods. and were only a few persons are doing the testing. Because, if the tested web application is very complex or the application is developed very fast and a lot of functionalities are often changed or you have a big team of automated testers (and most of them are juniors), it is likely that the maintenance of the framework will be your nightmare. Because sometimes you will be forced and called upon to maintain the framework.

A simple example: what if after clicking LogIn button a dozen of other different pages may be loaded in addition to StartPage? For example, imagine that according to the type of user’s contract, his role, profile settings, user location (the country where the request has come from) and settings of the testing environment (server which the user is connected through), there may be loaded eighteen different pages. In this case, you should override the method eighteen times to get all the pages, and after some time you should maintain all these versions of the method if something has been changed in the application. Of course, you can use a generic method aka <T>Login(username, password) in your tests but we’re talking about a maximum ease of writing and understanding of tests. It’s hard to imagine that a customer or PM or manual tester at least superficially understand the generics.

The second underwater stone is the scaling. If you described a page or some of its part as a single object and one day something is changed of this page (or its part) you will have to update the object itself, its methods (there may be a lot of ones) and related tests (the number of such tests may be actually huge). In general, the causes from above are already sufficient to decide not to implement the Page Object pattern to web pages or forms but to implement the pattern to page’s elements. In my approach, an object I will interact with is a web element, not the entire page. You may call it Element Object. I describe every single web page (or web form) as a separate class and it still contains a set of web elements located on the related web page but there are no methods for interaction with its elements. Instead, the web elements (buttons, links, images, tables, etc.) are described as the page’s properties. Every element is defined in its own class and has its own methods for interaction. Thus, the Page Object pattern is implemented in relation to web elements, not web pages.

Please, keep in mind that the bigger and complex object is the more difficult is its maintenance. You can describe, for example, the entire login form as a single entity or you can describe separately every element of this form as a single entity. The second approach will be more flexible.

Example:

public class Login
{
   //the class contains a set of properties, not methods
   //this is full description of login form. No additional verification, actions or logging is required.Everything, together with all properties and methods of every element, is encapsulated inside appropriate web element class
   public Textbox Textbox_UserName { get { return new Textbox(“locator of the element on the page”, [other parameters]); } }
   public Textbox Textbox_Password { get { return new Textbox(“locator of the element on the page”, [other parameters]); } }
   public Textbox Button_LogIn { get { return new Button(“locator of the element on the page”, [other parameters]); } }
}
[Test]
public void TestLogIn()
{
   TestedApplication.Page_Login.Textbox_UserName.TypeText(userName);
   TestedApplication.Page_Login.Textbox_Password.TypeText(password);
   TestedApplication.Page_Login.Button_Login.Click();
   Assert.IsTrue(TestedApplication.Page_StartPage.IsLoaded);
}

Dark side of a Software Development Engineer in Test (SDET)

A lot of people have an opinion that a software development engineer in the test is a more difficult, more responsible, more skilled position than that of an automation QA engineer who is actually just a ‘tester’. It’s because the SDET is almost a software developer: he deeply knows programming languages, design patterns, algorithms. He can create a high-quality, maintainable, and performant code. He creates tools for automated testing, writes his own frameworks – such kind of work is more complicated and, therefore, should be better-paying. That’s why many automation test engineers like to name themselves an SDET, alluding to their high skills and value.

Sure, everything said above is true, if and only if the SDET also has a deep knowledge of software testing methodologies and APPLIES it to his work. Unfortunately, in real life you can see the following situation:

There are two QA teams on a project – manual testers and automation testers (who proudly consider themselves SDETs). The manual team creates a set of test cases and passes them to the auto-team for automation. The automation team develops its own framework, converts the test cases to automated ones, writes test scripts, and runs them.

As you can see, there are two different roles: 1 – the team of highly skilled manual testers who write test cases and are responsible for the product quality, 2 – high skilled developers who convert manual test cases to automated scripts. Obviously, the manual test cases and the programming code will be much qualitative in terms of an architecture and design.

But, there are also some cons:

When the automation team receives manual test cases as an input and produces automated scripts as an output only, it means that the team is not responsible for the product quality. It’s because they cannot be responsible for the product test coverage, test strategy, or test design quality – they do not do this. And it also means that the AUTO-TEAM is the only one in the project who IS NOT RESPONSIBLE FOR THE PRODUCT QUALITY!!! And therefore it is not motivated to give the product of high quality. Their goal is tons of test reports marked ‘passed’.

Simple example. Assume there is a defect found in the production branch.

Customer: why has it happened and who is responsible for that?
Manual QA: I created a fine test case that covers everything you need, including the found defect. Then I passed the test case to the automation team. They converted the test case and ran it.
Automation QA: I covered all the requirements and all are reports are green (all the tests are passed).
Customer: But there is a defect!
Manual QA: If you run my test cases manually, you will catch the defect.
Automation QA: Our tools cannot catch such kind of bugs and It’s not my fault that the manual QA did not foresee that and did not provide a more suitable scenario. All my scripts exactly repeat the test cases, every single step.

To avoid a problem similar to the one described above, the SDET must have and apply his/her knowledge of manual software testing. He must be at the heart of the software development process as the customer’s advocate. In addition, he must be responsible for the product quality. So, any SDET must have a very deep knowledge of manual testing and preferably some working experience in this position. Sure, now he does pure automation and writes the code like a developer but he also must take part in the development of the test strategy, create his own test plans and test cases and be responsible for his part of the work.

If you hear someone calling himself an SDET, whereas this function is limited to the development of testing tools, you should know that this person must have come to the software testing from the development field (or always dreamt to be a developer but lacks qualification) and has an insufficient knowledge of software testing and reluctance to study it.

So, make your own conclusions but note that everything written above is only my personal opinion.

Smart click (part 1)

When using the Selenium Webdriver tool for testing web-based applications, I faced a problem: sometimes the common Click() method does not work for specific elements. Or, for example, it may work fine in the FF browser and fails to click in Internet Explorer. After a little investigation, I noticed that instead of the Click() method I can use methods from the Actions class, or I can click elements with JavaScript. But I also discovered that I have to use one action for FF and another for IE – often an action worked with one browser but failed with the other. I had to add extra logic for specific elements and it began spreading some mess in my code.

Then a couple of months later “funny” things started to happen regularly. Guys from Mozilla Corp. or Microsoft delivered a new version of their browser. The old version of Selenium Webdriver didn’t support this new browser, so I had to upgrade it to the latest one. But oops… most of my specific clicks turned out to work conversely. Or did not work at all, and I had to return to the common Click() method. Chaos in my code was about to come.

That’s why I started looking for a method that would work consistently with any browser, webdriver, or elements and would also give me some additional helpful features like events logging with screenshots, handling exceptions, coded-behind verification, etc. Finally, I realized I had to invent it myself.

I asked myself what I do when I click a web element (assume a button) in a browser manually and came up with the following list:

  1. I determine what the button I am going to click.
  2. I am sure if I can click the button. I check if it is present on the page, is displayed, is enabled for a click, etc. In other words, I verify conditions for a successful click.
  3. Then I click the button.
  4. I verify that click has been successful, that some changes has occurred – expected or not – even if I’ve got an error, it means that the click itself has happened. So, I verify conditions after the click.

I do all the thing from the list above unconsciously. So does everyone else.

So I decided to write my own version of the Click() method reproducing all my manual actions for clicking a button in real life. Here is the recipe:

If you have separate classes for different types of web elements in your testing framework, such as buttons or links, you can add the method Click() to this class(es) and use a private IWebElement instance defined inside the class for interactions. For example:

public class WebButton
{    
    private IWebElement element;
    public WebButton(/*constructor parameters*/) 
    {
        element = //instance of IWebElement according to constructor parameters
        //bla-bla
    }

    public void Click(/*possible parameters*/)
    {
        //logic for clicking the element in a smart way
    }
}

If you use an ordinary IWebElement interface for describing web elements, you can create an extension method for the interface. Like this:

public static class Extensions
{
    public static void Click(this IWebElement buttonToClick, /*possible parameters*/)
    {
        //logic for smart click on buttonToClick
    } 
}

You will be able to invoke the methods in your tests in this way:

//1st case
WebButton button = new WebButton(/*constructor parameters*/);
button.Click();

//2nd case
IWebElement button = driver.FindElement(By.Id("buttonID"));
button.Click();

 

 

  • 1
  • 2