65.9K
CodeProject 正在变化。 阅读更多。
Home

从 TestResult(.trx) 文件中提取 Visual Studio Webtest 结果

starIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

1.00/5 (1投票)

2008年7月2日

CPOL
viewsIcon

58294

downloadIcon

130

从 TestResult(.trx) 文件中提取 Visual Studio Webtest 结果

背景

在 Visual Studio Webtest 中,您可以设置浏览器的 User-Agent。
使用此功能,您可以模拟各种浏览器(IE、FireFox、Opera、Safari...)来测试您的网站。
但是,我们只能在 Visual Studio 测试结果窗口中查看结果,该窗口使用 IE 作为渲染引擎。

要在其他浏览器中查看,您需要从 TestResult 文件中提取网站响应。

TestResult 文件结构

响应信息存储在 WebRequestResult 元素中,如下所示。

<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>

响应主体存储在 Entry 元素中,如下所示。

<Entry handle="0" bytes="H4sIAAAAAAAEAO29B2AcSZYlJi9tyn

WebRequestResult 通过 responseBytesHandle 属性和 handle 属性引用 Entry。
Entry 元素的 bytes 属性经过 GZip 压缩,然后通过 Base64 编码。

概述

1. 从 TestResult 文件中提取响应主体。
2. 将响应主体写入文件。
3. 重写链接 URL。

代码

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(); 
                }
        }
    }
}
© . All rights reserved.