Dial your load - custom load patterns in VSTS Load Tests

We often are asked about our support for different load patterns in a load test.

What's a load pattern? A load pattern controls the number of users that the load test is simulating at a given period of time in the load test.

We ship with three load patterns: constant, step, and goal-based. But we also provide a key extensibility point in our load test plugin that enables you to pretty easily build any pattern you want. It even enables you to "dial" the load up or down in real time while the test is running.

Here's a simple plugin that billbar wrote that ramps load up and then back down:

 using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Microsoft.VisualStudio.TestTools.LoadTesting;

namespace TestProject1
{
    /*
      This class is a sample LoadTest Plug-in class that ensures implements a custom load profile.
      Specifically, in this example the user load steps up from 1 to 50 users by increasing the load
      by one user every 30 seconds, and then decreases the user load by 1 user every 30 seconds until
      the user load reaches 0.

      To use this class:

      1. Add the class to a test project.
      2. [Optional] If you want a different load pattern than the one described above, change the
         implementation of the method GetLoadForElapsedTime().
      3. Build the test project.
      4. Hook this load test plugin up to your load test: in the load test editor, select the top-most node 
         in the load test tree (the load test name in the tree), and go to the property sheet.  
         Click on the ... icon by the value for "Load Test Plug-in" and you should be able to select the 
         CustomLoadProfileLoadTestPlugin class as your plugin.
     */


    public class CustomLoadProfileLoadTestPlugin : ILoadTestPlugin
    {
        #region ILoadTestPlugin Members

        // The initialize method is called just before the load test starts running
        public void Initialize(LoadTest loadTest)
        {
            m_loadTest = loadTest;

            // Register to listen for the heartbeat event
             loadTest.Heartbeat += new EventHandler<HeartbeatEventArgs>(loadTest_Heartbeat);
        }

        // This method returns the user load as a function of the number of elapsed seconds
        // into the load test.    In this example, the user load starts at 1, increases by 1
        // every 30 seconds to a max of 50, and then decreases by 1 every 30 seconds until the
        // user load goes to 0.   The load test that uses this example should be set to have a during
        // of at least 50 minutes to go through the entire cycle.
        private int GetLoadForElapsedTime(int elapsedSeconds)
        {
            if (elapsedSeconds < 30 * 50)
            {
                return (elapsedSeconds / 30) + 1;
            }
            else
            {
                return Math.Max(0, 50 - ((elapsedSeconds - (30 * 50)) / 30));
            }
        }

        // This method changes the current user load for the 1st Scenario in the load test
        // This example assumes there is only one scenario in the load test
        void SetLoad(int newLoad)
        {
            ((LoadTestScenario)m_loadTest.Scenarios[0]).CurrentLoad = newLoad;
        }

        // HeartBeat event handler - this gets calls once every second during the load test
        // including during the warmup period
        void loadTest_Heartbeat(object sender, HeartbeatEventArgs e)
        {
            if (e.IsWarmupComplete)
            {
                SetLoad(GetLoadForElapsedTime(e.ElapsedSeconds));
            }
        }

        LoadTest m_loadTest;

        #endregion
    }
}

Here's the load test plugin I wrote that reads the current load from a file. Then I used notepad to "dial" the load up and down (I also wrote a simple winforms app that allows you to spin the load up and down, but I'll leave that as an exercise to the reader :)):

 using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Microsoft.VisualStudio.TestTools.LoadTesting;

namespace Plugins
{
    /*
        This class is a sample load test plugin that allows you
        to dynamically change the load while the test is running.
        Notice the m_loadFilePath, which is the file that load 
        will be read from.
        This sample assumes there is a single load scenario. It
        would be fairly easy to extend this to multiple scenarios.
     */
    public class LoadDialLoadTestPlugin : ILoadTestPlugin
    {
        #region ILoadTestPlugin Members

        public void Initialize(LoadTest loadTest)
        {
            m_loadTest = loadTest;
            if (File.Exists(m_loadFilePath))
            {
                loadTest.Heartbeat += new EventHandler<HeartbeatEventArgs>(loadTest_Heartbeat); 
                m_loadFileTime = File.GetLastWriteTime(m_loadFilePath);
                SetLoad();
            }
        }

        void SetLoad()
        {
            // Read the load and set it on the first scenario
            StreamReader loadFileStream = File.OpenText(m_loadFilePath);
            string load = loadFileStream.ReadLine();
            ((LoadTestScenario)m_loadTest.Scenarios[0]).CurrentLoad = Int16.Parse(load);
            loadFileStream.Close();
        }

        void loadTest_Heartbeat(object sender, HeartbeatEventArgs e)
        {
            // If running on a rig, we only want to set the load from one agent
            if (m_loadTest.Context.AgentId != 1)
            {
                return;
            }

            // If the file has been modified, read the new load
            DateTime loadFileTime = File.GetLastWriteTime(m_loadFilePath);
            if (loadFileTime > m_loadFileTime)
            {
                SetLoad();
            }
        }

        LoadTest m_loadTest;
        DateTime m_loadFileTime;
        string m_loadFilePath = "c:\\public\\load.txt";

        #endregion
    }
}

You can see how super-easy it is to add your own custom load patterns using the load test plugin.

Ed.