《軟件測試自動化之道》讀書筆記 之 底層的Web UI 測試

《軟件測試自動化之道》讀書筆記 之 底層的Web UI 測試

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 }
View Code

測試程序

啓動IE並鏈接到這個實例

 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         }
View Code

如何判斷待測web程序徹底加載到瀏覽器

 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         }
View Code

測試程序有可能在待測程序還沒有徹底加載的狀況下試圖對其進行操做,這麼作,極可能引起異常。測試程序可經過事件DocumentComplete和AutoResetEvent類,對自動化程序進行同步。測試

AutoResetEvent類還有帶參數的WaitOne()方法,用於指定最大等待時間,超過就再也不等待:網站

//9000毫秒,true標識能夠再等待結束以前推出同步域
documentComplete.WaitOne(9000,true)

操縱並檢查IE Shell

 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         }
View Code

當編寫針對Web UI的自動化測試程序師,須要把IE的3個區域考慮在內:ui

  • 客戶區域,即待測頁面所在區域;
  • Shell區域,即諸如地址欄和回退按鈕等IE控件所在的區域;
  • 以及其餘窗口,好比alert對話框等,這些窗口與IE是分開的。

SHDocVw.InternetExplorer對象提供了一些屬性和方法用於操縱(可用來模擬用戶操做)和檢查Shell(可用來判斷某個測試場景經過與否)。下面是幾種屬性和方法:this

  • GoBack(), GoForward(), GoHome(), Refresh(), Quit();
  • Height, Width: 設置IE外殼的高度和寬度(以像素爲單位)。
  • Top, Left: 設置IE外殼左上角的位置(以像素爲單位)。
  • FullScreen:若是IE在全屏模式下運行,則返回true。
  • MenuBar:若是IE菜單欄可見,則返回true。
  • Resizable:若是能夠調整IE的大小,則返回true。
  • LocationURL:返回IE當前顯示頁面的URL。
  • StatusText:返回IE狀態欄的文本。

操做待測Web頁面上的HTML元素的值

示例代碼:

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();

                //...
        }
View Code

在上述代碼中,要模擬用戶選中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。

驗證Web頁面上HTML元素

經過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");
View Code

上述代碼中,item()方法:

  • 第一個參數能夠爲整數(整數時爲從0開始的索引值)或字符串(字符串時爲tag名字);
  • 第二個參數是個索引值,但只有當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                 }
View Code

上述代碼中,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
View Code
相關文章
相關標籤/搜索