September 2006 Entries
Custom extraction rules for Web Tests

To help test MiVoice I've put together a Web Test that votes continously for a random candidate. I tried using the Form Field Extraction rule to select a candidate from the options returned (as a radio button list), but it wasn't up to the job (didn't seem to know what a radio button list was and couldn't randomly select a value). After nosing around in the documentation you can convert a bog standard web test into a coded web test and then from there hook in custom extraction rules. Our custom rule looks like :

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.VisualStudio.TestTools.WebTesting;
using System.Text.RegularExpressions;
namespace MiVoiceLoadTest
{
    public class GetCandidateOidExtractionRule : ExtractionRule
    {
        private string mFieldName = string.Empty;
        private static Random sRandom = new Random();
        public override string RuleName
        {
            get { return "GetCandidateOidExtractionRule"; }
        }
        public string FieldName
        {
            get { return mFieldName; }
            set { mFieldName = value; }
        }
        public override void Extract(object sender, ExtractionEventArgs e)
        {
            List candidateOids = new List();
            string regexString = "type=\"radio\" name=\"" + FieldName.Replace("$", "\\$") + "\" value=\"([a-z0-9\\-]{36})\"";
            Regex r = new Regex(regexString);
            MatchCollection mc = r.Matches(e.Response.BodyString);
            foreach (Match m in mc)
            {
                string v = m.Groups[1].Value;
                if (!string.IsNullOrEmpty(v))
                {
                    candidateOids.Add(v);
                }
            }
            int i = sRandom.Next(candidateOids.Count);
            string oid = candidateOids[i];
            e.WebTest.Context.Add("CandidateOid", oid);
            e.Success = true;
            e.Message = "Passed";
        }
    }
}

Notice the e.WebTest.Context.Add("CandidateOid"), this puts the value we selected into the context for the next request to use. This rule is then hooked into the request that's going to return the radio button list as

GetCandidateOidExtractionRule candidates = new GetCandidateOidExtractionRule();
candidates.FieldName = "ctl00$pageContent$vpVote$wizVotingProcess$rblCandidates";
candidates.ContextParameterName = "1"; // ! THIS BIT IS VITAL, NULLRFERENCEEXCEPTION OTHERWISE
request2.ExtractValues += new EventHandler(candidates.Extract);

Then the value we've set into the context is consumed in a subsequent request thus

request3Body.FormPostParameters.Add("ctl00$pageContent$vpVote$wizVotingProcess$rblCandidates", this.Context["CandidateOid"].ToString());

Worked out very nicely.