2014-09-28html
測試自動化程序的任務
待測程序
測試程序
啓動IE並鏈接到這個實例
如何判斷待測web程序徹底加載到瀏覽器
操縱並檢查IE Shell
操做待測Web頁面上的HTML元素的值
驗證Web頁面上HTML元素
示例代碼ios
底層技術的核心是,經過直接調用mshtml.dll和shdocvw.dll庫來訪問而且操縱IE客戶區域的HTML對象。web
新建一個網站「WebAUT」,刪除原來的Default.aspx,建立一個新的Default.aspx。在其中添加3個Label控件、2個RadioButton控件、1個TextBox控件、1個Button控件和1個ListBox控件。瀏覽器
圖1 Web UATapp
待測程序代碼:ide
1 using System; 2 using System.Collections.Generic; 3 4 using System.Web; 5 using System.Web.UI; 6 using System.Web.UI.WebControls; 7 8 public partial class _Default : System.Web.UI.Page 9 { 10 private System.Collections.ArrayList al = new System.Collections.ArrayList(); 11 protected void Page_Load(object sender, EventArgs e) 12 { 13 Product p1 = new Product("widgets", "1A11A", 11.11); 14 Product p2 = new Product("gadgets", "2B22B", 22.22); 15 Product p3 = new Product("foozles", "3C33C", 33.33); 16 17 al.Add(p1); 18 al.Add(p2); 19 al.Add(p3); 20 Label3.Text = "Search Complete"; 21 Label3.Visible = false; 22 } 23 protected void Button1_Click(object sender, EventArgs e) 24 { 25 ListBox1.Items.Clear(); 26 string filter = TextBox1.Text; 27 ListBox1.Items.Add("ProdName ProdID Price"); 28 ListBox1.Items.Add("====================="); 29 30 if (RadioButtonList1_1.Checked) 31 { 32 foreach (Product p in al) 33 { 34 if (p.name.IndexOf(filter) >= 0) 35 ListBox1.Items.Add(p.name + ", " + p.id + ", " + p.price); 36 } 37 } 38 else if (RadioButtonList1_2.Checked) 39 { 40 foreach (Product p in al) 41 { 42 if (p.id.IndexOf(filter) >= 0) 43 ListBox1.Items.Add(p.name + ", " + p.id + ", " + p.price); 44 } 45 } 46 Label3.Visible = true; 47 } 48 49 public class Product 50 { 51 public string name; 52 public string id; 53 public double price; 54 public Product(string name, string id, double price) 55 { 56 this.name = name; 57 this.id = id; 58 this.price = price; 59 } 60 } 61 }
1 static void Main(string[] args) 2 { 3 //... 4 5 SHDocVw.InternetExplorer ie = null; 6 Console.WriteLine("\nLaunching an instance of IE"); 7 Process p = Process.Start("iexplore.exe", "about:blank"); 8 System.Threading.Thread.Sleep(2000); 9 if (p == null) 10 throw new Exception("Could not launch IE"); 11 Console.WriteLine("Process handle = " + p.MainWindowHandle.ToString()); 12 13 SHDocVw.ShellWindows allBrowsers = new SHDocVw.ShellWindows(); 14 Console.WriteLine("Number active browsers = " + allBrowsers.Count); 15 16 if (allBrowsers.Count == 0) 17 throw new Exception("Cannot find IE"); 18 19 Console.WriteLine("Attaching to IE"); 20 int i = 0; 21 22 while (i < allBrowsers.Count && ie == null) 23 { 24 InternetExplorer e = (InternetExplorer)allBrowsers.Item(i); 25 if (e != null) 26 { 27 if (e.HWND == (int)p.MainWindowHandle) 28 ie = e; 29 } 30 ++i; 31 } 32 33 if (ie == null) 34 throw new Exception("Failed to attach to IE"); 35 36 //... 37 }
1 static void Main(string[] args) 2 { 3 SHDocVw.InternetExplorer ie = null; 4 //把ie對象鏈接到IE程序所在的進行 5 6 ie.DocumentComplete += new DWebBrowserEvents2_DocumentCompleteEventHandler(ie_DocumentComplete); 7 8 Console.WriteLine("\nNavigating to the Web app"); 9 object nil = new object(); 10 ie.Navigate("http://localhost:30614/WebAUT/Default.aspx", ref nil, ref nil, ref nil, ref nil); 11 12 documentComplete.WaitOne(); 13 14 //... 15 } 16 private static void ie_DocumentComplete(object pDisp, ref object URL) 17 { 18 documentComplete.Set(); 19 }
測試程序有可能在待測程序還沒有徹底加載的狀況下試圖對其進行操做,這麼作,極可能引起異常。測試程序可經過事件DocumentComplete和AutoResetEvent類,對自動化程序進行同步。測試
AutoResetEvent類還有帶參數的WaitOne()方法,用於指定最大等待時間,超過就再也不等待:網站
//9000毫秒,true標識能夠再等待結束以前推出同步域 documentComplete.WaitOne(9000,true)
1 static void Main(string[] args) 2 { 3 SHDocVw.InternetExplorer ie = null; 4 //把ie對象鏈接到IE程序所在的進行 5 6 Console.WriteLine("Setting IE to size 450x360"); 7 ie.Width = 450; 8 ie.Height = 360; 9 Thread.Sleep(1000); 10 11 if (ie.StatusText.IndexOf("Done") == -1) 12 Console.WriteLine("could not find 'Done' in status bar"); 13 else 14 Console.WriteLine("Find 'Done' in status bar"); 15 //... 16 }
當編寫針對Web UI的自動化測試程序師,須要把IE的3個區域考慮在內:ui
SHDocVw.InternetExplorer對象提供了一些屬性和方法用於操縱(可用來模擬用戶操做)和檢查Shell(可用來判斷某個測試場景經過與否)。下面是幾種屬性和方法:this
示例代碼:
using mshtml; // .NET component = Microsoft.mshtml. HTML interfaces static void Main(string[] args) { //... HTMLDocument theDoc = (HTMLDocument)ie.Document; Console.WriteLine("\nSelecting 'ID' radio button"); HTMLInputElement radioButton = (HTMLInputElement)theDoc.getElementById("RadioButtonList1_2"); radioButton.@checked = true; Console.WriteLine("Setting text box to '2B'"); HTMLInputElement textBox = (HTMLInputElement)theDoc.getElementById("TextBox1"); textBox.value = "2B"; Console.WriteLine("Clicking search button"); HTMLInputElement butt = (HTMLInputElement)theDoc.getElementById("Button1"); butt.click(); documentComplete.WaitOne(); //... }
在上述代碼中,要模擬用戶選中radio button控件,必須使用@checked,由於checked是C#語言的一個關鍵字。
在上述代碼中,按鈕控件和文本控件的類型都是HTMLInputElement,而下拉空間的類型則是HTMLSelectElement。可經過下面代碼知道到底該用哪一個類:
HTMLInputElement textBox = (HTMLInputElement)theDoc.getElementById("TextBox1"); Console.WriteLine("The textbox has type" + textBox.GetType().ToString());
注意:由於咱們是經過getElementById()方法得到HTML元素/控件的引用的,因此這個控件必需要有ID attribute,從而能夠惟一的表示這個控件。若Web頁面是由Visual Studio .NET UI設計器建立的,那麼全部控件都有一個ID attribute。可是若是Web程序是手工建立(好比經過Notepad),那麼最好修改這個程序,給他們加上一個ID attribute。
經過mshtml.dll庫裏的getElementByTagName()方法和item()方法獲得你想要的特定的元素。而後能夠經過InnerText屬性取回HTML元素的實際值。
設想某個待測頁面含有幾個<P>元素,和一個ID爲「div2」的<div>元素。下面的代碼在<p>元素中查找「aloha」,在<div>元素中查找"adios":
1 Console.WriteLine("Seek 'aloha' in <p>[2]"); 2 Console.WriteLine("<p> type is:" + theDoc.getElementsByTagName("p").GetType().ToString()); 3 HTMLParaElement paraElement = (HTMLParaElement)theDoc.getElementsByTagName("p").item(1, null); 4 if (paraElement.innerText.ToString().IndexOf("aloha") >= 0) 5 Console.WriteLine("Found target 'aloha'"); 6 else 7 Console.WriteLine("Target string not found"); 8 9 Console.WriteLine("Seek 'adios' in <div id='div2'>"); 10 HTMLDivElement divElement = (HTMLDivElement)theDoc.getElementsByTagName("div").item("div2", null); 11 if (divElement.innerText.ToString().IndexOf("adios") >= 0) 12 Console.WriteLine("Found target 'adios'"); 13 else 14 Console.WriteLine("Target string not found");
上述代碼中,item()方法:
有時候這些元素的值並不屬於任何子的HTML元素,可用如下代碼解決:
1 // non-HTML element 2 Console.WriteLine("Seeking 'Search Complete' in body"); 3 HTMLBody body = (HTMLBody)theDoc.getElementsByTagName("body").item(0, null); 4 if (body.createTextRange().findText("Search Complete", 0, 4) == true) 5 { 6 Console.WriteLine("Found target string"); 7 } 8 else 9 { 10 Console.WriteLine("*Target string not found*"); 11 pass = false; 12 }
上述代碼中,findText()方法:
1 // Chapter 7 - Low-Level Web UI Testing 2 // Example Program: LowLevelUITest 3 4 5 using System; 6 using SHDocVw; // COM component = Microsoft Internet Controls. IE object 7 using mshtml; // .NET component = Microsoft.mshtml. HTML interfaces 8 using System.Diagnostics; // Process 9 using System.Threading; // Sleep() 10 11 namespace RunTest 12 { 13 class Class1 14 { 15 static AutoResetEvent documentComplete = new AutoResetEvent(false); 16 17 [STAThread] 18 static void Main(string[] args) 19 { 20 try 21 { 22 Console.WriteLine("\nStarting test run"); 23 24 bool pass = true; // assume test run will pass 25 26 SHDocVw.InternetExplorer ie = null; 27 Console.WriteLine("\nLaunching an instance of IE"); 28 Process p = Process.Start("iexplore.exe", "about:blank"); 29 System.Threading.Thread.Sleep(2000); 30 if (p == null) 31 throw new Exception("Could not launch IE"); 32 Console.WriteLine("Process handle = " + p.MainWindowHandle.ToString()); 33 34 SHDocVw.ShellWindows allBrowsers = new SHDocVw.ShellWindows(); 35 Console.WriteLine("Number active browsers = " + allBrowsers.Count); 36 37 if (allBrowsers.Count == 0) 38 throw new Exception("Cannot find IE"); 39 40 Console.WriteLine("Attaching to IE"); 41 int i = 0; 42 43 while (i < allBrowsers.Count && ie == null) 44 { 45 InternetExplorer e = (InternetExplorer)allBrowsers.Item(i); 46 if (e != null) 47 { 48 if (e.HWND == (int)p.MainWindowHandle) 49 ie = e; 50 } 51 ++i; 52 } 53 54 if (ie == null) 55 throw new Exception("Failed to attach to IE"); 56 57 ie.DocumentComplete += new DWebBrowserEvents2_DocumentCompleteEventHandler(ie_DocumentComplete); 58 59 Console.WriteLine("\nNavigating to the Web app"); 60 object nil = new object(); 61 ie.Navigate("http://localhost:30614/WebAUT/Default.aspx", ref nil, ref nil, ref nil, ref nil); 62 63 documentComplete.WaitOne(); 64 65 Console.WriteLine("Setting IE to size 450x360"); 66 ie.Width = 450; 67 ie.Height = 360; 68 Thread.Sleep(1000); 69 70 //if (ie.StatusText.IndexOf("Done") == -1) 71 // Console.WriteLine("could not find 'Done' in status bar"); 72 //else 73 // Console.WriteLine("Find 'Done' in status bar"); 74 75 HTMLDocument theDoc = (HTMLDocument)ie.Document; 76 77 Console.WriteLine("\nSelecting 'ID' radio button"); 78 HTMLInputElement radioButton = (HTMLInputElement)theDoc.getElementById("RadioButtonList1_2"); 79 radioButton.@checked = true; 80 81 82 Console.WriteLine("Setting text box to '2B'"); 83 HTMLInputElement textBox = (HTMLInputElement)theDoc.getElementById("TextBox1"); 84 Console.WriteLine("The textbox has type" + textBox.GetType().ToString()); 85 textBox.value = "2B"; 86 87 Console.WriteLine("Clicking search button"); 88 HTMLInputElement butt = (HTMLInputElement)theDoc.getElementById("Button1"); 89 butt.click(); 90 91 documentComplete.WaitOne(); 92 93 Console.WriteLine("Seek 'aloha' in <p>[2]"); 94 Console.WriteLine("<p> type is:" + theDoc.getElementsByTagName("p").GetType().ToString()); 95 HTMLParaElement paraElement = (HTMLParaElement)theDoc.getElementsByTagName("p").item(1, null); 96 if (paraElement.innerText.ToString().IndexOf("aloha") >= 0) 97 Console.WriteLine("Found target 'aloha'"); 98 else 99 Console.WriteLine("Target string not found"); 100 101 Console.WriteLine("Seek 'adios' in <div id='div2'>"); 102 HTMLDivElement divElement = (HTMLDivElement)theDoc.getElementsByTagName("div").item("div2", null); 103 if (divElement.innerText.ToString().IndexOf("adios") >= 0) 104 Console.WriteLine("Found target 'adios'"); 105 else 106 Console.WriteLine("Target string not found"); 107 108 // non-HTML element 109 Console.WriteLine("Seeking 'Search Complete' in body"); 110 HTMLBody body = (HTMLBody)theDoc.getElementsByTagName("body").item(0, null); 111 if (body.createTextRange().findText("Search Complete", 0, 4) == true) 112 { 113 Console.WriteLine("Found target string"); 114 } 115 else 116 { 117 Console.WriteLine("*Target string not found*"); 118 pass = false; 119 } 120 121 if (pass) 122 Console.WriteLine("\nTest result = Pass\n"); 123 else 124 Console.WriteLine("\nTest result = *FAIL*\n"); 125 126 Console.WriteLine("Closing IE in 4 seconds . . . "); 127 Thread.Sleep(4000); 128 ie.Quit(); 129 130 } 131 catch (Exception ex) 132 { 133 Console.WriteLine("Fatal error: " + ex.Message); 134 Console.ReadLine(); 135 } 136 137 } // Main() 138 139 private static void ie_DocumentComplete(object pDisp, ref object URL) 140 { 141 documentComplete.Set(); 142 } 143 144 } // class Class1 145 } // ns RunTest