Selenium IDE – How to verify html-table

From time to time every programmer creates a table which looks like this:

test page in browser

Please take notice, the total quantity and the sum look strange. They have to be verified.

The table is simply a set of rows. Look at source code:

source of test page

 

I’m going to sum the values from the second cell for each row and compare the calculated value with the total quantity. The same should be done with the values of the third cell to get the total amount.

In order to do that, I store the value of the second cell into a global variable ‘quantity’ in Selenium IDE
[crayon-5d7ddcbd38bf5816502334/]
It works, but I need the value of the second cell of each rows. For this we need to loop through the lines:
[crayon-5d7ddcbd38bf9601823379/]
Why does the increment of the index look so strange: new Number(${index} + 1) ?

Because normally “+” concatenates strings.

We get the quantity of each row now and they should sum into a different variable.

At first I define the global variable ‘totalQuantity’:
[crayon-5d7ddcbd38bfa680550857/]
and then I sum all quantities into it in the loop:


[crayon-5d7ddcbd38bfb030637144/]

Now I have the total quantity at the end. The same way I get the total amount into the variable ‘totalPrice’.

But there is another small problem in cells containing the price: the price has the euro sign before and the text after the price value. In order to use the value we need to get rid of all excessive characters. We can remove it as following:

price.replace(/[^0-9.,]*/g,””)

and convert a decimal separator into ‘.’ then:

price.replace(“,”,”.”)

Finally the complete script is there:

selenium ide

And, as expected, it reports an error: the total quantity must be 4 though we show 5 in the table.


Selenium Grid - How does it work

Grid

When we start one of our Selenium tests, then a request is sent to the Hub.
The Hub checks all the Nodes which are registered, for a System, that matches the desired Capabilities for the started testcase (for example, Chrome).

DesiredCapabilities

With a match, the Hub sends the Selense to the Node which is communicating with the browser and the test will be executed step by step. If there is no free slot on the matched Node, then the Hub will wait and try again until the timeout is reached.

Seleneium_Grid

Source: http://goo.gl/RwUijO

In our case the tests are structured in a way, so that it use specific URLs to reach different application systems depends where the tests will run. That means, when we start the tests local on our own developer machine, then it works with the local code and application. When we start it on the grid instead, then the Version on the Testsystem will be tested.


Iterative Performance Tuning of Web Apps

In my last blog post I described how to use Firebug's Profiler in order to find out which parts of your code are most time consuming and are responsible for the performance issues you might experience. Today I am showing you how I used the Profiler as a step in the iterative process of tuning the performance of a web app.

Steps of the iterative performance tuning process:

According to Wikipedia, the systematic tuning of performance comprises the following steps:

  1. Assess the problem and establish numeric values that categorize acceptable behavior.
  2. Measure the performance of the system before modification.
  3. Identify the part of the system that is critical for improving the performance. This is called the bottleneck.
  4. Modify that part of the system to remove the bottleneck.
  5. Measure the performance of the system after modification.
  6. If the modification makes the performance better, adopt it. If the modification makes the performance worse, put it back the way it was.
  7. start at 1. again

The Problem & Performance before the test

In my application, the performance issues concerned the searching functionality. I have a list with more than 45000 items which is searched for a search term the user can enter in a search field. The search itself uses an implementation of the Soundex algorithm (I described the Soundex Algorithm and the adoptions I made in order to use it for the German language in an earlier post) to match the search term against the items. I observed the performance to be awful especially on mobile devices.

I did not establish a numeric value to define acceptable behaviour. I just wanted it to improve significantly (being well aware that "improve significantly" is a heavy violation of the SMART principle…) so that the user does not deem the application dead while waiting for the search to finish…
Repeatedly running the Firebug profiler gave me the average of about 4500ms per searching task.

Identifying and removing the bottleneck

Using the Firebug profiler, I received the following profiling report (excerpt):

profiling report before the tuning

With the help of this report, I could easily identify the first three function calls as the bottleneck of my search. The first of them is an access to the database to retrieve all items of the list, the second the transformation of a search term into its Soundex code, and the third a filtering operation.

Generally, there are two options to deal with these functions: either to improve the function so that less time is spent for its execution, or to reduce the number of calls of that function; which of the two options is best of course depends on the function's internal logic.

I started by analyzing the first of the functions and checked where it was called. I found out that accessing the database could be prevented entirely here. Until now, the same variable was used for storing the list as it appears when it is not filtered, and for storing the list when it contains only the search results. So what happened during each search was that first, the list got emptied completely. Then, a list with all available items was demanded from the database and then filtered for the search item. I introduced a separate variable to store the list with the unfiltered items. Now the search can use this variable instead of retrieving the list from the database.

Assessing the improvement

Having made this modification, I ran the profiler again in order to check if the performance has indeed improved. As I had expected, the function that accesses the database was not invoked a single time, leading to an improvement of about 1500ms! This was a great success, so I kept the changes.

I also had a look at the other two bottlenecks. I could not improve the Soundex algorithm, nor could I reduce the amount of calls of that function. However, I was able to make some further improvement by making some minor changes to the filterBy function. Even though the modification decreased the average time spent in this function by only about 0.015ms, this accounts for quite a lot if it is multiplied with 45426, the number of calls of this function.

In total, a sorting task now takes about half the time it did before. Here is an excerpt of the profiling report after the tuning:

Profiling report after optimization


Using the Firebug Profiler for profiling web apps

I am sure every programmer is quite familiar with such situations: you are bursting with pride and self-content because your app is finally running without errors. You try it out on a mobile device for the first time, and you are thoroughly disappointed to realize that the performance of your masterpiece is just awful …
Then it is just about time for some profiling. This blog post will show you how profiling a JavaScript application can easily be done using Firebug's Profiler.

Alternative Profiling Tools

Although many other browsers provide built-in profiling tools (such as Chrome, Internet Explorer or Safari), I liked Firebug's Profiler best for its highly detailed profiling report and its way of presenting the results so that you get the most important information at one glance.

How to use the profiler

To start using Firebug's Profiler, you need to open Firebug. Select the Console tab and click on "Profile". The profiler is running now and observing all your JavaScript activity, making statistics about time consumption.

starting the firefox profiler

All you need to do now is trigger some activity. I am having performance issues with searching for a particular entry in a table in my app. So I enter a search term, start the search and wait until the search results are displayed. Then I click "Profile" again in order to stop the Profiler. Firebug now opens a huge table (well, that actually depends on the complexity of your code…) containing the profiling results. Here is an excerpt from the table I got:

profiling report

How to read the results

The great art now lies in correctly interpreting the results in order to know which part of the code is causing the trouble. Therefore it is vital to know which information is contained in the report:

In the top left corner, the profiling report specifies the total amount of time for executing the activity, as well as the total number of function calls that were involved. The table below lists every function that was called during the sort. The columns provide the following information:

  • Function: the name of the invoked function
  • Calls: how often has this function been called?
  • Percent: the percentage of time this function consumed in relation to all other functions within the sorting
  • Own time: total time spent within the function (summary of all calls)
  • Time: total time spent within the function (summary of all calls); the difference to 'own time' is that 'time' also includes the time spent within functions that were called by that function
  • Avg: average time for one call of the function
  • Min: minimal time for one call of the function
  • Max: maximal time for one call of the function
  • File: the name of the file in which the function is located and the line number of the function; a link leads directly to the file

By default the table is sorted so that those functions accounting for the highest percentage are listed first. Thus your culprits are easy to spot!

Having conducted the profiling and identified the functions responsible for the high time consumption, we need to start to analyze those functions and think of ways to improve their performance. How I used the profiling report to improve the performance of my search I will describe in a following blog post.