Věděl jsem, že pro web testy/load testy webových aplikací ve Visual Studiu lze vytvářet vlastní extrakční a validační pravidla. Ale netušil jsem, že je to tak snadné. Stačí vytvořit obyčejnou knihovnu tříd, v ní odvodit třídu od příslušné abstraktní třídy (např. ValidationRule), implementovat metody RuleName, RuleDescription a Validate, a do projektu s testem přidat referenci na knihovnu tříd - to mne překvapilo, jak snadné je "nasazení", čekal jsem nějaké složité registrace. Výsledek dema, které kontroluje počet řádků v tabulce na XHTML stránce, je na následujícím obrázku a kód je pod ním:

 

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.VisualStudio.TestTools.WebTesting;
using System.ComponentModel;
using System.Xml;

namespace CustomWebTestRules
{
    public class TableRowCountValidationRule : ValidationRule
    {
        public override string RuleName
        {
            get { return "Table Row Count"; }
        }

        public override string RuleDescription
        {
            get { return "Verifies that given table has expected number of rows. Response must be valid XHTML."; }
        }

        private string tableID;

        [DisplayName("Table ID"),Description("HTML ID of the examined table.")]
        public string TableID
        {
            get { return tableID; }
            set { tableID = value; }
        }

        private int rowCount;

        [DisplayName("Row Count"), Description("Expected number of rows in the table.")]
        public int RowCount
        {
            get { return rowCount; }
            set { rowCount = value; }
        }

        public override void Validate(object sender, ValidationEventArgs e)
        {
            e.IsValid = false;
            XmlDocument doc = new XmlDocument();
            try
            {
                doc.LoadXml(e.Response.BodyString);
            }
            catch (XmlException)
            {
                e.Message = "Response is not a valid XHTML document.";
                return;
            }
            XmlNamespaceManager nsm = new XmlNamespaceManager(doc.NameTable);
            nsm.AddNamespace("xhtml", "http://www.w3.org/1999/xhtml");
            XmlNode table = doc.SelectSingleNode("//xhtml:table[@id='"+TableID+"']", nsm);
            if (table == null)
            {
                e.Message = String.Format("Table with id={0} not found.", TableID);
                return;
            }
            int rows = table.SelectNodes("./xhtml:tr", nsm).Count;
            if (rows == RowCount)
            {
                e.IsValid = true;
                e.Message = "Passed";
            }
            else
                e.Message = String.Format("Table id={0} rows: expected {1}, actual {2}", TableID, RowCount, rows);
        }
    }
}