Debugging errors in Load Test

One of the common questions I get is similar to this: “My web test runs fine when it is run by itself, but starts failing when run in a load test. What is wrong with my web test?” First, if your test runs successfully when it runs standalone then more then likely, your test is fine. You have probably found a problem with the application that you are testing when the application is run under load. The next step is trying to figure out what is going wrong with your app.

 

This post will describe a technique for diagnosing a certain type of error. One common error that I see when running a test under load is the following. A web test will fail and the error is: “Context parameter '$HIDDEN1.__VIEWSTATE' not found in test context”. This error occurs because a request has a form parameter called __VIEWSTATE which is bound to the {{$HIDDEN1.__VIEWSTATE}} context parameter. For some reason the $HIDDEN1.__VIEWSTATE parameter was not added to the test context during hidden field binding.

 

Let me give a quick description of hidden field binding. While you are recording your web test, we will attempt to determine if any form post parameter being submitted is from a hidden field. If it is, then we will automatically correlate the parameter for you. By correlate, I mean that an extraction rule will be added to the request that has the value for the hidden field and then the form post parameter will be bound to the value from the extraction rule. Here is an example of what this looks like.

 

  __VIEWSTATE is a hidden field which is present in most ASP.net applications. Say our web test has 2 requests. Request 2 has a form parameter call __VIEWSTATE. We will look through each of the previous requests for a hidden field called __VIEWSTATE. If we find one and the one we found has the same value as the one on request 2, then we will perform the correlation.

 

This works well most of the time. The way the Extract Hidden Fields extraction rule works in VS 2005 is that it will extract all hidden fields from a response and add them to the test context. If none are found, then the rule does nothing. It would be better if the rule actually failed if it did not find any hidden fields to extract. In fact we changed the behavior for VS 2008 to do just this. This rule is only added if at record time we detect it is needed. So at run time, if it does not find any hidden fields, then that is an error. The other reason it would be better if this request fails is that the next request which is relying on the hidden fields to be in the context will always fail if the values are not in the context. And the error that you will receive is “Context parameter '$HIDDEN1.__VIEWSTATE' not found in test context”. This error is valid because the value does not exist in the test context, but this request is not really the problem. The previous request which did not extract any hidden fields is the problem.

 

Now let’s get back to how this applies to the load test. When a request fails in a load test, you will be able to view the request and response details of the failed request. But again, in this case, you really want to see the request and response of the previous request because that is the one that is behaving differently then when the test is run standalone. But since that request is not failing, you can not see the details for that request. Here is an example. I created a simple web test against a sample shopping site. The test runs successfully by itself, but when run within a load test I get the errors listed below.

 

 

When I drill into the error, you can see the “Request failed: Context parameter '$HIDDEN1.__VIEWSTATE' not found in test context” error message.

 

 

To really figure out what is going on I need to see the previous request/response. To see that request/response we need that request to fail. From our error message we see that we expected the previous request to have a hidden field called __VIEWSTATE. So one thing we can do is create a simple validation rule which takes a field name as a parameter and validates the field exists in the response. Here is the code for that rule:

 

using System;

using System.Collections;

using System.Globalization;

namespace RuleExamples

{

   

    public class ValidateFormFieldExists : ValidationRule

    {

        private string m_name;

       

        public string Name

        {

            get { return m_name; }

            set { m_name = value; }

        }

        public override void Validate(object sender, ValidationEventArgs e)

        {

            if (DoesFormFieldExist(e.Response, m_name))

            {

                e.IsValid = true;

            }

            else

            {

                //this resource does not mention extraction in the text, so it's fine to use here, too

                e.Message = String.Format("Did not find form Field with name {0}", Name);

                e.IsValid = false;

            }

        }

        internal static bool DoesFormFieldExist(WebTestResponse response, string formFieldName)

        {

            foreach (HtmlTag tag in response.HtmlDocument.GetFilteredHtmlTags("input"))

            {

                if (String.Equals(tag.GetAttributeValueAsString("name"), formFieldName, StringComparison.OrdinalIgnoreCase)

                        || String.Equals(tag.GetAttributeValueAsString("id"), formFieldName, StringComparison.OrdinalIgnoreCase))

                {

                    return true;

                }

            }

            return false;

        }

    }

}

 

To add this as a rule to your project do the following:

1) Add a class to your test project

2) Paste this code in the class

3) Compile

 

Now it is ready for use. Next we need to go to the web test and add the rule to the request which is supposed to be extracting the hidden fields. Typically it is the preceding request, but not always. Add this new validation rule to this request and set the field to look for to __VIEWSTATE. Also set the validation level to Low. By default, load tests will only run validation rules with level set to low. Here is what that looks like.

 

 

Then run your test again. As you can see from my errors below, I received the error again.

 

 

I also received a validation rule error for the missing field. So this time I can drill into that failure and see the request and response. Here is what that looks like.

 

 

As you can see, I am receiving a database deadlock problem. This is a much more informative error and definitely points to a problem that occurs because my app is being run under load. For this particular error, I now know I need to add extra logging to my database to figure out what is happening.

 

So to review the steps to getting more information into the problem are:

 

1) Create the validation rule listed above

2) Add the validation rule the request that is supposed to be extracting the hidden fields.

3) Run your test and hopefully the error will occur again.

 

 

Also to recap, if you are running VS2008, there are a few differences. First, as I mentioned above the Extract Hidden Fields rule will now fail if it finds no fields to extract. So you may not need to add the new validation rule. There is another option in VS2008 that you might find useful. You can have a web test stop when it hits an error. This property is on the root node of the web test. The reason this is useful, is that it will cut down on errors in the load test and let you focus errors that appear. If you look at the screen shot of the errors after I applied the rule, you will see that there are still errors for not finding the parameter in the context. If I had set the Stop on Error Property to true, then I would not have seen these errors. I would have just seen the validation rule errors and would focus just on those problems.