Creating an Extraction Rule for VSTS 2008 Web Tests

Extraction rules are essentially for finding data in the HTTP response and placing it in the output context of the web test. There are a few built-in tests, but they mostly focus on the HTML tags themselves and the attributes. In my case I really needed the data between span tags. I think this could probably be done with the existing rules and some regular expressions, but I couldn’t resist the chance to write some code and learn something new.

All you need to do is place the class file in the Test Project and compile it. The rule automatically becomes available to the tests in the project.  Here is my class that finds a span for a given ClientId. It overrides the Execute method of the ExtractionRule base class and attempts to find a span for the given ID. If the span is found, it parses the HTML string to find the content of the span tag.

namespace WebTestDemo

{

    [System.ComponentModel.DisplayName(“Span Extractor”)]

    public class ExtractSpan : ExtractionRule

    {

        // The name of the desired input field

        private string nameValue;

        public string ClientId

        {

            get { return nameValue; }

            set { nameValue = value; }

        }

 

        public override void Extract(object sender, ExtractionEventArgs e)

        {

            string[] tagTypeFilter = new string[] { “span” };

 

            //Fail the test if nothing is found (this may need to be modified)

            e.Success = false;

 

            if (e.Response.HtmlDocument != null && e.Response.IsHtml)

            {

                try

                {

                    //Find the span tag based on ID. Exception if none found

                    HtmlTag result = e.Response.HtmlDocument.GetFilteredHtmlTags(tagTypeFilter).First(t => string.Equals(t.GetAttributeValueAsString(“ID”), this.nameValue, StringComparison.OrdinalIgnoreCase));

 

                    //The span was found (no exception), now find the data

 

                    //Get the location of the ID in the span tag

                    int startPosition = e.Response.BodyString.IndexOf(this.nameValue);

 

                    //Find the position of the data immediately following the closing angle bracket of the span,

                    //  accounting for the > character as well

                    startPosition = e.Response.BodyString.IndexOf(“>”, startPosition) + 1;

 

                    //Get the position of the closing tag for the span

                    int endPosition = e.Response.BodyString.IndexOf(“</span>”, startPosition);

 

                    //Fetch the content

                    string content = e.Response.BodyString.Substring(startPosition, endPosition – startPosition);

 

                    //Add the value to the context output. This could just as easily go to a file or a DB

                    // this step is not necessary for the extraction to succeed

                    e.WebTest.Context.Add(this.ContextParameterName, content);

 

                    //Mark the extraction as successful

                    e.Success = true;

                }

                catch (Exception)

                {

                    e.Success = false;

                    e.WebTest.Context.Add(this.ContextParameterName, string.Format(“span tag id={0} not found”, this.nameValue));

                }

            }

        }

    }

}

Now that I have the class, I need to wire it up to a URL in a web test. Right-click the URL and choose Add Extraction Rule…

AddRuleToTest[1]

I need to set two properties:

  1. Context Parameter Name. This comes from the base ExtractionRule class, and is the name for the data that ends up in the output.
  2. ClientId. This is a custom property from my class. It is the ClientId of the rendered control in the HTML output. The class finds the span with this name and returns the data.

Now when I run the test, if the ClientId I specified was found, it shows up in the Context output after running the test. The Context Parameter Name was “SpanData” in this case:

ExtractionRuleResults[1]

This could be made more robust by not coding specifically for spans. Certainly there could be issues if the tag ID is used more than once or if there is significant nesting of spans within the tag you are trying to find. This code is intended to prove out the concept, it could certainly be made stronger.

One thing I want to mention is that all the code samples I have run across (MSDN included) show the RuleName property as the way to display the extraction rule name in the Visual Studio UI. But under compilation this property comes up as obsolete. I found the answer on Ed Glas’s blog. The obsolete message mentioned using attributes, but this info was not discoverable, so I was quite grateful for that posting to get the syntax correct.

Helpful Links

Must Read VSTS – Testing Related Blogs and Introductory Articles

How to: Create a Custom Extraction Rule

Custom Extraction Rule and Generating a Code Test from VSTS