Write a simple asp.net web page test framework less than 150 lines of code
2011-06-14 10:26
507 查看
Talking About Test
I hate the unit test to some extent, since I think unit test is a kind of duplication. We all know “Don’t Repeat Yourself”, but test definitely duplicated with production code. Think about that you are compelled to change test when if you change the production code.After some practice of writing test, I found the productivity improvement can persuade me to writing test in a project. As a programmer we spent a lot of time to debug when develop a application. We should cut down the debug time if we want to improve the productivity during development. Writing test a good way that can save the time in debug. We are talking about debug in here is not just finding a bug in our code, but verifying the result when implemented a function of application. We stop coding and check out our code whether working as we expected it does. This is a time killer, this is why I decide to writing test at last.
Testing a ASP.NET web page Automatically
1, ScenarioI have a asp.net web page. In that page, there is a link button and submit button on the page. as following:
If we click the New Account link, I will be redirect to the page that allowing user creating new a account. meanwhile, I be redirect the category list page if I fill out Category ID and click the Query Category button.The code of this page are following:
protected void lnk_Click(object sender, EventArgs e) { this.Response.Redirect("NewAccount.aspx"); } protected void btnQueryCategory_Click(object sender, EventArgs e) { if (txtCategoryID.Text.Trim() != string.Empty) { this.Response.Redirect(string.Format("Categories.aspx?ID={0}", this.txtCategoryID.Text)); } }
2, How our test looks like
[TestClass] public class UnitTest1 { [TestMethod] public void CanOpenIndexPage() { AspNetTestBrowser browser = new AspNetTestBrowser(); browser.Open("http://localhost:50002/Index.aspx"); Assert.IsTrue(browser.PageHtml.Contains("Index")); } [TestMethod] public void CanRedirectNewAccountPage() { AspNetTestBrowser browser = new AspNetTestBrowser(); browser.Open("http://localhost:50002/Index.aspx"); Dictionary<string, string> parms = new Dictionary<string, string>(); parms.Add(AspHiddenField.EVENTTARGET, "lnkNewAccount"); parms.Add(AspHiddenField.EVENTARGUMENT, string.Empty); browser.Postback(parms); Assert.IsTrue(browser.PageHtml.Contains("Create New Account")); } [TestMethod] public void CanRedirectCategoryPage() { AspNetTestBrowser browser = new AspNetTestBrowser(); browser.Open("http://localhost:50002/Index.aspx"); Dictionary<string, string> parms = new Dictionary<string, string>(); parms.Add("txtCategoryID", "5"); parms.Add("btnQueryCategory", "Query Category"); browser.Postback(parms); Debug.WriteLine(browser.PageHtml); Assert.IsTrue(browser.PageHtml.Contains("Categories")); } }
The things you should to know is which element will be post to server when we click the button, you can refer to my previous blog. Another trick is using firebug(a plugin for firefox browser). as following:
3,less than 150 lines of code to help our test
The things our test framework does:extract the hidden field by asp.net.
post the web page by WebClient class(built in .net framework)
Here is the code:
namespace aspnet_test_lib { public class AspHiddenField { public const string VIEWSTATE = "__VIEWSTATE"; public const string EVENTVALIDATION = "__EVENTVALIDATION"; public const string EVENTTARGET = "__EVENTTARGET"; public const string EVENTARGUMENT = "__EVENTARGUMENT"; } public static class WebClientEx { public static string HttpPost(this WebClient webClient, string URI, string Parameters) { WebRequest req = System.Net.WebRequest.Create(URI); //Add these, as we're doing a POST req.ContentType = "application/x-www-form-urlencoded"; req.Method = "POST"; //We need to count how many bytes we're sending. Post'ed Faked Forms should be name=value& byte[] bytes = System.Text.Encoding.ASCII.GetBytes(Parameters); req.ContentLength = bytes.Length; System.IO.Stream os = req.GetRequestStream(); os.Write(bytes, 0, bytes.Length); //Push it out there os.Close(); System.Net.WebResponse resp = req.GetResponse(); if (resp == null) return null; System.IO.StreamReader sr = new System.IO.StreamReader(resp.GetResponseStream()); return sr.ReadToEnd().Trim(); } } public class AspNetTestBrowser { private WebClient _webClient = new WebClient(); public WebClient WebClient { get { return _webClient; } } private string _pageHtml = string.Empty; public string PageHtml { get { return _pageHtml; } private set { _pageHtml = value; } } private string _urlLocation = string.Empty; public string UrlLocation { get { return _urlLocation; } private set { _urlLocation = value; } } public string Open(string address) { this.UrlLocation = address; PageHtml = WebClient.DownloadString(address); return PageHtml; } public string Postback(string address, IDictionary<string, string> parms) { parms.Add(AspHiddenField.VIEWSTATE, GetAspHiddenField(this.PageHtml, AspHiddenField.VIEWSTATE)); string eventValidation = GetAspHiddenField(this.PageHtml, AspHiddenField.EVENTVALIDATION); if (eventValidation != null) { parms.Add(AspHiddenField.EVENTVALIDATION, GetAspHiddenField(this.PageHtml, AspHiddenField.EVENTVALIDATION)); } string urlParameters = string.Empty; foreach (var parm in parms) { if (!string.IsNullOrEmpty(parm.Value)) { urlParameters += string.Format("{0}={1}", parm.Key, parm.Value); urlParameters += "&"; } } if (urlParameters.EndsWith("&")) { urlParameters = urlParameters.Remove(urlParameters.Length - 1, 1); } this.PageHtml = this.WebClient.HttpPost(address, urlParameters); return this.PageHtml; } public string Postback(string address, string parms) { this.PageHtml = this.WebClient.HttpPost(address, parms); return this.PageHtml; } public string Postback(IDictionary<string, string> parms) { return this.Postback(this.UrlLocation, parms); } private string GetAspHiddenField(string pageHtml, string hiddenField) { string pattern = string.Format("<input type=\"hidden\" name=\"{0}\" id=\"{0}\" value=\"(?<view>.*)\" />", hiddenField); Regex regex = new Regex(pattern); var match = regex.Match(pageHtml); if (match.Groups["view"].Success) { return match.Groups["view"].Value; } else { return null; } } } }
Enjoy!
相关文章推荐
- A simple Test Client built on top of ASP.NET Web API Help Page
- Adding the Test API in The ASP.NET Web API Help Page
- What events are fired as part of the ASP.NET System.Web.UI.Page lifecycle?
- Life Cycle Stages of ASP.NET Web Page.
- How to add a Login, Roles and Profile system to an ASP.NET 2.0 app in only 24 lines of code
- Embed client-side JavaScript in an ASP.NET 1.1 web page from server side code
- Code snippet of the day : persist the scroll position of an ASP.NET page
- ASP.NET Web Page Code Model
- Adding the Test API in The ASP.NET Web API Help Page
- ASP.NET App_Code中的类文件如何继承System.Web.UI.Page
- ASP.Net Web Page深入探讨
- ASP.NET(C#)——不扩展System.Web.UI.Page
- 开发ASP.NET 2.0 Web应用程序时如何将App_Code文件夹中的共享代码配置生成多个Dll
- Debugging ASP.NET 5 framework code using Visual Studio 2015
- ASP.Net Web Page深入探讨
- Asp.net Mvc 未能加载类型“System.Web.Mvc.ViewPage<IEnumerable...的解決方法
- ASP.NET 2.0的Web Part Framework(新书连载)
- Lightweight UI Test Automation for ASP.NET Web Apps
- ASP.NET 2.0的Web Part Framework(新书连载)
- ASP.NET Web Page应用深入探讨