Find The Button Sometimes In The Room

Small recap also known as cliff hanger

At the end of the sprint I demonstrated my automated regression tests. An unknown dialog popped up and interrupted the normal flow of the tests.

An unexpected dialog

After the demo one of my team mates asked the standard routine questions:
“Did you test before the demo?”
“Yes, of course”
“Did everything go right?”
“Yes”

I had done all the standard actions and still this dialog popped up. I studied it. Something went wrong with saving a file. This neat feature offered the user to add a personalised picture with a text like “Happy birthday, Cap. Loves from Dom, Sam, and George.” This way nicknames “Captain Marvel” or “Captain America” can be used or even abbreviated to Cap.

So the first attempt to save the file failed. I pressed the OK button to upload the picture again. After two other attempts, an error dialog popped up. It was not possible.

Of course I tried to reproduce this error manually, but all uploading went just fine. Hmm. Another attempt with the automated test showed the file upload problem straight away. The computer was too fast with testing.

The Need For Brakes

Imaginary scene in a shop in a cinema. I am recognised by one of the employees.

Employee: “Good evening, what do you want to drink?”
Me: “Well.”
Employee: “Here is your favourite drink, Cola.”
Me: “I was thinking about .. ”

Employee: “Here is your second favourite drink, Lemonade.”
Me: “Actually ….”
Employee: “This is the last drink we offer: Sparkling Orange.”

Me: “This was not in my mind.”
Employee: “You are going to watch Monsters Unlimited with the famous desert scene. Right?”
Me: [Nods]
Employee: “Excuse me for being so rude.”
Employee [Removes the 3 drinks from the counter and places a bucket on the counter.]
Employee: “This will take a few seconds.”
Employee: [Places a thick tube into the bucket.]
[The sound of 1 gallon of Sparkling Orange being pumped into the bucket.]
Employee [Removes the tube and smiles at me]

Me: “And …”
Employee: “You are going to the 5D experience with the real desert temperature.”
Me [Nods slightly]
Employee: [Empties a box of ice cubes into the bucket.]
[The sound of overflowing Sparkling Orange, followed by dripping sounds on the floor.]

Me: “I am trying to tell you …”
Employee: “I got it. Drinking out of a bucket is a drinking hazard, so you get this special straw.”
Employee [Pulls out a mini submarine with a tube on top and places it on the drink.]
[Again the sound of dripping Sparkling Orange on the floor]

Me; “I want ..”
Employee [Shows receipt of 100 Euro.]
Me: “nothing to drink.”
[The end]

This story describes a timing issue. The employee is way too fast. And guess what? Programs are also very fast. For example a test automation tool.

Wait a few seconds

Something had been changed in the program and a dialog popped up. There should be a way to let the test automation tool wait. I picked Thread.sleep(2000). This command let the tool wait for 2000 milliseconds or 2 seconds.

I started the tests again. This time no problems with the Error dialog were encountered.

Next stop was to ponder whether this was a proper solution. I was actually hiding a performance issue. My team lead had already given me a hint about this kind of cases.

Personally I never had any problems with the upload of the file. So this should not happen with other human beings. Waiting for 2 seconds was not that bad.

The Untouchable

On my screen I had a nice combo box. I wanted to select an option. This was not that difficult I thought.

My test failed. Wait, this cannot be true. All the time the combo box was in full view and my test automation tool Selenium web driver could find it until that very moment. I opened the console to look at the problem: it was a Stale Element Reference Exception.

On the internet I read about a situation that a web element was somehow disconnected with the element on the screen. This read quite cryptic. I tried to imagine what happened.

There was a combo box with movies to be shown, Monsters Unlimited and Finding Marlin. After the selection of a new date a new movie would be shown, the combo box was updated with the latest movie, Outside In.

What actually happens was that the old combo box was replaced by another combo box. So the old combo box did not exist anymore. Small courtesy of the low code development tool. Not really helpful.

But why did this error happen right now?
The code of the website was not changed. But. I had changed the structure of my tests.
How can a restructuring of my tests cause this problem? Give me a few paragraphs to explain.

A popular design pattern for test automation is the Page Object Model. A design pattern is an experience based way of working, which saves a lot of time and frustration. Using Page Object Model or POM I put all the old code associated with a page like Select Movie Page in one single class.

The class contains the following useful information:

  • Constructor (how can I make this page object?)
  • Methods (which actions can I do on this particular page?)
  • Fields (which web elements are contained on this page? What other relevant information is used by this page?)

A movie combo box can be coded like:

@FindBy(contains(@id, “moviesComboBox”))
WebElement moviesComboBox ;

This is an abbreviation of TestNG, a test framework, for

WebElement moviesComboBox = driver.findElement(By.xpath(contains(@id,“moviesComboBox”))

For the reader wondering about the word contains, there is an explanation about this construction.

What I set up, was an administration, which connects moviesComboBox to the movie combo box with the movies Monsters Unlimited and Finding Marlin on screen.
The program replaced the combo box with the two movies by the movie combo box with Monsters Unlimited, Finding Marlin, and Outside In.
Now my web element moviesComboBox was referencing nothing.

My solution was to make the connection between the web element moviesComboBox and the combo box on screen as last as possible. Just before selecting a movie I placed the following code:

WebElement moviesComboBox = driver.findElement(By.xpath(contains(@id,
                                     “moviesComboBox”));

I got a Stale Element Reference Exception. No worries, I use a sleep.

Thread.sleep(100);
WebElement moviesComboBox = driver.findElement(By.xpath(contains(@id,
                                     “moviesComboBox”));

This was a flaky test. I could tweak my number of milliseconds of sleep, but a reliable test was slipping out of my hands.

The Unfindable

Now I had a situation that in 60 % of the cases my tests would execute with Passed. This was quite disturbing for me, because the website was not changed. Same test, same unpredictable result.

I focused on my latest test automation challenge: finding the right order identity often abbreviated to order id. Users were allowed to use an order Name like “Cap 13”. This is short for the 13th birthday of Captain Marvel or Captain America.

But this could hurt the handling of orders. Suppose a parent of Cap had made two reservations with the same name. If this persons calls the cinema, which order must be deleted by the customer agent? Cap 13 or Cap 13? So an order id was introduced.

For test automation this was really helpful. The organizer or parent placed the order for the movie visit. And she or he got an order id. In turn all attendees or kids could use this order id to order a snack and a drink.

If I automated my manual steps, then everything would be okay.
My steps were:

  • Search for the order name.
  • Determine the first row in the table.
  • Determine the order id in this row.

The code was ready, but the test did not pass. Another fail on my record. I better got used to this.

This time I saw a No Such Element Exception in my console. This meant, that the first row could not be found. Then I got a déjà vu. The test automation tool was too fast, so I built in a sleep. This did not solve the problem completely.

Sent until accepted

[Update author: my opinion is not the same as the author of the referred characters, but I believe in the goodness of the good characters.]

Suppose there is a character, who wants to reach someone else. Let me pick an arbitrary person called M. McGonagall. Her employer does not receive a response on her letter.

So every responseless day she resends a letter and also slowly increases the number from 1 via 3 via 12 via 24 via 30 – 40 to some 100. Until a pink umbrella wielding bloke delivers the long awaited letter to Mr. H. Potter.

The Multiple

In the meantime I was tweaking my sleep time in milliseconds. It looks that a response time was between the 2 and 6 seconds. If I only used the worst case scenario time, then this would lead to an increased execution time of my regression tests. Because the low code tool automatically made the code for the website, there was no way to tweak this code.

I got an idea. What about trying to find the first row 3 times instead of once?

Boolean individualOrderNotFound = false;
For (int i = 0; i < 3 && !individualOrderNotFound; i++){
  try {
      findElement(xpath).click();
      individualOrderNotFound = true;
  }
  catch(NoSuchElementException e){
      Thread.sleep(2000);
  }
}

While blogging I fully realise that this is not the best piece of code to be shown. But things in the past cannot be changed.

I performed my test 5 times in a row. There was 1 fail. I felt relieved, that my tests were more reliable than before. Less fails on my record. I better got used to it.

There was still one more thing to check.

Time for another blog post.