An important part of loadtesting with Markov chains is choosing which transition the test should take. This boils down to generating a random number and then seeing in which of the transitions in the probability matrix that number belongs to.

The plugin code below generates a random number between your specified lower- and upper bound and places it into the specified context parameter. Its very similar to the out-of-the box plugin. However Visual Studio’s plugin can only be executed once when a webtest starts. I needed a new random number every time that my loops executes.

using System;
using System.ComponentModel;
using Microsoft.VisualStudio.TestTools.WebTesting;
using Microsoft.VisualStudio.TestTools.WebTesting.Rules;

namespace LoadTestPlugins
{

    [DisplayNameAttribute("Generate random number")]
    [DescriptionAttribute("Generates a random number during a request")]
    public class GenerateRandomNumber : WebTestRequestPlugin
    {

        #region Methods
        private void GenerateIt(WebTestContext Context)
        {
            Context[this.ContextParameterName] = new Random().Next(this.LowerBound, this.UpperBound);
        }

        public override void PostRequest(object sender, PostRequestEventArgs e)
        {
            if(this.BeforeRequest == false)
            {
                this.GenerateIt(e.WebTest.Context);
            }
        }
        
        public override void PreRequest(object sender, PreRequestEventArgs e)
        {
            if(this.BeforeRequest == true)
            {
                this.GenerateIt(e.WebTest.Context);
            }
        }
        #endregion

        #region Properties
        [Description("Name of context parameter to store the number in"),
        DisplayName("Context parameter"), IsContextParameterName(true)]
        public string ContextParameterName {get; set;}

        [Description("The lower bound"),
        DisplayName("Lower bound"),
        DefaultValue(1)]
        public Int32 LowerBound { get; set; }


        [Description("The upper (inclusive) bound"),
        DisplayName("Upper bound"),
        DefaultValue(100)]
        public Int32 UpperBound { get; set; }

        [Description("Whether to generate the number before or after the request has executed"),
        DisplayName("Apply before request"),
        DefaultValue(true)]
        public bool BeforeRequest { get; set; }
        #endregion
    }
}