Sunday, December 8, 2013

goto considered helpful (in some cases)!


    There are occasional debates on whether it's good to have "goto" statements in a program or even in a programming language.  The typical argument by a proponent is a little weak:  "goto" can help jumping out of a nested loop. As far as I can see,  the proponents are typically on the losing side.    Sadly, I am one of them.  In this blog,  we are going to present a better argument   using "goto" can be natural for certain audience in some cases.

    Some developers may argue that we can use "if", "while" etc to accomplish what "goto" statements can do.    Yes, that's true, but it doesn't feel natural and easy for our audience: those without a lot of programming background.  "goto" (or jump) feels more familiar for them.

   On Netgend test platform,  we use javascript syntax. It may appear that it's impossible to support "goto" since javascript language itself doesn't support it.  We came up with the following way around it. To set a label, you can call a function "setLabel(<labelName>)",  to jump to a label, you can call "goto(<labelName>)".

    Here is a simple example to illustrate how it is used.
  function VUSER() { 
      id = 2; 
      println("start");  
      setLabel("test1");  // <--- set the label here
      println("hello"); 
      id --; 
      if (id > 0) {  
            goto("test1"); // <--- jump to label
      }  
      println("world");
 }  

    In this example, the println("hello"); statement will be executed twice (the second time is due to the "goto" statement),  the output is
 start  
 hello  
 hello  
 world  

    Now let's look at an example that's a little more realistic:  we need to emulate sensors trying to register with a master. Master node may ask a sensor node to wait a little bit and try again.

 function VUSER() {
       connect("1.1.1.1", 12345);  
       setLabel("register");  
       send("register by ${userId}");  
       recv(response);  
       if (match(response, /please wait (\d+) ms/) {  
          sleep(g1);  
          goto("register");  
       }  
       //now send data to master 
}

    It's true that the above logic can be done with a while loop, but it's much easier for a test engineer to understand the logic if we use "goto" here.

    Finally as a simple, real world example, we need to emulate a user who visits an e-commerce site,  with the following distribution:
  • 70% probability, the user will just browse the product
  • 20% probability, the user will exit the site.
  • 10% probability, the user will register and continue to browse product
 function VUSER() {
       action(http, "http://www.example.com");  
       isRegistered = 0;  
       browsePercentage = 70;
       exitPercentage = 20;
       registerPercentage = 10;

       setLabel("userAction");  //<--- let the fun start
       if (isRegistered == 0) {  
            choice = rolldice([browsePercentage, exitPercentage, registerPercentage]);  
       } else if (isRegistered == 1) {  
            choice = rolldice([browsePercentage, exitPercentage]);  
       }  
       if (choice == 0) { //browse product
            //pick a product and view it  
       } else if (choice == 1) { //exit site  
            return 1;  
       } else { //register  
            //register actions
            isRegistered = 1;  
            browsePercentage += registerPercentage;  
        }  
       goto("userAction");  
}
    The rolldice() function above will pick a choice (it's 0 based) according to the percentages. Based on the value of choice, we perform one of the 3 actions and go back to "userAction" to decide what to next.

    Human mind is wired to understand "goto" faster, let's keep it that way for performance testing.

No comments:

Post a Comment