Friday, February 28, 2014

Multiple downloading made easy

    Most test platforms can emulate a user downloading a (big) file.  What if we need to emulate a user downloading multiple (big) files at the same time?   That's why a question was asked in a forum on implementing HTTP asynchronous downloads.

    This nice tutorial gave an implementation on the JMeter platform.  The test scenarios is about getting to the main download page and download multiple software images simultaneously.   It's related to the test scenario of downloading all the resources files on a HTML pages (such as images, css, js), but that is typically handled directly by a test platform.  What's new here is that the tester needs to control explicitly on what HTTP request(s) to make simultaneously.

     Here is the key part of the HTML download page: a dropdown box and its HTML code:

 <select name="current_os" id="current_os" class="select stacked" onchange="this.form.submit()" >  
 <option label="Select Platform&hellip;" value="0">Select Platform&hellip;</option>  
 <option label="Microsoft Windows" value="3" selected="selected">Microsoft Windows</option>  
 <option label="Ubuntu Linux" value="22">Ubuntu Linux</option>  
 <option label="Fedora" value="20">Fedora</option>  
 <option label="Oracle &amp; Red Hat Linux 6" value="31">Oracle &amp; Red Hat Linux 6</option>  
 <option label="Mac OS X" value="5">Mac OS X</option>  
 <option label="Source Code" value="src">Source Code</option>  
    We need to extract the values (the characters in bold font) and use them to start downloads.

    The solution given in the above tutorial is quite detailed with long instructions and many snapshots. Some part is about using regular expression to extract the values,  the part on the Jmeter plugin for inter-thread communication is new and more technical.  For those who are less familiar with the concepts of an operating system, inter-thread communication can pass information (like a URL) from one execution thread to other execution threads so that other execution threads can process the information passed in (it means downloading in this case) at about the same time. Without this plugin, the JMeter will have to do all the downloading sequentially.

  This makes me wonder how to implement it on NetGend test platform. Turns out it's pretty simple:

 function VUSER () {  
      values = substring(http.replyBody, 'value="', '"', "all");  
      urls = [];
      for (i=0; i < length(values); i ++) {  
           if (match(/^\d/, values[i])) {
                 push(urls, "${values[i]}");  

     In the above script, we used the function substring() to grab the values.  This function uses a left boundary and a right boundary and grabs the part in between. The last parameter ("all" in our case)  tells the function to grab all such parts. Not surprisingly it returns an array ("values" in our case).   Next, we use a simple loop to create an array of URLs (variable "urls" in our case) out of the values.  Note that we use a regular expression function to "match" only those values that are non-zero numbers (it will skip the values such as "0" or "src" in our case).   The part that does the job of the Jmeter inter-thread communication plugin is the spawn() function, it takes a list of URLs and starts the HTTP transactions on them at the same time and waits for all of them to finish before moving on.

    Note that the extraction of values can be improved by using this XPath:
 values = fromHtml(http.replyBody, '//select/option/@value', "text");   
It requires a little more knowledge, but it's actually not too difficult to learn and it's more resistant to the variation on HTML encoding where double quote may be skipped in some cases.  For example in an equivalent HTML code <option label="Microsoft Windows" value=3...    the double quote after value= is skipped.

    We are happy not only because NetGend can implement the test scenario, but also because our solution is so simple that users do not need to understand the concept "inter-thread communication" and do not need to install a plugin to do it.

No comments:

Post a Comment