Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Extracting Visual Studio Webtest result from TestResult(.trx)

0.00/5 (No votes)
2 Jul 2008 2  
Extracting Visual Studio Webtest result from TestResult(.trx)

Background

In Visual Studio Webtest, you can set Browser's User-Agent.
Use this function, you can test your website simulating various Browsers(IE, FireFox, Opera, Safari...).
But we can see results only in Visual Studio Test Results window which is using IE as rendering engine.

Viewing in other browser, you have to extract website response from TestResult file.

TestResult File Structure

Response information is stored in WebRequestResult element like this.

<WebRequestResult exceptionMessage="" run="0" submitted="true" cached="false" 
isRedirectFollow="false" requestBodyBytesHandle="-2" responseBytesHandle="0">
  <Request url="http://doda.jp/">http://doda.jp/" command="GET / HTTP/1.1" encoding="utf-8">
    <Headers>User-Agent : Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)
    Accept : */*
    Accept-Language : ja,en-us;q=0.5
    Accept-Encoding : GZIP
    Host : doda.jp
    Connection : Keep-Alive
    </Headers>
  </Request>
  <Response url="http://doda.jp/index.html">http://doda.jp/index.html" contentType="text/html; charset=Shift_JIS" 
  statusLine="HTTP/1.1 200 OK" pageTime="0.995" time="0.104" statusCodeString="200 OK" contentLength="45922">
    <Headers>Content-Location : http://doda.jp/index.html
    Vary : Accept-Encoding
    Accept-Ranges : bytes
    Content-Length : 45922
    Content-Type : text/html
    Date : Wed, 05 Dec 2007 15:27:03 GMT
    ETag : "092f3fd3b35c81:23fe"
    Last-Modified : Sun, 02 Dec 2007 23:35:16 GMT
    Set-Cookie : BIGipServerwww_80=220795052.20480.0000; path=/
    Server : Microsoft-IIS/6.0
    </Headers>
  </Response>

And Response Body is stored in Entry element like this.

<Entry handle="0" bytes="H4sIAAAAAAAEAO29B2AcSZYlJi9tyn

WebRequestResult references Entry by responseBytesHandle attribute and handle attribute.
And Entry element's bytes attribute is Compressed by GZip and then Encoded by Base64.

Overview

1.Extracting Response Body from TestResult.
2.Writing Response Body to files.
3.Rewrite link url.

Code

using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.IO.Compression;
using System.Xml;
namespace Rei
{
    public class Converter
    {
        private Encoding defaultEncoding = Encoding.GetEncoding("Shift-JIS");
        private Regex srcRegex = new Regex("src=\"(?<url>[^\"]+)\"", RegexOptions.Compiled | RegexOptions.IgnoreCase);
        private Regex hrefRegex = new Regex("href=\"(?<url>[^\"]+)\"", RegexOptions.Compiled | RegexOptions.IgnoreCase);
        public void Convert(string inputFileName,string outputDirName)
        {
            XmlDocument xmldoc = new XmlDocument();
            xmldoc.Load(inputFileName);
            XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmldoc.NameTable);
            nsmgr.AddNamespace("a", "http://microsoft.com/schemas/VisualStudio/TeamTest/2006">http://microsoft.com/schemas/VisualStudio/TeamTest/2006");
            List<WebRequestResult> reqResults = new List<WebRequestResult>();
            foreach (XmlNode node in xmldoc.SelectNodes("//a:WebRequestResult",nsmgr))
            {
                string responseHandle = node.Attributes["responseBytesHandle"].Value;
                XmlNode childNode = node.SelectSingleNode("a:Request",nsmgr);
                string url = childNode.Attributes["url"].Value;
                WebRequestResult reqresult = new WebRequestResult();
                reqresult.ResponseHandle = responseHandle;
                reqresult.Url = url;
                XmlNode responseNode = node.SelectSingleNode("a:Response", nsmgr);
                reqresult.ContentType = responseNode.Attributes["contentType"].Value;
                reqResults.Add(reqresult);
            }
            foreach (WebRequestResult reqresult in reqResults)
            {
                string handle = reqresult.ResponseHandle;
                XmlNode entryNode = xmldoc.SelectSingleNode("//a:Entry[@handle =\"" + handle + "\"]",nsmgr);
                if (entryNode != null)
                {
                    reqresult.EncodedResponse = entryNode.Attributes["bytes"].Value;
                }
            }
            foreach (WebRequestResult reqresult in reqResults)
            {
                string outFileName = outputDirName + "\\" + reqresult.fileName;
                using(FileStream fs = new FileStream(outFileName,FileMode.Create))
                {
                    if (!reqresult.ContentType.StartsWith("text"))
                    {
                        byte[] bytes = reqresult.Response;
                        fs.Write(bytes, 0, bytes.Length);
                        fs.Close();
                    }
                    else
                    {
                        Encoding enc = null;
                        if (reqresult.Charset != string.Empty)
                        {
                            enc = Encoding.GetEncoding(reqresult.Charset);
                        }
                        else
                        {
                            enc = defaultEncoding;
                        }
                        string body = enc.GetString(reqresult.Response, 0, reqresult.Response.Length);
                        Dictionary<string, string> urlMap = new Dictionary<string, string>();
                        MatchCollection srcMatches = srcRegex.Matches(body);
                        foreach (Match match in srcMatches)
                        {
                            string src = match.Groups["url"].Value;
                            if (!urlMap.ContainsKey(src))
                            {
                                for (int i = 0; i < reqResults.Count; i++)
                                {
                                    if (reqResults[i].Url.EndsWith(src))
                                    {
                                        urlMap.Add(src, reqResults[i].fileName);
                                        break;
                                    }
                                }
                            }
                            if (src.StartsWith("/") || src.StartsWith("."))
                            {
                                Uri uri = new Uri(new Uri(reqresult.Url), src);
                                if (!urlMap.ContainsKey(src))
                                {
                                    for (int i = 0; i < reqResults.Count; i++)
                                    {
                                        if (reqResults[i].Url.EndsWith(uri.AbsoluteUri))
                                        {
                                            urlMap.Add(src, reqResults[i].fileName);
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                        MatchCollection hrefMatches = hrefRegex.Matches(body);
                        foreach (Match match in hrefMatches)
                        {
                            string src = match.Groups["url"].Value;
                            if (!urlMap.ContainsKey(src))
                            {
                                for (int i = 0; i < reqResults.Count; i++)
                                {
                                    if (reqResults[i].Url.EndsWith(src))
                                    {
                                        urlMap.Add(src, reqResults[i].fileName);
                                        break;
                                    }
                                }
                            }
                            if (src.StartsWith("/") || src.StartsWith("."))
                            {
                                Uri uri = new Uri(new Uri(reqresult.Url), src);
                                if (!urlMap.ContainsKey(src))
                                {
                                    for (int i = 0; i < reqResults.Count; i++)
                                    {
                                        if (reqResults[i].Url.EndsWith(uri.AbsoluteUri))
                                        {
                                            urlMap.Add(src, reqResults[i].fileName);
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                        foreach (string beforeUrl in urlMap.Keys)
                        {
                            Regex regex1 = new Regex("src=\"" + beforeUrl + "\"", RegexOptions.IgnoreCase);
                            Regex regex2 = new Regex("href=\"" + beforeUrl + "\"", RegexOptions.IgnoreCase);
                            body = regex1.Replace(body, "src=\"" + urlMap[beforeUrl] + "\"");
                            body = regex2.Replace(body, "href=\"" + urlMap[beforeUrl] + "\"");
                        }
                        byte[] converted = enc.GetBytes(body);
                        fs.Write(converted, 0, converted.Length);
                        fs.Close();
                    }
                }
            }
        }
        
    }
    internal class WebRequestResult
    {
        private static Regex charsetRegex = new Regex(@"charset=(?<charsetName>.+)", RegexOptions.Compiled);
        public string Charset
        {
            get {
                MatchCollection matches = charsetRegex.Matches(this.contentType);
                if (matches.Count > 0)
                {
                    return matches[0].Groups["charsetName"].Value;
                }
                return string.Empty; 
                }
        }
        private string contentType;
        public string ContentType
        {
            get { return this.contentType; }
            set {this.contentType = value;}
        }
        private string url;
        public string Url
        {
            get { return this.url; }
            set { this.url = value; }
        }
        private string guid = Guid.NewGuid().ToString();
        public string fileName
        {
            get
            {
                string name = Url;
                name = name.Replace("//", "_");
                name = name.Replace('/', '_');
                name = name.Replace(':', '_');
                name = name.Replace('*', '_');
                name = name.Replace('"', '_');
                name = name.Replace('<', '_');
                name = name.Replace('>', '_');
                name = name.Replace('|', '_');
                name = name.Replace('?', '_');
                if (name.EndsWith("\\"))
                {
                    name = name.Substring(0, name.Length - 1);
                }
                if (name.Length > 100)
                {
                    return this.guid;
                }
                return name;
            }
        }
        private string responseHandle;
        public string ResponseHandle
        {
            get { return this.responseHandle; }
            set { this.responseHandle = value; }
        }
        private string encodedResponse;
        public string EncodedResponse
        {
            get { return this.encodedResponse; }
            set { this.encodedResponse = value; }
        }
        public byte[] Response
        {
            get {
                if (this.encodedResponse == null || this.encodedResponse == string.Empty)
                {
                    return new byte[0];
                }
                byte[] compressed = Convert.FromBase64String(this.encodedResponse);
                MemoryStream ms = new MemoryStream();
                ms.Write(compressed, 0, compressed.Length);
                ms.Position = 0;
                GZipStream gzipStream = new GZipStream(ms, CompressionMode.Decompress,true);
                MemoryStream msOut = new MemoryStream();
                int uncompressedByte = -1;
                while ((uncompressedByte = gzipStream.ReadByte()) != -1)
                {
                    msOut.WriteByte((byte)uncompressedByte);
                }
                return msOut.ToArray(); 
                }
        }
    }
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here