How can I make my tests execute faster?

This is a common question that often arises from Silk Test users. In most instances we find that a number of efficiency gains can be obtained from changes to how the tests are scripted.

The Silk Test suite provides many ways of interacting with an application under test (AUT), some of which can drastically reduce the overall execution time of your tests. This blog provides information on how the findAll method can help reduce the overall execution time of tests with Silk4J. The procedure is similar for the other Silk Test clients.

The following code snippet was created by a real Silk4J user to determine the number of different controls within a Web Application. When executing tests in Chrome and Firefox, the user found that the execution time was significantly higher than in Internet Explorer. When tracing through the Silk4J framework of the user, we discovered that the vast majority of the additional execution time was being lost in a utility method called countObjects. The utility method was scripted as follows:

public void countObjects( ) {

desktop.setOption(“OPT_TRUELOG_MODE”, 0);

int iCount = 0;

int i = 0;
while(desktop.exists(“//BrowserApplication//BrowserWindow//INPUT[“+(i+1)+”]”) ) {
i++;
}

iCount += i;

i=0;
while(desktop.exists(“//BrowserApplication//BrowserWindow//SELECT[“+(i+1)+”]”) ) { i++;
}

iCount += i;

i=0; while(desktop.exists(“//BrowserApplication//BrowserWindow//BUTTON[“+(i+1)+”]”) ) { i++; }

iCount += i;

i=0;
while(desktop.exists(“//BrowserApplication//BrowserWindow//A[“+(i+1)+”]”) ) {
i++;
}

iCount += i;

System.out.println(“Counted “+iCount+” items.”);

}

The initial analysis of the method indicated that the code was not efficient for the task at hand.

Why was the above code not efficient?

The following areas were identified as being not efficient:

  1. The method counts each control individually; therefore if there are 100 controls to be counted, the above snippet would make over 100 calls to the browser to count the required controls.
  2. The use of while loops in the above fashion would eventually lead to unnecessary calls to the browser and therefore execution time which was being wasted.

How could the code be made efficient?

Analysis of the countObjects method revealed that the same functionality could be achieved in four Silk4J statements. To make this possible the method was modified to use the Silk4J method findAll. This method returns a list of controls matching a specific locator string with a single call, therefore it has the following benefits over the original approach:

  1. Each control does not need to be found individually before incrementing the count.
  2. No unnecessary calls are made to the browser

The modifications resulted in the following method:

public void countObjects ( ) {

int iCount = 0;

iCount += desktop.findAll (“//INPUT”).size( );
iCount += desktop.findAll (“//SELECT”).size( );
iCount += desktop.findAll (“//BUTTON”).size( );
iCount += desktop.findAll (“//A”).size( );

System.out.println (“Counted “+iCount+” items.”);

}

Visually the modifications have already reduced the number of lines of code required to perform the same functionality as the original utility method. There is now also no requirement for loops of any sort and from an execution standpoint, we were able to demonstrate the following performance gains:

Chart01

The above chart and table demonstrate how much time a user can gain by simplifying their code through the use of other methods within the Silk4J API that are more suitable for a particular task. The performance gains in Google Chrome and Mozilla Firefox are hugely substantial, while the execution time in Internet Explorer is now less that a second. Overall this process has resulted in better code, better efficiency, and ultimately time saved.

Can I apply this to other parts of an automation framework?

In the following example the user needed to verify that the labels and values within a number of tables have the correct text values. Again, the execution time in both Mozilla Firefox and Google Chrome was considerably higher than the execution time in Internet Explorer. For example, the user experienced a great difference in execution times when executing the following method:

public void verifyLabels (String[ ][ ] expected) {

for (int i=1;i<=17; i++) {
DomElement lbl = desktop.find (“//TH [“+i+”]”);
DomElement value = desktop.find (“//TD [“+i+”]”);
Assert.assertEquals (expected [i-1] [0], lbl.getText ( ) );
Assert.assertEquals (expected [i-1] [1], value.getText ( ) );
}

}

Why was the above code not efficient?

In the above method two find operations are being executed inside the for-loop. Each iteration of the loop increases the index of the controls to be found. To find all the elements of interest and to retrieve the text of those elements, 68 calls to the browser are required.

Where are the efficiency gains?

As the loop is simply increasing the locator index, which indicates that Silk4J is looking for a lot of similar controls, the find operations within the for-loop can be replaced with two findAll operations outside of the loop. This modification immediately reduces the number of calls that must be made to the browser through Silk4J to 36 and the method now reads as follows:

public void verifyLabelsEff(String[ ][ ] expected) {

List <DomElement> labels = desktop. <DomElement>findAll (“//TH”);
List <DomElement> values = desktop.<DomElement>findAll (“//TD”);

for (int i=0;i<17; i++) {
Assert.assertEquals(expected [i] [0], labels.get(i).getText ( ) );
Assert.assertEquals(expected [i] [1], values.get(i).getText ( ) );
}

}

Performance Impact

The chart below highlights how small changes in your Silk4J framework can have a large impact on the replay performance of tests.

Chart02

Robert

Share this post:
Tweet about this on TwitterShare on FacebookShare on LinkedInGoogle+

Leave a Reply

Your email address will not be published. Required fields are marked *