Search code examples
visual-studio-2013performance-testingload-testing

web performance test bind form post parameters array to a data source


In a web performance test I have a POST request which takes an array of users along with their details. No of users could be anything from 1 to 100+.

Through web test recorder I have captured a POST request containing 3 users.

POST Request

{{WebServer1}}/test/mypage/users
  |-  Form Post Parameters
      |-  Users[0].Id=90001
      |-  Users[0].FirstName=Rice
      |-  Users[0].LastName=Bran
      |-  Users[1].Id=90002
      |-  Users[1].FirstName=Samantha
      |-  Users[1].LastName=Rock
      |-  Users[1].Id=90003
      |-  Users[1].FirstName=Jenny
      |-  Users[1].LastName=Bryan

I need to send the request for 100s of users. One way would be to manually add the form post parameters in a request, but then future maintenance would be difficult.

I am thinking of using a data source like csv containing the user details and somehow bind them form post parameters.

CSV (testusers)

Id,FirstName,LastName
90001,Rice,Bran
90002,Samantha,Rock

I tried to bind them to form post params like below, but it doesn't work. [it only takes one data row]

form post params bind with csv data

{{WebServer1}}/test/mypage/users
  |-  Form Post Parameters
      |-  Users.Id=users.users#csv.Id
      |-  Users.FirstName=users.users#csv.FirstName
      |-  Users.LastName=users.users#csv.LastName

Does anyone know a proper way create a form post parameter array from a data source. Do I need to create coded web test or some plugin for this? (I am going to try that but simple binding would be great)


Edit: 10Sep2015

I couldn't find any solution. Ended up creating a coded web test which will add one request for each data row.

In the coded web test added this deployment item:

[DeploymentItem("Project\\Data\\users.csv")] 
public class HelloCodedWebtest : WebTest
{
    public HelloCodedWebtest()
    {       
        .....              
        .....

       // new Users().GetUsers() reads the csv and returns a list of user object, which i have stored in the context
       this.Context.Add("Users", new Users().GetUsers());           
    }

     public override IEnumerator<WebTestRequest> GetRequestEnumerator()
     {
        ......
        ......

        // Here for the request I have created the form post body from the list of users stored which was stored in the context.

        var myUsers = (List<User>) this.Context["Users"];

        foreach (var u in myUsers)
        {
            request2Body.FormPostParameters.Add("Users["+ myUsers.IndexOf(recipient) +"].Id", u.Id);
            request2Body.FormPostParameters.Add("Users["+ myUsers.IndexOf(recipient) +"].FirstName", u.FirstName);
            request2Body.FormPostParameters.Add("Users["+ myUsers.IndexOf(recipient) +"].LastName", u.LastName);
        }

        ....
     }
}

So far this is working just fine, but i would prefer a normal web test with some plugin over coded a web test.


Solution

  • Based on the updated question asking how to do the work with plugins, something based on the following should work. Note that the code has not been compiled or tested.

    In a PreWebTest plugin of the web test you can read the CSV just as done in the question. The plugin below will save the user data into the context.

    public class WriteTestStatus : WebTestPlugin
    {
        public virtual void PreWebTest(object sender, PreWebTestEventArgs e)
        {
            e.WebTest.Context.Add("Users", new Users().GetUsers());
        }
    }
    

    To make use of the data and build the correct form post parameters use thie following PreRequest plugin attached to the request.

    public class AddUserDetails : WebTestRequestPlugin
    {
        public override void PreRequest(object sender, PreRequestEventArgs e)
        {
            FormPostHttpBody formBody = e.Request.Body as FormPostHttpBody;
    
            if (formBody == null)
            {
                e.WebTest.AddCommentToResult("formBody is null");
                return;
            }
    
            var myUsers = (List<User>) e.WebTest.Context["Users"];
    
            foreach (var u in myUsers)
            {
                formBody.FormPostParameters.Add("Users["+ myUsers.IndexOf(recipient) +"].Id", u.Id);
                formBody.FormPostParameters.Add("Users["+ myUsers.IndexOf(recipient) +"].FirstName", u.FirstName);
                formBody.FormPostParameters.Add("Users["+ myUsers.IndexOf(recipient) +"].LastName", u.LastName);
            }
        }
    }
    

    The above uses two plugins to match the two methods shown in the question. If the user data from the CSV is only needed by the one request then saving into a context variable might be avoided and the new Users().GetUsers() placed in the assignment to var myUsers = ... in the PreRequest plugin.