Suppose you have a very simple page that permits you to search customers in northwind database and visualize orders, a classic master-detail page.

image

Figure 1: A classic Master-Detail page

Now suppose that you need to create a VS web test to search for each letter of the alphabet, and for each result page you should visit order details. Thanks to VS 2010 we have another construct for Web test called Loop, but there is no out-of-the-box loop condition to iterate with all the letters of the alphabet, so I need to build a custom one. To create a plugin for loop test you need simply to inherit from the ConditionalRule class and write a little bit of code:

   1: public class CharLoop : ConditionalRule

   2: {

   3:     // Fields

   4:     private ForLoopComparisonOperator _comparisonOperator;

   5:     private string _contextParameterName;

   6:     private Int32 _incrementValue;

   7:     private Char _initialValue;

   8:     private Char _terminatingValue;

   9:  

  10:     // Methods

  11:     public override void CheckCondition(object sender, ConditionalEventArgs e)

  12:     {

  13:  

  14:         Char num = Convert.ToChar(e.WebTest.Context[this._contextParameterName]);

  15:         num = (Char)(num + _incrementValue);

  16:         e.WebTest.Context[this._contextParameterName] = num;

  17:         switch (this._comparisonOperator)

  18:         {

  19:             case ForLoopComparisonOperator.LessThan:

  20:                 e.IsMet = num < this._terminatingValue;

  21:                 return;

  22:  

  23:             case ForLoopComparisonOperator.LessThanOrEqual:

  24:                 e.IsMet = num <= this._terminatingValue;

  25:                 return;

  26:  

  27:             case ForLoopComparisonOperator.GreaterThan:

  28:                 e.IsMet = num > this._terminatingValue;

  29:                 return;

  30:  

  31:             case ForLoopComparisonOperator.GreaterThanOrEqual:

  32:                 e.IsMet = num >= this._terminatingValue;

  33:                 return;

  34:         }

  35:         e.IsMet = false;

  36:     }

  37:  

  38:     public override void Initialize(object sender, ConditionalEventArgs e)

  39:     {

  40:         if (e.WebTest.Context.ContainsKey(this._contextParameterName))

  41:         {

  42:             e.WebTest.Context[this._contextParameterName] = this._initialValue - this._incrementValue;

  43:         }

  44:         else

  45:         {

  46:             e.WebTest.Context.Add(this._contextParameterName, this._initialValue - this._incrementValue);

  47:         }

  48:     }

  49:  

  50:     public override string StringRepresentation()

  51:     {

  52:         return string.Format(CultureInfo.CurrentCulture,

  53:             "Initialvalue{0} increment {1} context {2} terminating {3}",

  54:             new object[] { 

  55:                 this._initialValue, 

  56:                 this._incrementValue, 

  57:                 this._contextParameterName, str, 

  58:                 this._terminatingValue });

  59:     }

  60:  

  61:     // Properties

  62:     [Description("Operator to compare to compare the value with the actual one"),

  63:     DisplayName("Comparison operator"), DefaultValue(0)]

  64:     public ForLoopComparisonOperator ComparisonOperator

  65:     {

  66:         get

  67:         {

  68:             return this._comparisonOperator;

  69:         }

  70:         set

  71:         {

  72:             this._comparisonOperator = value;

  73:         }

  74:     }

  75:  

  76:     [Description("Name of context parameter where the current value should be set"),

  77:     DisplayName("Context parameter"), IsContextParameterName(true)]

  78:     public string ContextParameterName

  79:     {

  80:         get

  81:         {

  82:             return this._contextParameterName;

  83:         }

  84:         set

  85:         {

  86:             this._contextParameterName = value;

  87:         }

  88:     }

  89:  

  90:     [Description("Value to increment, it should be an integer"),

  91:     DisplayName("Increment Value")]

  92:     public Int32 IncrementValue

  93:     {

  94:         get

  95:         {

  96:             return this._incrementValue;

  97:         }

  98:         set

  99:         {

 100:             this._incrementValue = value;

 101:         }

 102:     }

 103:  

 104:     [DisplayName("Initial value"), Description("Initial Value")]

 105:     public Char InitialValue

 106:     {

 107:         get

 108:         {

 109:             return this._initialValue;

 110:         }

 111:         set

 112:         {

 113:             this._initialValue = value;

 114:         }

 115:     }

 116:  

 117:     [DisplayName("terminating value"), Description("terminating value")]

 118:     public Char TerminatingValue

 119:     {

 120:         get

 121:         {

 122:             return this._terminatingValue;

 123:         }

 124:         set

 125:         {

 126:             this._terminatingValue = value;

 127:         }

 128:     }

 129: }

This class is based on the classic for Loop with integer values, and it iterate simply from a starting char to an ending char. Now if you reference the project that contains this class into a test project, you can use this loop in your test.

SNAGHTML171375c

Figure 2: adding a custom rule for a loop in web test.

With this sample I want to iterate from the letter ‘a’ to letter ‘z’ incrementing each time by 2 chars, so I’ll have the sequence a,c,e,g,i…. Then I need to specify the Context parameter property, the property that will store the value of the sequence during each iteration, in Figure 3 you will see all the properties specified for our loop.

image

Figure 3: full configuration for the Loop iteration.

Now you can use that ContextParameter into a POST Variable

SNAGHTML173e8a1

Figure 4: Use the variable in loop to pass parameter with post.

If you run the test you can verify that it iterates in your sequence doing a series of requests, each one for each value of the loop.

SNAGHTML175a154

Figure 5: During test execution, for each iteration a different request was issued.

Thanks to this new feature of Visual Studio 2010 web test and very few lines of code, we are able to create, with little effort, an interesting test that can be used in load testing to simulate a series of search. In a subsequent post I’ll explain how to add another custom loop to select the detail page of each customer that satisfies the filter.

alk.

Tags: