Click here to Skip to main content
Licence CPOL
First Posted 2 Jul 2008
Views 10,111
Downloads 48
Bookmarked 10 times

Extracting Visual Studio Webtest result from TestResult(.trx)

By | 2 Jul 2008 | Article
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="<a href="http://doda.jp/">http://doda.jp/</a>" 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="<a href="http://doda.jp/index.html">http://doda.jp/index.html</a>" 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 : <a href="http://doda.jp/index.html">http://doda.jp/index.html</a>
    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", "<a href="http://microsoft.com/schemas/VisualStudio/TeamTest/2006">http://microsoft.com/schemas/VisualStudio/TeamTest/2006</a>");
            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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Masayuki Tanaka

Software Developer

Japan Japan

Member

I am Software Developer currently working at global IT consulting firm in Tokyo, Japan.
 
I have 9 years of experience in software development especially in Web Application.
 
I want to improve my English writing and speaking skill.
So,I am looking for English - Japanese language exchange partner in Tokyo area.
If you have some interest, Please email me<m-tanaka@pp.iij4u.or.jp>.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralCreating a Documentation Pinmembermuffelig1:57 3 Dec '08  
GeneralDisplaying the .trx file content in .Net web page PinmemberMember 18268830:15 12 Nov '08  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web02 | 2.5.120517.1 | Last Updated 2 Jul 2008
Article Copyright 2008 by Masayuki Tanaka
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid