Category Archives: Test automation

Fast Forwarding Act

Kent Beck used an old programming technique. This way he rediscovered Test Driven Development.

Decades later I was combining Test Driven Development with test automation. According to me it was feasible.
Like the British would say:
“The proof is in the program.”

Recap

In order to make this test automation code work I used Arrange Act Assert.

  • First I had to Arrange, that given my Selenium web driver is in the Form Authentication of https://the-internet.herokuapp.com/.
  • I had to Act: when my Selenium web driver will enter the user name and password, and pressing the Enter button.
  • I had to Assert: then I got a message that I had entered the right credentials.

I had finished Arrange and Assert. The next step was to get Act in place.

Inserting Act between Arrange and Assert

Now I had made code for a situation with no credentials. I had not entered any user name and password, so I did not get access. This seems fair enough.

I programmed my steps using Red Green Refactor, which are used in Test Driven Development.
Under the rectangle Arrange there are two groups of a arrow pointing to the right and three rectangles Red, Gree, and Refactor. The left group is higher than the right group!

Ready Set Code.

Do You Want To Make Some Test Code?
[On the melody of “Do You Want to Build a Snowman?”]

My first step for Act was to enter the user name.

Red:
the failing test was that no user name was entered. I could see, that the user name field was empty.

Green:
I added code in the test code.

loginPage.setUsername("tomsmith");

and additional code for setUsername.

public class LoginPage {

  private WebDriver driver;
  // NB: edited for readbility
  private By usernameField = By.id("username");  

  public void setUsername(String username){
    driver.findElement(usernameField).sendKeys(username);
  }
}

I executed the code. The user name field contained “tomsmith”, so I passed my test.

Refactor:
clean up code was not needed.

My second step for Act was to enter the password. Another round of Red Green Refactor was needed.

Red:
the failing test was that no password was entered. I could see, that the password field was empty.

Green:
I added code in the test code.

loginPage.setPassword("SuperSecretPassword!");

Then I put in additional code for setPassword in the LoginPage class:

public class LoginPage {

  private WebDriver driver;
  private By usernameField = By.id("username");
  private By passwordField = By.id("password");
  private By loginButton = By.cssSelector("#login button");

  public LoginPage(WebDriver driver){
    this.driver = driver;
  }

  public void setUsername(String username){
    driver.findElement(usernameField).sendKeys(username);
  }

  public void setPassword(String password){
    driver.findElement(passwordField).sendKeys(password);
  }

  public SecureAreaPage clickLoginButton(){
    driver.findElement(loginButton).click();
    return new SecureAreaPage(driver);
  }
}

When I used the test code, the password field was filled. I made enough code to pass my failing test.

This piece of code had another effect: a green mark was shown in my programming tool. My Assert was also right: my Selenium web driver was successfully logged in.

I also most had my Act together. One more step.

Refactor:
clean up code was not really needed. Maybe I could have deleted the empty line.

The complete code looked like this:

@Test
public void testSuccessfulLogin(){
  LoginPage loginPage = homePage.clickFormAuthentication();
  loginPage.setUsername("tomsmith");
  loginPage.setPassword("SuperSeretPassword!");
  SecureAreaPage secureAreaPage =
    loginPage.clickLoginButton();
  assertTrue(secureAreaPage.getAlertText()
             .contains("You logged into a secure area!"),
             "Alert text is incorrect");
}

Let Me Code.
[On the melody of “Let It Go”]

Automatic please

There are people who would suggest to automatically check every step in Arrange. Of course this is possible. Here is another piece of code:

public class UploadTests extends BaseTests {
  @Test
  public void testUploadFile(){
    // Arrange
    FileUploadPage fileUploadPage =
      homePage.clickFileUploadPage();

    // Act
    // Upload file
    fileUploadPage.selectFileToBeUploaded(
      "D:\\Users\\Han Toan\\Downloads\\test.txt");
    FileUploadPage.FileUploadedPage fileUploadedPage =
       fileUploadPage.triggerUpload();

    // check header.
    // var result = "ran349454lk";
    var result = fileUploadedPage.getHeader();
    Assert.assertEquals(result, "File Uploaded!", 
      "Wrong page is shown");

    // Assert
    // Check file name
    // result = "ran3495840";
    result = fileUploadedPage.getUploadedFiles();
    Assert.assertEquals(result, "test.txt", 
      "Wrong file uploaded");
  }
}

So the Test in Test Driven Development can be performed on view or automatically.

Overview of TDD in Test Automation

At a low level I have small building steps: Red Green Refactor.
These steps orginated from TDD or Test Driven Development.

Red:
make a failing test.

  • What is the failing test in this particular case? Which text or information is shown to the tester?
  • Does the test provide useful information? Is the message specific enough? “Fail” is not an option, “Wrong screen” is a better one.
  • How do I determine whether the test fail? With my own eyes or automatically?

Green:
make enough code to pass the failing test.

  • Does the test pass?
  • Did I write minimal code to pass this failing test? Did I not add too much in the code
  • Does the code test the application and not my test code?

Refactor:
cleanup the code.

  • Did I take time to look at the code?
  • Do I know the right design pattern to optimise the code? E.g. POM, Page Object Model.
  • Does my programming tool offer options to refactor code? E.g. options in Refactor menu.
  • Do I know a resource, where I can find design patterns? E.g. Test Automation University, “Design Patterns” by Martin Fowler
  • Can I delete redundant automatic tests?
  • Did I execute the refactored code?

At a high level there are three construction phases for automatic tests:

  • Arrange: make sure, that everything is in order before a function is tested in a specific situation.
  • Act: perform the function to be tested.
  • Assert: determine, whether the tested function can be used in the right way in this specific situation.

For a construction phase I could use one or more cycles of building steps: Red, Green, and Refactor.

Most of the time I use them in a chronological order. I start at the beginning of Arrange and work slowly to the end of Arrange. It is the same with Act.

here are two groups of a arrow pointing to the right and three rectangles Red, Gree, and Refactor. The left group is higher than the right group!

For Assert I change the order, because Assert works as expected in a specific situation. In this case I start at the end and work my way back to the beginning.

There are two groups of a arrow pointing to the right and three rectangles Red, Gree, and Refactor. The left group is lower than the right group!

My whole approach for TDD in Test Automation can be summarised as follows:

Arrange followed by an arrow pointing to the right Assert followed by an arrow pointing to the left Act followed by an arrow pointing to the right!

The main reason to make an Assert before the Act is to assure that my Assert can provide me information about the wrong situation. More information can be found in my previous blog post.

FAQ or Frequently Asked Questions

Here are some questions, which I asked myself after several sessions of deliberate practice. Some of my answers are based on practice. Other answers are theoretical, which have to be tested in practice.

I ‘m a tester after all.
[On the melody of “It’s a small world after all.”]

Q: If I have a form with 9 fields, do I have to check whether Selenium Webdriver has entered the right values?
A: Some reasons for checking the contents of the fields are a change of the user interface and screen flow by filling the key fields properly. Examples are extra entry fields popping up or warnings about format shown to the user.

Q: Are there reasons to skip the checking of all 9 fields?
A: If the user interface will not change much. Another reason is that you do not want to test the Selenium code. A third reason is time saving.

Q: Is there an alternative for an automated check of field entry?
A: Yes, I can view changes with my own eyes. Or demonstrate my code to someone else.

Q: You use Arrange, Act, and Assert. You could also use Given, When, and Then. Why do you prefer the first ones?
A: I expected the question. For the people unfamiliar with this construction I edited the first section

  • Given I am in the Form Authentication of https://the-internet.herokuapp.com
  • When I enter a valid user name and password combination
  • Then I get a message that I had entered the right credentials
    The description of the steps are at a higher level than the steps in the first section, but it basically leads to the same result. The reason I use Arrange, Act, and Assert is to put myself in action. I have code to write and it will not write it self.

Q: You mentioned time saving. Why would it save time to skip tests?
A: If I give directions for a walk in Amsterdam, it is along the lines:
“First street right, 3rd street left, etc.”

I do not tell:
“You see a house with number 12. Continue walking to the red brick house with number 34, then turn to the right. At your right you see a small house with number 45b. Continue walking to the brick house with number 85a, then turn to the left.”
This costs a lot of time to tell and to remember. You can give it a try.

End of example

Let me write a little more about the directions to walk from the Rijksmuseum to the Palace in Amsterdam.
The Palace is situated on a dam. The Dam – yes seriously – is a place with buildings around it.

My next instructions would be like:
Go to the Monument on The Dam. This looks like a big needle with a sculpture at the bottom.
Look over The Dam with your back to the Monument on The Dam.
Then you can see the royal palace.

Of course readers might object:
“How are you sure you are looking at the right building?”
In my previous blog post I wrote, how the tourist could Assert this:
it look like a grey huge townhall with a dome.

For the people with normal vision there is no white castle with rank towers.
For the people with X-ray vision there is no Sleeping Beauty in the palace.

Last quote

Why should I not practice TDD in test automation?
It is a weird idea. Like TDD.

“No one is stupid enough to be a competitor. For about a year.”
Kent Beck about Explore at YOW! Conference 2018.

Fast Forwarding Assert

Recap

In order to make this test automation code I used Arrange Act Assert.

  • First I had to Arrange, that given my Selenium web driver is in the Form Authentication of https://the-internet.herokuapp.com/.
  • I had to Act: when my Selenium web driver will enter the user name and password, and pressing the Enter button.
  • I had to Assert: then I got a message that I had entered the right credentials.

I had finished Arrange. The next step was to add Assert. I know that this seems a bit of order, but you are allowed to read the section “Trust”. It would be great that you would return for the technical stuff in the next section.

Connecting Arrange and Assert

My first attempt to make Assert was a failure. It was code which tested my code instead of the code under test.

Now I needed to look again to the Red Green Refactor cycle of Test Driven Development or TDD in Assert.
In the upper part there is a rectangle "Assert". Under this rectangle there are two groups rectangles "Red", "Green", "Refactor". The left group is lower than the right group!

What was Assert supposed to do?
It was supposed to show some message. I had to translate Assert to Red Green Refactor.

  • Red: no message is shown.
  • Green: a message is shown.
  • Refactor: cleanup code.

If it was too difficult for one cycle, I could always use additional Red Green Refactor cycles.

The first step is Red or make a failing test. How did I determine whether the message was not shown?
I looked with my own eyes. Guess what? I had already a failing test.

The second step is Green or make enough code to pass the failing test,
It was time for my rebound. I had enough code in Arrange to make useful code for Assert.

 
   assertTrue(secureAreaPage.getAlertText()
              .contains("You logged into a secure area!"),
              "Alert text is incorrect");

I could plug in my code like this:

@Test
public void testSuccessfulLogin(){
  LoginPage loginPage = homePage.clickFormAuthentication();
  assertTrue(secureAreaPage.getAlertText()
             .contains("You logged into a secure area!"),
             "Alert text is incorrect");
}

But this would lead to code, which could not be compiled. For starters secureAreaPage was not initialised and did not have a method getAlertText. Code which is not executable can not be tested. The line with assertTrue was unusable.

The test could not be performed, so it is not really a proper Assert.

Now I had to introduce a secureAreaPage.

public class LoginPage {

  private WebDriver driver;
  private By loginButton = By.cssSelector("#login button");

  public LoginPage(WebDriver driver){
    this.driver = driver;
  }

  public SecureAreaPage clickLoginButton(){
    driver.findElement(loginButton).click();
    return new SecureAreaPage(driver);
  }
}

Painful discoveries

While blogging my code looked perfect to me, but my memory was not that perfect. When I coded, I did not use version control system for my personal project at that moment. Luckily I had made short notes in charters. I missed some notes, but I was still able to reconstruct my steps.

Another thing I noticed was, that the code for testBackspacePressed was written before testSuccessfulLogin. I could change flash forward to flash backward. But that would be quite confusing for the reader. So this blog post serie is based on real stories.

Connecting Assert and Act Continued

A way to introduce secureAreaPage in the code is to insert a new line of code:
“SecureAreaPage secureAreaPage = loginPage.clickLoginButton();”

@Test
public void testSuccessfulLogin(){
  LoginPage loginPage = homePage.clickFormAuthentication();
  loginPage.setUsername("tomsmith");
  loginPage.setPassword("SuperSecretPassword!");
  SecureAreaPage secureAreaPage = loginPage.clickLoginButton();
  assertTrue(secureAreaPage.getAlertText()
             .contains("You logged into a secure area!"),
             "Alert text is incorrect");
}

Now secureAreaPage was initialised, but now I had to code a method clickLoginButton.

public SecureAreaPage clickLoginButton(){
  driver.findElement(loginButton).click();
  return new SecureAreaPage(driver);
}

There was still something missing. I missed a class for SecureAreaPage. So I coded a class with a constructor SecureAreaPage and the long awaited method getAlertText. For the newbie programmers a constructor is a method to make object. If there is no constructor, then there is no object to manipulate or test.

public class SecureAreaPage {
  private WebDriver driver;
  private By statusAlert = By.id("flash");

  public SecureAreaPage(WebDriver driver){
    this.driver = driver;
  }

  public String getAlertText(){
    return "ran394594";
  }
}

Notice, that I put in some random text in the method getAlertText. So every time getAlertText is invoked, it will return “ran394594”.

Now comes the interesting part. Let us have a look what happens, if the following line is executed:

assertTrue(secureAreaPage.getAlertText()
             .contains("You logged into a secure area!"),
             "Alert text is incorrect");

secureAreaPage.getAlertText() returns “ran394594”.
This is different from “You logged into a secure area!”,
so the following error message was shown to me:
“Alert text is incorrect”.

So I had finished Green: a message is shown.

The third step of the cycle in TDD is Refactor. The code was already well structured. End of cycle.

Time for a flash forward for another example

@Test
public void testBackspacePressed(){
  // Arrange
  // String header  = "Random text";
  var keyPressesPage = homePage.clickKeyPresses();

  String header  = keyPressesPage.getHeader();
  Assert.assertEquals(header, "Key Presses", "You entered the wrong page.");

  // Assert
  String result = keyPressesPage.getResult();
  Assert.assertEquals(result, "You entered: BACK_SPACE", "Wrong key detected");
}

Stumbling around

Some readers might prefer a straight forward description of TDD in test automation. And yes, I will describe it more concisely in the next blog post. My message is that it took time to adjust my mind to a new way of developing. I had to unlearn things. That is difficult.

Let me clarify this a bit more. Test Driven Development in test automation sounds like programming and testing of programming and testing. It took me a lot of effort to keep the Arrange, Act, and Assert apart from the Red, Green, and Refactor.

Another thing is that blogging this way gives me a better understanding how it works. It is no theory; it is real practice; it does actually work.

Trust

“Never trust a test you have never seen fail.”

I have seen talks of Angie Jones and Bas Dijkstra, two good test automation experts. Their recurring warning is always to see whether the test actually worked. They used Arrange, Act, and Assert in this order. Then they changed Act to see whether the Assert would show an error.

By using the order Arrange, Assert, and Act I know that Assert is testing the right thing. If I will finish my Act in the next blog post, I do not have to change Act to verify my Assert.

A small story to end this blog post

Maybe you remember the story about the walk from the Rijksmuseum to the palace in Amsterdam from the previous blog post. It is not some palace, but a real royal palace is used by the Dutch king and queen.

Lots of kids would go like
“Awwww, white castle with rank towers.
We want to see it!
Now!
Please.”

Only the royal palace is different from the one from a fairy tale. If you are on The Dam, there is no single building looking like that castle of a Sleeping Beauty.

How do I describe this palace to a tourist?
It looks like a grey huge townhall with a dome. This is a way to assert that a tourist is looking to the right building.
Sorry kids for spoiling the fun.

My next blog post is about inserting Act between Arrange and Assert.

Fast Forwarding Arrange

At that moment I had a test, which would always pass. This was not the right starting point.

Putting

The first phase of a test is to arrange, that things can be tested. Somehow I had to land on the Login Page on https://the-internet.herokuapp.com/. In other words put the automation tool on the same page. And off I coded.

What is a way to identify this screen?
Okay, the header is “Login Page”.
Now I can use Red, Green, and Refactor to make the final step to this screen.

Red or making a failing test was simple, because nothing could be seen.

@Test
public void testSuccessfulLogin(){
  assertTrue(loginPage.getHeader()
               .contains("Login page"),
               "You entered the wrong page.");
}

Green: now I had to make enough code to pass the test. The code was quite simple.
In LoginPage.java I made a method for the class LoginPage:

public String getHeader(){
  return "ran394594";
}

Refactor: the code looked simple. So there was no need for cleanup.

There was a drawback. I had a continuous passing test. This reminded me of the last unsuccessful attempt. In that case I started with a failing test of the Assert. Also in this case I ended with test code unconnected with the code under test.

Things

Then I realised that I had repeated the same wrong steps. This walk was clumsy. I started at the end of the Arrange and wanted to walk back with Red, Green, and Refactor.

In the upper part there is a rectangle "Arrange". Under this rectangle there are two groups rectangles "Red", "Green", and "Refactor" under an arrow pointing to the left. The left group is lower than the right group!

A lot of people state that you should start with the desination and then try to figure out what you need to get there. I had the feeling that I was rather awkward.

Let us assume that I have to provide some information to a wondering visitor of The Netherlands.
Imagine me walking backwards from the Palace on the Dam to the Rijksmuseum in Amsterdam.
They might mistake me for being a tourist. I hope.
Better to take some extra pictures. A habit of tourist. I think.

In the right order

It was better to start with Red, Green, and Refactor at the beginning of the Arrange. And from there I would slowly walk in the right direction.
Under the rectangle Assert there are two arrows RGR pointing to the right. The left RGR is higher than the right RGR!

So I needed to have code to get to the home page. But LoginPage.java extends BaseTests.java. This basically means that all code in BaseTests.java also applies to LoginPage. I discovered that the code to get to the Home Page was already present.

@BeforeClass
public void setUp(){
  System.setProperty("webdriver.chrome.driver", "resources/chromedriver.exe");
  driver = new ChromeDriver();
  driver.get("https://the-internet.herokuapp.com/");

  homePage = new HomePage(driver);
}

My first step was to put the code with getHeader in a comment.

@Test
public void testSuccessfulLogin(){
  /*
  assertTrue(loginPage.getHeader()
               .contains("Login page"),
               "You entered the wrong page.");
  */		   
}

Red: now I had to test that the Login Page was not shown. There was no code in place, so my test would always fail. I checked with my own eyes, that the Login dialog was not shown

Green: then I made some code to get there

@Test
public void testSuccessfulLogin(){
  /*
  assertTrue(loginPage.getHeader()
               .contains("Login page"),
               "You entered the wrong page.");
  */
  LoginPage loginPage = homePage.clickFormAuthentication();
}

I also needed some code for the method clickFormAuthentication in HomePage.java.

private By formAuthenticationLink = By.linkText("Form Authentication");

public LoginPage clickFormAuthentication(){
  driver.findElement(formAuthenticationLink).click();
  return new LoginPage(driver);
}

I executed the code again. And I saw the Login dialog.

Refactor: the code contained some comment with old code.

@Test
public void testSuccessfulLogin(){
  /*
  assertTrue(loginPage.getHeader()
               .contains("Login page"),
               "You entered the wrong page.");
  */
  LoginPage loginPage = homePage.clickFormAuthentication();
}

I deleted the comment:

@Test
public void testSuccessfulLogin(){
  LoginPage loginPage = homePage.clickFormAuthentication();
}

Also I noticed, that there were only manual checks and no automatic tests in the code of login page. Somehow I let my attention slip away. Again.

It is time for a flash forward. A few practice runs later:

@Test
public void testBackspacePressed(){
  // Arrange
  // String header  = "Random text";
  var keyPressesPage = homePage.clickKeyPresses();

  String header  = keyPressesPage.getHeader();
  Assert.assertEquals(header, "Key Presses", "You entered the wrong page.");
}

Why should I bother to use Red, Green, and Refactor so intensively?
This was the only way for me to fully experience this new way of developing. Later on I could always change things.

Okay, back to the point where I was trying to test a login form.
There I was. Ready to make actual tests.

This exercise was so small, that I started at the wrong point twice.

  1. At the end of the Assert
  2. At the end of the Arrange.

The whole way of programming in the right direction was still not a natural thing for me.

Somehow I forgot the time being a test coordinator for performance tests. My team members had to make scripts for complete unknown websites. My task was to simplify this by asking for click paths.
“Would you please provide screenshots, which are shown to to the user, and the input of the users?”

Another side note

In music there is a saying that the tape does not lie. If you are a good musician, then the recording will prove it. For software development I could translate it to “the code does not lie”. For doubtful people I could change it to the “the version control system does not lie”.

I could write about an error free test automation experience, which is not real.
My coding in TDD in test automation was still in progress. I was learning.

My next blog post is about fixing the Assert.

Fast Forwarding Slow Down

On the day of my talk about TDD in Test Automation the meetup was postponed.

Painting

One month later I was still exploring Test Driven Development or TDD. The talk is still available. In this blog post I will write about my latest experiences.

Test automation is about programming and TDD is about programming. In a talk Kent Beck told about crazy ideas, which would bring him laughter. TDD in Test Automation made me laugh. What was holding me back?

“What is holding me back?”
Kent Beck about Explore at YOW! Conference 2018.

In TDD there is a continuous loop of Red, Green, and Refactor. Red is writing a failing test. Green is writing enough code to let the test pass. Refactor is clean up the code.

Refactor is like something like “Let me put that recurring piece of code in 1 method”. This sounds easy, but it is still tempting to optimise during coding or Green. I already made the optimised code, so why should I spend more time on refactoring? There might be a chance that I miss 2 out of 3 improvements.

A post it with the text Red posing to the post it with the text Green, pointing to the post it to the post it "Refactor". The Refactor post it points to the Red post it!

Myself

A common pattern in test automation is Arrange, Act, and Assert. The first phase is to arrange that everything is ready for testing. E.g. I am logged in with the right user name and password on the right website. The second phase is to act or do something, which must be checked. E.g. I have to press on this button, so a dialog will pop up. The third and last phase is to assert or check, whether the result is right. E.g. I can see a dialog.

At that moment I had two patterns to work with:

  1. Arrange Act Assert
  2. Red Green Refactor

On a high level I used Arrange, Act, and Assert for the general structure. On a low level I used the Red Green Refactor cycle to make the code. So the Assert block contained several Red Green Refactor cycles. A cycle can also be shown as a serie of actions.

In the upper part there is a rectangle "Assert". Under this rectangle there are two groups rectangles "Red", "Green", "Refactor". The left group is lower than the right group!

In the next image I add Arrange and Act. For my convenience I abbreviated to “Red, Green, Refactor” to “RGR”.

There are 3 rectangles, Arrange, Act, and Assert. Under the rectangle Assert RGR is written twice. The left RGR is lower than the right RGR!
In order to improve my skills I used the Selenium WebDriver with Java course of Angie Jones. It was very free, very good, and filled with useful code.

My deliberate practice exercise was to see, whether I could log in via the link Form Authentication on https://the-internet.herokuapp.com/.  See chapter 4.2 of the course.

In the corner

Maybe you noticed that I started with Assert. But why did I start with the Assert?
Frankly I cannot remember it. Maybe Assert was my final destination for my test script. Or perhaps I used Red Green Refactor on the wrong level. Any way I had a starting point for my test automation script.

public class LoginTests {
SecureAreaPage secureAreaPage = new SecureAreaPage();

@Test
public void testSuccesfulLogin(){
  Assert.assertEquals(secureAreaPage.getMessage(),
    "You logged into a secure area!",
    "Alert text is incorrect.");
}

In SecureAreaPage.java I made a method for the class SecureAreaPage:

public String getMessage(){
  return "ran394594";
}

So I made my failing test. Red.

Now I could easily pass this test by changing the return value in SecureAreaPage.java. Green.

public String getAlertText(){
  return "You logged into a secure area!";
}

At this moment I had a problem. There was no connection with the website. The test would always pass regardless of the correctness of the form authentication.

Looking back I could even use the code to test pizzas. The test results would be of no value. What about testing that gravity is pulling me sideways? Same story. I must have been sleeping on my right side. The wrong side.

I needed to make some code to connect the website and Assert.
In the next blog post I will start with Arrange.

Test Automation is a quick way to check items in a web site. Fast Forwarding.
Coding is an activity which still needs consideration. Slow Down.

Find That Thing In The Room

80 % is not good enough.

A lot of readers might wonder about this statement. 80 % is quite good. Unless your boss does not accept any mistakes. But Agile is the new norm, so learn and adapt. Errors are some great and uncomfortable way to learn.

On the other hand a test automation result should not be right in 80 % of the cases. Especially when it was executed several times within 15 minutes. It is difficult for me to interpret these results.

My draft FAQ for test automation

This one is not perfect, but it will be better at the end of this blog post.

Q: What to do, if I always have a No Such Element Exception?
A: There is a good chance, that the web element cannot be found. So my way to locate the web element is bad. There are several ways to find a web element.

A: What to do, if I always have a Stale Element Exception?
A: There is a high chance, that TestNG is used. The element to be used cannot be found any more. In this can use a findElement as late as possible.

Q: What to do, if I have a No Such Element Exception once in a while?
A: My solution was to retry the required action. After an exception I would wait and try again.

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

Q: What to do, if I have a Stale Element Exception once in a while?
A: See the answer on the previous question.

Q: Would you like to write a blog post about it?
A: You are reading one of the blog post serie.

Q: Do you have anything to add?
A: Sure. How about from 80 % to 100% reliability?

Q: Why is 80 % not good enough?
A: If you perform a test, then the result cannot be trusted.

Q: I would just execute the test several times. 80 % of the results would point in the right direction.
A: So you take extra test execution for granted. And what if 90% of the test results are the same. Do you still execute tests until you get to 80 %?

Q: This is supposed to be a frequently asked questions.
A: You are right. Now it is a dialogue. Does it matter?

Q: I am the person who should be posing the question.
A: Why?

Pretty sure

The morale of the following story is that statistics should be used carefully to help your customers. So you can go straight to the next chapter with more Java and Selenium stuff.

Content warning: the following story contains a scene about a date with an unfortunate ending.

Imaginary situation in the cinema more than 2 decades ago. I am recognized by one of the employees.

Me: “I want to have a Cola.”
Employee: “Here you are. And the nachos and the hot sauce.”
Me: [puzzled] “How did you know that?”

Employee: “You always have the Nachos, if you order the Cola.”
Me: “Yes, you are right. I also want to order a Lemonade.”
Employee: “With a chance of 80 % …”
Employee: [Writes something on the cup and places the drink with a wink] “Here you are.”

Me: [Surprised] “What did you write??”
Brunette: [Walks to the counter] “Amy! Who is Amy?”
Me [Turning to the lady with a cramped smile.]
Employee: “Hi Amy.”

Me [Turning to the blond lady with a cramped smile.]
Brunette [Turning to the blond lady] “I am 5 minutes away and …”
Brunette: [Picks up my drink and throws it over me. Walks away angrily.]

Me: “And Amy, did you figure out the situation with the pointers?”
Young man [Approaches counter]: “So, that’s why you are interested in programming.”
Young man [Picks up the drink of Amy and pours over me. Walks away angry]

Amy: [Sighs] “I finally found a young man, who wants to talk about programming.”
Amy: [Picks up my hot sauce and pours it over me. Followed by the nachos]
Amy [Walks away angrily]

Employee: “If this get worse, I pay you bill. 100 % chance of no way.”
A TV crew pops up. A woman with a microphone: “People do the strangest things to stand the desert heat of the desert scene of Monsters Unlimited. More at 9. What is the cooling effect of Nachos and the hot sauce?”

Employee: [Shows receipt with a message: the receiver gets a lifetime membership of Cinema Hype VIP.]
[The sound of a paper being shredded.]

[The end]

Say it again Sam

Back to reality.
In my office I had the following quality check of my automation scripts. If a script would pass in 4 out of 5 cases, then it would be good. OK next test.

Now I had my honour to make my test results 100 % reliable.

The biggest advantage of the Cinema Hype VIP application was the two stage order. First an order could be placed for the movie tickets, so the seats were reserved. On the day of the movie drinks and snacks could be added to the order.

Let me try to remember what happened.
On first sight the actions were not that complicated:

  • Select a day.
  • Select a movie.
  • Select a time slot.

What did I see on screen?
There were 7 buttons to select a day. I implemented this step flawlessly.

The next step was to select the right movie in a combo box. I really liked Outside In, which would be shown from Thursday.

 
WebElement moviesComboBox = driver.findElement(By.xpath(contains(@id,
                                     “moviesComboBox”));
filterCombobox.click();
selectMovieOption();
filterField.sendKeys(“Outside In”);
filterField.sendKeys(Keys.ENTER);

The selection in the combo box went wrong: Stale Element Exception.

Maybe a loop might solve this problem.

Boolean individualOrderNotFound = false;
For (int i = 0; i < 3 && !individualOrderNotFound; i++){
  try {
      WebElement moviesComboBox = driver.findElement(By.xpath(contains(@id,
                                     “moviesComboBox”));
      filterCombobox.click();
      selectMovieOption();
      filterField.sendKeys(“Outside In”);
      filterField.sendKeys(Keys.ENTER);
      individualOrderNotFound = true;
  }
  catch(StaleElementException e){
      Thread.sleep(2000);
  }
}

After some tweaking I got No Such Element Exception. I also added this exception, but it did not help.

 
Boolean individualOrderNotFound = false;
For (int i = 0; i < 3 && !individualOrderNotFound; i++){
  try {
      WebElement moviesComboBox = driver.findElement(By.xpath(contains(@id,
                                     “moviesComboBox”));
      filterCombobox.click();
      selectMovieOption();
      filterField.sendKeys(“Outside In”);
      filterField.sendKeys(Keys.ENTER);
      individualOrderNotFound = true;
  }
  catch(StaleElementException e){
      Thread.sleep(2000);
  }
  catch(NoSuchElementException e){
      Thread.sleep(2000);
  }
}

I found my monster in the room. So I asked for help.

A tester from another team replaced the loop for the movie selection by a couple of sleeps.

Thread.sleep(2000);
filterCombobox.click();
Thread.sleep(2000);

selectMovieOption();
filterField.sendKeys(“Outside In”);
filterField.sendKeys(Keys.ENTER);

The code was a bit slower, but more reliable. 5 out of 5 passed. I better got used to this.

Hypothetical causes

Retrospecting my coding was not pleasant. I did not stick to my own FAQ. And this can happen.

Now let me focus on the working code.
My fellow tester gave me the tip to use sleep. This way any delays would be handled.

There were two statements “filterCombobox.click();” and “selectMovieOption();”, which were preceded with sleeps. Therefore there were two places where exceptions could occur. In my loop I assumed that there was only one place for exceptions. The worst part was that I picked the wrong action.

Let me illustrate, what would happen, if I handle exceptions by starting over at the wrong spot.
I have a recipe for baking. I have enough flour and more than enough eggs. First I find the flour. Everything goes right: there is no exception. Then I put 200 gram of flour into a bowl.

For the second step I pick an egg. I break the egg and the smell is bad. That is an exception. The egg goes into the wastebin. So I start all over. I empty the bowl.

First step I have to weigh the flour, but there is no flour any more. Now I have an exception and I cannot finish the recipe.

A much better way to find a good egg without throwing away the flour.

This is something I need to research.

Final Fantast I C Assert

At the end of every regression test there should be one final check. A simple yes or no would indicate, whether the test has passed. For the cinema reservation system this was quite simple. Has the order for the tickets, drinks, and snacks sent to the cinema?

I let Selenium set the search field to Order Id and enter the Order id. I saw a Stale Element Exception. Time for my FAQ. I used findElement at the latest moment. Stale Element Exception.

I let Selenium switch to another menu and back to the right page to continue.
Stale Element Exception.

Which other steps were possible?
I let Selenium log off and log on. A search of the Order Id followed.
The order was not found, so it was sent. Test passed.

Another look at Continuous Delivery

It was like delivering a message. If one way did not work out, another way was explored. What had a mail delivery person, a milk delivery person, and a mail delivery teacher in common?

They all wanted to deliver a letter to Mr. H. Potter. Persistence paid off. And be nice to the messenger. The delivery story had a nasty tail.

Deliberate Practice

Of course this post should end with some smart code.

While blogging I was going through the chapters of the free course about Selenium WebDriver and Java of Angie Jones on the Test Automation University. In Chapter 9 about Wait Strategies I found FluentWait. One of the cool things about this command, that it could ignore exceptions.

A part of the solution was:

Thread.sleep(2000);

selectMovieOption();

This code was not optimal. If the environment or network is changed, then the sleep time might be adopted each time. A FluentWait would provide a robust and fast solution in this case.

FluentWait wait = new FluentWait(driver)
  .withTimeout(Duration.ofSeconds(8))
  .pollingEvery(Duration.ofSeconds(1))
  .ignoring(NoSuchElementexception.class);
wait.until(ExpectedConditions.visibilityOf(
  driver.findelement(filterCombobox)));
selectMovieOption();

Also Alan Richardson released a paid course about test automation on LinkedIn: Advanced Selenium: 3 Synchronization Strategies. If I need more tricks, I consider to have a close look.

My improved FAQ for test automation

Q: What to do, if I always have a No Such Element Exception?
A: There is a good chance, that the web element cannot be found. So my way for to locate the web element is bad. There are several ways to find a web element.

Q: What to do, if I always have a Stale Element Exception?
A: There is a high chance, that TestNG is used. The element to be used cannot be found any more. In this case I use a findElement as late as possible.  Another option is to add some additional steps like logging out and logging in.

Q: What to do, if I have a No Such Element Exception once in a while?
A: Use a FluentWait.

Q: What to do, if I have a Stale Element Exception once in a while?
A: See the answer on the previous question.

Q: Do you have anything to add?
A: Have a look at Deliberate Practice. I mean the way of learning and not the previous chapter.

Selenium, I think this is the beginning of a beautiful friendship.

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

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.

Find The Button In The Room

Introduction

This is my second blog post in the Find In The Room blog post serie. In order to avoid any legal issues I sanitised my story. It is about software testing and IT: test automation.

For this story I will use the Cinema Hype VIP website.

Voice commercial:
“Are you tired to buy drinks and snacks for a child birthday party in a cinema?
Cinema Hype VIP website is here to rescue you.”
Author – that’s me: “Let me turn down the volume.”
[Presses a button]
Commercial [Loud voice] “Now you can order everything before setting a foot in the cinema.”
Me: “Excuse me. Let me mute the volume.”
[Presses a button]
Commercial: [Loud voice] “What are you waiting for?”

Me: [Surprised]
[Presses a button]
Commercial: [Silent]
Me: [Silently smiling]
[Presses a button]
Commercial: [Silent]
Me: “Test. 1 2 3. ”

Commercial: [Silent]
Me [Remains a few seconds silent.]
Commercial: [Silent]
Me [Looks a few lines up and down.]
Me [Remains a few seconds silent.]
Commercial: [Silent]
Me: “Ahum.”
Commercial: [Silent]
Me: “Someone is watching me from a few lines above.
Oh, I watched myself.”

The moment of approval

In my introduction I wrote several times about the button. It took me some effort to find the right button.

Now it is time for a real world test automation example. For my first big test automation experience I programmed the steps in Java. Selenium was used for the interaction with the website.

One of the most important steps of a website is pushing a button. These days a lot of deals are closed with a press of a button. Also online transactions need some key presses to pay. So I must be able to find a button on the web page.

Let me return to the Cinema hype VIP website.
My kid has a birthday party and all tickets, snacks, and drinks are listed. The only thing I have to do is to press a button.

The quickest way

Years ago I thought that there was one way to find a button.

  • Right click the button and select Inspect in the Option menu.
    An option  menu is shown above the OK button. The last menu option is Inspecteren or inspect in English!
  • Select the HTML code of the button and copy XPath.
    In DevTools  menu is shown above the HTML text for the OK button. This menu contains the sub menu Copy containing the option Copy XPath!
  • Give XPath to Selenium to find the button.
  • Pat myself on my shoulder.

Then my attention was drawn to the free online course of Andrew Knight, Web Element Locator Strategies, on Test Automation University.
So what did I actually use?

An XPath is basically a route description through the web page. And it can look a bit scary:
/html/body/div[2]/div/div[2]/button
This is of course automatically followed by Selenium. That is something programs tend to do. There is 1 huge problem. If signs change, then Selenium cannot find its way.

Let me use an arbitrary text on a letter and transform it to a more computer friendly notation.

/Surrey / Little Whinging / Privet Drive 4 \/The Cupboard under the Stairs / Mr. H. Potter.

If his uncle would move Mr. Potter to a bed room, then the postman had still no problem with delivery. Same address and a decent room this time.

Would it a bit more convenient to address the letter to a mister called H. Potter? A muggle postman would have serious problems, if this Mr. is evacuated to an island before his 12th anniversary. But finding him is a Half Giant job for a bloke like Hagrid.

This would lead to:
//Mr. H. Potter

But computers need more details:
//Human[contains(text() = 'Mr. H. Potter`]

Find a button with text OK.In that case I would get something like
//button[text()='OK']

The HTML code of the OK is hightlighted, while the search bar contains the text “//button[text()='OK']” followed by the text “1 of 1”!

Let me give you a more precise translation:

  • “//” means “Find somewhere on the page”
  • “button” means “the first button you encounter”
  • “[text()= ‘OK’]” means with the condition, that the text is equal to ‘OK’

No idea

But this does not completely explains:
/html/body/div[2]/div/div[2]/button

  • “/” means “search directly under”
    “body/div” means “search the first div under the body”
  • “[2]” means the second, so
    “div[2]” is the second div.
  • The rectangular brackes, “[” and “]”, are useful, if I do not need the first , but another one in the row.

The website I was testing was created with a low code tool. This tool can be compared with an advanced presentation tool, which also builds a fully functional website.

With great power comes great creativity. This basically means, that certain things were not fully under control of the developers. As a tester I had to solve these problems.

Placing a button on a web page led to an explosion of actions. Lots of code were automatically added, but this led to names like 1_saveFiles.

So I used ‘1_saveFiles’. A fellow tester pointed out, that the low code tool could change the button name to ‘2_saveFiles’ at will.

So I focused on the last part of the string.
//Button[contains(@name, 'saveFiles')]
This means such much as
“Search a button with the name containing saveFiles”
Of course there is a faster way to address an element using the attribute id. There is no magic needed to find Mr. Potter, if we were on the same page.
//Human[contains(@id, 'Mr. H. Potter`]

By the way id is pronounced as at Eye Dee instead of it. If you want to surprise your big sister or brother test automator, then use a sentence like “That element had probably no id.” Don’t forget a little sigh.

In my case id was not always set. To make things a little more challenging for me a single condition was not enough.

This is an exaggerated situation:
Code for dirnks: <input class="radio" name="2_drink" type="radio" value="one"> Cola</label> <br> <input class="radio" name="2_drink" type="radio" value="two"> Lemonade</label> <br> <input class="radio" name="2_drink" type="radio" value="three”> Sparkling Orange</label> <br>!

//input[contains(@name, 'drink')]
This might lead to some drink

//input[@value = 'two')]
could lead to the second drink or second snack.

So I chose for two conditions:
//input[contains(@name, 'drink')][@value = 'two']

There were other cool tricks in the course of Andrew Knight. The described ones in this blog post were big time savers.

Show and fail

It was time for the demo. My team liked that I would show my scripts in action. People were looking when I kicked off the tests.

An unexpected dialog popped up. I had to close it. What went wrong?

I apologised and left the stage. My team members postponed the demonstration of my tests.

Time for another blog post.

Escape The Consultant Trap

During a talk at a test conference a consultant told smilingly to stick to customers. The woman next to me was bristling. Her company hired consultants.

Is there a way to make this situation more painful for me?
You bet.

As a test consultant I had given her a ticket for the conference.
Ouch.

A good consultant makes herself or himself dispensable.

Definition obliged

Looking at the Dutch job market there is a cry for test automation experts. Even testers with a few months of experience have a distinct advantage over the inexperienced testers. They have a proof that they can use the demanded tool. And they are hired.

So if a company really needs test automation and no candidates have been found, then a test automation expert is flown in. This gives the company a real advantage. Or wings for the intended pun.

What is the consultant trap? After a while there is a test framework and lots of scripts and impressive heaps of test data which must be executed, updated, and maintained. In good order.

It is like buying a car which needs intensive care. If it is neglected for too long, then the car will not ride.

All the test automation stuff can be compared with a car. The mechanic is the test consultant.

No consultant means no working test automation, which means no edge, less revenue, and stronger competition. The company is trapped. This also hurts the revenue.

Path obliged

There are some managers who would object with

  • “This is a proof of concept.”
  • “The product is at the end of the life cycle.”
  • “The consultant is only hired during the holiday of one of my employees.”

These sound like sound arguments.

In this blog post I want to focus on test automation experts who are the only ones to operate the test automation in a company.
That’s bad.

Suppose you are a manager and you have the task to improve test automation. Now you have to avoid the consultant trap.

But you still need a consultant to teach test automation to your team member.
Hummm.

According to me a good teacher doesn’t make the homework of a pupil. In terms of test automation a consultant is helping your team member with learning instead of putting all test automation in place.

Don’t touch everything.

Is there a way to determine whether a consultant is a good teacher?
Sure.

Ask to explain how to set up test automation in plain language. Or ask for possible first steps in your company. Other useful resources are recommendations of other customers, talks, or blog posts.

My suggestion is to keep the number of hours of the consultant low and the number of hours spent by your team member high.

My favourite way to learn something new is pairing. As a pupil I like to share the same computer with an expert while figuring out what is happening. The teacher (she or he) demonstrates things to me and then let me struggle.

Pairing is an activity for 2 persons. I do not like searching the right note with fast scribbled words on it because of the high pace of demonstration. And then interrupting my teacher who is teaching someone else in the meantime.

Attention!

While I was learning Test Driven Development, a junior DevOps engineer was watching every step I took.

Once in a while he made remark. Then I told my thoughts aloud and he would gently lead me to the right solution. He had an educational degree and earned my respect.

In short it is about finding the right balance between demonstrating and experimenting.

Another way for me to learn is exploring. Elisabeth Hendrickson made a nice concise format for this:
Explore < target > with < resources > to discover < information>.

I personally like exploring because of the hidden treasures I might find. Dungeons and diamonds.

OK. Back to the Example.
(No DeLorean included.)

A consultant could suggest something like
“Explore data driven testing with Postman to discover a concise way to maintain test scripts.”
A bit vague.

I tend to ask questions.
“What is data driven testing?”

A good teacher will give some examples:
“Suppose you buy 2 items costing 1 Euro each. What will be the total cost?”
“2 Euro.”

“And if you buy 4 items costing 1 Euro each. What will be the total cost?”
“4 Euro.”

“6 items for the same price?”
“6 Euro.”

“23 items.”
“23 Euro.”

“What did you notice?”
“The question became shorter. And you only changed the number every time.”

“So the numbers are data. What I described were 4 simple tests. In Data driven testing a tester or developer extracts data from the tests. So you only need 1 test with a set of data.”

“What would be a good to store the data?”
“A table like in spreadsheet program.”

And this conversation and experimentation could continue for hours.

After the session a debriefing can take place to reflect and determine new points of interest.

After a while I could explore on my own. If I get stuck, then I could contact the consultant.

Let me write about exploration of data driven testing on my own.
“What is the first place to look for?
I don’t like manuals.

Wait. This is cool:
TestAutomationU offers a free online course from Amber Race about Postman.

It contains a section about data driven testing.”

For the video I used sketchnotes for note taking. When I did some experimentation in this course, I used a word processor for notes.

Also now a debriefing is the way to reflect and to determine new steps. A consultant or colleague can be a person to speak with.

Proposal obliged

If there is a company where I would like to work, then it is the one with experimentation and growth mind set. It will earn my loyalty.
Hold my engineer degree.

As a manager you might complain about the time spent. As an Agile practitioner I would answer that competitors might outperform your company by learning and teaching.

In summary hire people with ability to learn and ability to teach test automation.
Thank you for your attention.

Okay time for the legal stuff.

Disclaimer: I have no experience with this approach to escape the consultant trap. I did not do any research. But I do welcome feedback.

According to me this proposal is agile. You learn and adapt. Luckily agile is in high demand.
Say Cheese.

Disclosure: at the moment of publication I wa jobless, so I was biased.

Tricky Driver Dilemma

Ability to learn

Decades ago I had a colleague without a driving license. In case of trouble he would take public traffic or got a ride of his boss. His boss decided to give him driving lessons during office hours. It saved the company time and money.

Suppose you have a delivery firm. Your company picks up packages and delivers them to the right addresses.

It takes about a few months to get a driving license for a car. But sometimes a motorcycle is more convenient. This will take another few months. If a lot of packages must be delivered, then another driving license for a truck is needed.

For super fast and expensive delivery you can use a spacecraft and …

This is the point, that a favourite quote of a project leader is used:
“This is no rocket science. ”

Searching testers

OK time for the real message.

Suppose you are a manager of a Dutch software delivery company.
You look surprised, but you mentioned Continuous Delivery. Let me continue with writing.

You happen to need a tester. On the Dutch tester job market there is a shortage of qualified men and women. The basic requirement is test automation.

A paper with "Qualified" lies on 2 steps "Advanced" and "Expert"

Why is test automation so hot?
My guess is DevOps or competitors.
But you are the manager and you have all the clues.

So you have to hire consultants to get things tested. And that is quite expensive.
At the end of the project or sprints you have less profit and less experience in your own workforce.
A graphs with a vertical axis with "Profit" and a horizonal axis with "Time" containing a red slow rising line with "Consultant" and a green steeper rising line with "Employed tester" above the red line

A graph with vertical axis with "Company expertise" and a horizonal axis with "Time" containing a red slow rising line with "Consultant" and a green steeper rising line with "Employed tester" above the red line

The only solution is to hire and train testers. Just like the driving license story it takes months and probably years to get testers at the right level.

New testers should be hired for their ability to learn. Of course you can wait, until an experienced test automation tester knocks on your door. Maybe you are lucky this year.

Basically you have a vendor lock in. You desperately need a consultant for the test automation.

A piece of paper with a picture of a lock and "Lock" lies on a step with "Expert"

According to me there are more unskilled testers willing to learn than qualified testers looking for a new job.

A tester is just unlucky, if he or she was not able to touch tools like Selenium and Cucumber during project or sprints.

Teaching matters

One of the things I learned is Zone of Proximity. If people are in the same zone, then they can teach each other.

Stairs with steps "Intermediate", "Advanced", and "Expert" on a floor "Beginner". A rubber band lies on the step “Intermediate” and “Beginner”

There are companies which really want qualified or expert testers.  It is too difficult to  teach test automation to testers with beginner level. In this case they are outside the Zone of Proximity. It would cost your company too much time and money.

Stairs with steps "Intermediate", "Advanced", and "Expert" on a floor "Beginner". A rubber band lies only on the step “Intermediate”.

  • A solution is to lower the requirements for testers and invest more time in teaching. This might attract more candidates.
  • The other option is to keep the requirements and hope high to attract the expert tester. Wait a minute. Wait a week. Wait a quarter.

In the ever changing world of software delivery you need a new edge: how well can you teach testers test automation?