《软件测试自动化之道》读书笔记 之 基于Windows的UI测试

《软件测试自动化之道》读书笔记 之 基于Windows的UI测试

2014-09-25

测试自动化程序的任务
待测程序
测试程序
  启动待测程序
  获得待测程序主窗体的句柄
  获得有名字控件的句柄
  获得无名字控件的句柄
  发送字符给控件
  鼠标单击一个控件
  处理消息对话框
  处理菜单
  检查应用程序状态
  示例程序
参考

本章主要讲述如何使用底层的Windows自动化技术通过用户界面来测试应用程序。这些技术涉及Win32 API的调用(比如FindWindow()函数)以及想待测程序发送Windows消息(比如WM_LBUTTONUP)。

测试自动化程序的任务



返回

基于Windows的UI测试,逍遥完成的工作主要有以下三类:

  • 找到目标窗体/控件的句柄
  • 操作这个窗体/控件
  • 检测这个窗体/控件

待测程序



返回

待测程序是一个用来做颜色混合的应用程序,关键代码如下:

 1 using System;
 2 using System.Windows.Forms;
 3
 4 namespace WinApp
 5 {
 6     public partial class Form1 : Form
 7     {
 8         public Form1()
 9         {
10             InitializeComponent();
11         }
12
13         private void button1_Click(object sender, EventArgs e)
14         {
15             string tb = textBox1.Text;
16             string cb = comboBox1.Text;
17
18             if (tb == "<enter color>" || cb == "<pick>")
19                 MessageBox.Show("You need 2  colors", "Error");
20             else
21             {
22                 if (tb == cb)
23                     listBox1.Items.Add("Result is " + tb);
24                 else if (tb == "red" && cb == "blue" || tb == "blue" && cb == "red")
25                     listBox1.Items.Add("Result is purple");
26                 else
27                     listBox1.Items.Add("Result is black");
28             }
29         }
30
31         private void exitToolStripMenuItem1_Click(object sender, EventArgs e)
32         {
33             this.Close();
34         }
35     }
36 }

 图1 AUT 

测试程序



返回

启动待测程序

1 using System.Diagnostics;
2
3         static void Main(string[] args)
4         {
5                //...
6                 string path = "..\\..\\..\\WinApp\\bin\\Debug\\WinApp.exe";
7                 Process p = Process.Start(path);
8                //...
9         }

获得待测程序主窗体的句柄

要获得待测程序主窗体的句柄,可使用FindWindow() Win32 API函数来解决这个问题。

FindWindow()的函数签名用C++来描述是:

HWND FindWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName); 

Win32 API函数FindWindow()是Windows操作系统的一部分,是由传统的C++程序而不是用受控代码(managed code)编写的。它返回HWND(Handle of Window), 是一个窗体的句柄

C#要使用Win32 API函数FindWindow(),可通过.Net平台的invoke(P/Invoke)机制,P/Invoke相关特性位于System.Runtime.InteropServices命名空间内。

        [DllImport("user32.dll", EntryPoint = "FindWindow", CharSet = CharSet.Auto)]
        static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

DllImport是用来将特性化方法由非托管动态链接库 (DLL) 作为静态入口点公开。

说明[1]
  1、DllImport只能放置在方法声明上。
  2、DllImport具有单个定位参数:指定包含被导入方法的 dll 名称的 dllName 参数。
  3、DllImport具有五个命名参数:
   a、CallingConvention 参数指示入口点的调用约定。如果未指定 CallingConvention,则使用默认值 CallingConvention.Winapi。
   b、CharSet 参数指示用在入口点中的字符集。如果未指定 CharSet,则使用默认值 CharSet.Auto。
   c、EntryPoint 参数给出 dll 中入口点的名称。如果未指定 EntryPoint,则使用方法本身的名称。
   d、ExactSpelling 参数指示 EntryPoint 是否必须与指示的入口点的拼写完全匹配。如果未指定 ExactSpelling,则使用默认值 false。
   e、PreserveSig 参数指示方法的签名应当被保留还是被转换。当签名被转换时,它被转换为一个具有 HRESULT 返回值和该返回值的一个名为 retval 的附加输出参数的签名。如果未指定 PreserveSig,则使用默认值 true。
   f、SetLastError 参数指示方法是否保留 Win32"上一错误"。如果未指定 SetLastError,则使用默认值 false。
  4、它是一次性属性类。
  5、此外,用 DllImport 属性修饰的方法必须具有 extern 修饰符。

注意:.NET平台大大简化了数据类型的模型,从而提高了程序开发的效率。要使用P/Invoke机制,必须为Win32数据类型找到相应的 C#数据类型。

此示例中,在.NET坏境中,窗体句柄的类型是System.IntPtr,它是一个平台相关的类型,用来代表指针(内存地址)或者句柄。它对应于Win32的数据类型HWND。String对应于LPCTSTR。

C#与win32 api数据类型对照

参数:

  • lpClassName:是窗体类名称,更OOP中类无任何关系。是由系统生成的一个字符串,用来把相应的窗体注册到操作系统。因为窗体/控件类的名称并不具有唯一性,对查找一个窗体/控件并没有太大帮助。因此,在本示例中传给它null。
  • lpWindowName:是窗体的名称。也被叫做window title或者window caption。在windows form程序中,这个值通常称为form name。

获得待测程序主窗体的句柄示例代码如下:

 1 using System.Runtime.InteropServices;
 2
 3         static void Main(string[] args)
 4         {
 5                 //...
 6                 IntPtr mwh = FindMainWindowHandle("Form1", 100, 25);
 7                 //...
 8         }
 9
10         [DllImport("user32.dll", EntryPoint = "FindWindow", CharSet = CharSet.Auto)]
11         static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
12
13         static IntPtr FindMainWindowHandle(string caption, int delay, int maxTries)
14         {
15             return FindTopLevelWindow(caption, delay, maxTries);
16         }
17
18         static IntPtr FindTopLevelWindow(string caption, int delay, int maxTries)
19         {
20             IntPtr mwh = IntPtr.Zero;
21             bool formFound = false;
22             int attempts = 0;
23
24             do
25             {
26                 //FindWindow
27                 mwh = FindWindow(null, caption);
28                 if (mwh == IntPtr.Zero)
29                 {
30                     Console.WriteLine("Form not yet found");
31                     Thread.Sleep(delay);
32                     ++attempts;
33                 }
34                 else
35                 {
36                     Console.WriteLine("Form has been found");
37                     formFound = true;
38                 }
39             } while (!formFound && attempts < maxTries);
40
41             if (mwh != IntPtr.Zero)
42                 return mwh;
43             else
44                 throw new Exception("Could not find Main Window");
45         } 

获得有名字控件的句柄

1         static void Main(string[] args)
2         {
3                 //...
4                 IntPtr tb = FindWindowEx(mwh, IntPtr.Zero, null, "<enter color>");
5                 //...
6         }
7
8         [DllImport("user32.dll", EntryPoint = "FindWindowEx",CharSet = CharSet.Auto)]
9         static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

参数:

  • hwndParent:控件目标的父窗体句柄
  • hwndChildAfter:从哪个控件开始找,即从下一个控件开始找
  • lpszClass:class name(如上参数lpClassName)
  • lpszWindow:目标控件的window name/title/caption

图2 Spy++捕获控件button1  

获得无名字控件的句柄

如何获得一个没有名字的空间的句柄,可通过隐含索引来查找相应控件

 1         static void Main(string[] args)
 2         {
 3                 //...
 4                 IntPtr cb = FindWindowByIndex(mwh, 2);
 5                 //...
 6         }
 7
 8         [DllImport("user32.dll", EntryPoint = "FindWindowEx",CharSet = CharSet.Auto)]
 9         static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
10
11         static IntPtr FindWindowByIndex(IntPtr hwndParent, int index)
12         {
13             if (index == 0)
14                 return hwndParent;
15             else
16             {
17                 int ct = 0;
18                 IntPtr result = IntPtr.Zero;
19                 do
20                 {
21                     //FindWindowEx
22                     result = FindWindowEx(hwndParent, result, null, null);
23                     if (result != IntPtr.Zero)
24                         ++ct;
25                 } while (ct < index && result != IntPtr.Zero);
26
27                 return result;
28             }
29         }

注意:这里索引的顺序是加入主窗体的顺序。见如下代码,主窗体的索引值为0,先后加入的控件button1的索引为1,comboBox1的索引为2,...

 1         private void InitializeComponent()
 2         {
 3             //...
 4             this.Controls.Add(this.button1);
 5             this.Controls.Add(this.comboBox1);
 6             this.Controls.Add(this.textBox1);
 7             this.Controls.Add(this.menuStrip1);
 8             this.Controls.Add(this.listBox1);
 9             //...
10         }

你也可以通过工具“spy++”来查找先后。

发送字符给控件

SendMessage()的函数签名用C++签名如下:

LRESULT SendMessage(HWND HwND, UINT Msg, WPARAM wParam, LPARAM lParam); 
  • HwND:目标窗体/控件的句柄
  • Msg:要发给该控件的Window消息
  • wParam, lParam:它们的意思和数据类型取决于相应的Windows消息

本例中,我们要发送一个VM_CHAR消息。当按键按下时,VM_CHAR消息会发送给拥有键盘焦点的那个控件。实际上,VM_CHAR是一个Windows的常量符号,它定义为0x0102。wParam参数指定的是被按下按键的字符代码。lParam参数指定的是不同的按键状态码,比如重复次数、扫描码等。有了这些信息,就可以创建相应的C#签名:

        [DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]
        static extern void SendMessage1(IntPtr hWnd, uint Msg, int wParam, int lParam);

发送字符给控件的示例代码:

 1         static void Main(string[] args)
 2         {
 3                 //...
 4                 SendChars(tb, "red");
 5                 //...
 6         }
 7
 8         static void SendChars(IntPtr hControl, string s)
 9         {
10             foreach (char c in s)
11             {
12                 SendChar(hControl, c);
13             }
14         }
15
16         static void SendChar(IntPtr hControl, char c)
17         {
18             uint WM_CHAR = 0x0102;
19             SendMessage1(hControl, WM_CHAR, c, 0);
20         }
21         [DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]
22         static extern void SendMessage1(IntPtr hWnd, uint Msg, int wParam, int lParam);

鼠标单击一个控件

PostMessage()的函数签名用C++签名如下:

BOOL PostMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM LParam);

PostMessage()和SendMessage()的参数列表完全一致,他们的不同是:SendMessage()会等相应的Windows消息之后才会返回;PostMessage()不会。
相应的C#签名:

        [DllImport("user32.dll", EntryPoint = "PostMessage", CharSet = CharSet.Auto)]
        static extern bool PostMessage1(IntPtr hWnd, uint Msg, int wParam, int lParam);

鼠标单击一个控件的示例代码:

 1         static void Main(string[] args)
 2         {
 3                 //...
 4                 ClickOn(okButt);
 5                 //...
 6         }
 7
 8         static void ClickOn(IntPtr hControl)
 9         {
10             uint WM_LBUTTONDOWN = 0x0201;
11             uint WM_LBUTTONUP = 0x0202;
12             PostMessage1(hControl, WM_LBUTTONDOWN, 0, 0);
13             PostMessage1(hControl, WM_LBUTTONUP, 0, 0);
14         }
15         [DllImport("user32.dll", EntryPoint = "PostMessage", CharSet = CharSet.Auto)]
16         static extern bool PostMessage1(IntPtr hWnd, uint Msg, int wParam, int lParam);

处理消息对话框

消息对话框是一个上层(top-level)窗体,使用FindWindow()函数捕获它。

处理菜单

处理菜单的的示例代码:

 1         static void Main(string[] args)
 2         {
 3                 //...
 4
 5                 //mwh: main window handle
 6                 IntPtr hMainMenu = GetMenu(mwh);
 7                 IntPtr hFile = GetSubMenu(hMainMenu, 0);
 8                 int iExit = GetMenuItemID(hFile, 2);
 9                 uint WM_COMMAND = 0x0111;
10                 SendMessage2(mwh, WM_COMMAND, iExit, IntPtr.Zero);
11                 //...
12         }
13
14         [DllImport("user32.dll")] //
15         static extern IntPtr GetMenu(IntPtr hWnd);
16
17         [DllImport("user32.dll")] //
18         static extern IntPtr GetSubMenu(IntPtr hMenu, int nPos);
19
20         [DllImport("user32.dll")] //
21         static extern int GetMenuItemID(IntPtr hMenu, int nPos);
22
23         [DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]
24         static extern void SendMessage2(IntPtr hWnd, uint Msg, int wParam, IntPtr lParam);

  • GetMenu():返回程序主菜单的句柄
  • GetSubMenu():返回子菜单的句柄
  • GetSubMenu():返回菜单项的索引值。

在该示例中选择File->Exit,并点击它。

图3 处理菜单

检查应用程序状态

使用VM_GETTEXT和SendMessage()获得控件状态

检查应用程序状态的示例代码

 1         static void Main(string[] args)
 2         {
 3                 //...
 4                 uint VM_GETTEXT = 0x000D;
 5                 byte[] buffer=new byte[256];
 6                 string text = null;
 7                 int numFetched = SendMessage3(tb, VM_GETTEXT, 256, buffer);
 8                 text = System.Text.Encoding.Unicode.GetString(buffer);
 9                 Console.WriteLine("Fetched " + numFetched + " chars");
10                 Console.WriteLine("TextBox1 contains = " + text);
11                 //...
12         }
13         [DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]
14         static extern int SendMessage3(IntPtr hWndControl, uint Msg, int wParam, byte[] lParam);

示例程序

  1 // Chapter 3 - Windows-Based UI Testing
  2 // Example Program: WindowsUITest
  3
  4 using System;
  5 using System.Diagnostics;
  6 using System.Runtime.InteropServices;
  7 using System.Threading;
  8
  9 namespace WindowsUITest
 10 {
 11     class Class1
 12     {
 13         [STAThread]
 14         static void Main(string[] args)
 15         {
 16             try
 17             {
 18                 Console.WriteLine("\nLaunching application under test");
 19
 20                 string path = "..\\..\\..\\WinApp\\bin\\Debug\\WinApp.exe";
 21                 Process p = Process.Start(path);
 22
 23                 Console.WriteLine("\nFinding main window handle");
 24                 IntPtr mwh = FindMainWindowHandle("Form1", 100, 25);
 25                 Console.WriteLine("Main window handle = " + mwh);
 26
 27                 Console.WriteLine("\nFinding handles to textBox1, comboBox1");
 28                 Console.WriteLine(" button1, listBox1");
 29
 30                 // you may want to add delays here to make sure Form has rendered
 31                 IntPtr tb = FindWindowEx(mwh, IntPtr.Zero, null, "<enter color>");
 32                 IntPtr cb = FindWindowByIndex(mwh, 2);
 33                 IntPtr butt = FindWindowEx(mwh, IntPtr.Zero, null, "button1");
 34                 IntPtr lb = FindWindowByIndex(mwh, 5);
 35
 36                 if (tb == IntPtr.Zero || cb == IntPtr.Zero ||
 37                     butt == IntPtr.Zero || lb == IntPtr.Zero)
 38                     throw new Exception("Unable to find all controls");
 39                 else
 40                     Console.WriteLine("All control handles found");
 41
 42                 Console.WriteLine("\nClicking button1");
 43                 ClickOn(butt);
 44
 45                 Console.WriteLine("Clicking away Error message box");
 46                 IntPtr mb = FindMessageBox("Error");
 47                 if (mb == IntPtr.Zero)
 48                     throw new Exception("Unable to find message box");
 49                 IntPtr okButt = FindWindowEx(mb, IntPtr.Zero, null, "OK");
 50                 if (okButt == IntPtr.Zero)
 51                     throw new Exception("Unable to find OK button");
 52                 ClickOn(okButt);
 53
 54                 Console.WriteLine("Typing ‘red‘ and ‘blue‘ to application");
 55                 SendChars(tb, "red");
 56
 57                 Console.WriteLine("Check for textBox1");
 58                 uint VM_GETTEXT = 0x000D;
 59                 byte[] buffer = new byte[256];
 60                 string text = null;
 61                 int numFetched = SendMessage3(lb, VM_GETTEXT, 256, buffer);
 62                 text = System.Text.Encoding.Unicode.GetString(buffer);
 63                 Console.WriteLine("Fetched " + numFetched + " chars");
 64                 Console.WriteLine("TextBox1 contains = " + text);
 65
 66                 ClickOn(cb);
 67                 SendChars(cb, "blue");
 68
 69                 Console.WriteLine("Clicking on button1");
 70                 ClickOn(butt);
 71
 72                 Console.WriteLine("\nChecking listBox1 for ‘purple‘");
 73
 74                 uint LB_FINDSTRING = 0x018F;
 75                 int result = SendMessage4(lb, LB_FINDSTRING, -1, "Result is purple1");
 76                 if (result >= 0)
 77                     Console.WriteLine("\nTest scenario result = Pass");
 78                 else
 79                     Console.WriteLine("\nTest scenario result = *FAIL*");
 80
 81
 82                 Console.WriteLine("\nExiting app in 3 seconds . . . ");
 83                 //GetMenu not work
 84                 Thread.Sleep(3000);
 85                 IntPtr hMainMenu = GetMenu(mwh);
 86                 IntPtr hFile = GetSubMenu(hMainMenu, 0);
 87                 int iExit = GetMenuItemID(hFile, 2);
 88                 uint WM_COMMAND = 0x0111;
 89                 SendMessage2(mwh, WM_COMMAND, iExit, IntPtr.Zero);
 90
 91                 Console.WriteLine("\nDone");
 92                 Console.ReadLine();
 93             }
 94             catch (Exception ex)
 95             {
 96                 Console.WriteLine("Fatal error: " + ex.Message);
 97             }
 98         } // Main()
 99
100         static IntPtr FindTopLevelWindow(string caption, int delay, int maxTries)
101         {
102             IntPtr mwh = IntPtr.Zero;
103             bool formFound = false;
104             int attempts = 0;
105
106             do
107             {
108                 mwh = FindWindow(null, caption);
109                 if (mwh == IntPtr.Zero)
110                 {
111                     Console.WriteLine("Form not yet found");
112                     Thread.Sleep(delay);
113                     ++attempts;
114                 }
115                 else
116                 {
117                     Console.WriteLine("Form has been found");
118                     formFound = true;
119                 }
120             } while (!formFound && attempts < maxTries);
121
122             if (mwh != IntPtr.Zero)
123                 return mwh;
124             else
125                 throw new Exception("Could not find Main Window");
126         } // FindTopLevelWindow()
127
128         static IntPtr FindMainWindowHandle(string caption, int delay, int maxTries)
129         {
130             return FindTopLevelWindow(caption, delay, maxTries);
131         }
132
133         static IntPtr FindMessageBox(string caption)
134         {
135             int delay = 100;
136             int maxTries = 25;
137             return FindTopLevelWindow(caption, delay, maxTries);
138         }
139
140         static IntPtr FindWindowByIndex(IntPtr hwndParent, int index)
141         {
142             if (index == 0)
143                 return hwndParent;
144             else
145             {
146                 int ct = 0;
147                 IntPtr result = IntPtr.Zero;
148                 do
149                 {
150                     result = FindWindowEx(hwndParent, result, null, null);
151                     if (result != IntPtr.Zero)
152                         ++ct;
153                 } while (ct < index && result != IntPtr.Zero);
154
155                 return result;
156             }
157         } // FindWindowByIndex()
158
159         static void ClickOn(IntPtr hControl)
160         {
161             uint WM_LBUTTONDOWN = 0x0201;
162             uint WM_LBUTTONUP = 0x0202;
163             PostMessage1(hControl, WM_LBUTTONDOWN, 0, 0);
164             PostMessage1(hControl, WM_LBUTTONUP, 0, 0);
165             Thread.Sleep(1000);
166         }
167
168         static void SendChar(IntPtr hControl, char c)
169         {
170             uint WM_CHAR = 0x0102;
171             SendMessage1(hControl, WM_CHAR, c, 0);
172         }
173
174         static void SendChars(IntPtr hControl, string s)
175         {
176             foreach (char c in s)
177             {
178                 SendChar(hControl, c);
179             }
180         }
181
182         // P/Invoke Aliases
183
184         [DllImport("user32.dll", EntryPoint = "FindWindow", CharSet = CharSet.Auto)]
185         static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
186
187         [DllImport("user32.dll", EntryPoint = "FindWindowEx", CharSet = CharSet.Auto)]
188         static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
189
190         // for WM_CHAR message
191         [DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]
192         static extern void SendMessage1(IntPtr hWnd, uint Msg, int wParam, int lParam);
193
194         // for WM_COMMAND message
195         [DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]
196         static extern void SendMessage2(IntPtr hWnd, uint Msg, int wParam, IntPtr lParam);
197
198         // for WM_LBUTTONDOWN and WM_LBUTTONUP messages
199         [DllImport("user32.dll", EntryPoint = "PostMessage", CharSet = CharSet.Auto)]
200         static extern bool PostMessage1(IntPtr hWnd, uint Msg, int wParam, int lParam);
201
202         // for WM_GETTEXT message
203         [DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]
204         static extern int SendMessage3(IntPtr hWndControl, uint Msg, int wParam, byte[] lParam);
205
206         // for LB_FINDSTRING message
207         [DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]
208         static extern int SendMessage4(IntPtr hWnd, uint Msg, int wParam, string lParam);
209
210         // Menu routines
211         [DllImport("user32.dll")] //
212         static extern IntPtr GetMenu(IntPtr hWnd);
213
214         [DllImport("user32.dll")] //
215         static extern IntPtr GetSubMenu(IntPtr hMenu, int nPos);
216
217         [DllImport("user32.dll")] //
218         static extern int GetMenuItemID(IntPtr hMenu, int nPos);
219
220     } // class
221 } // ns

参考

[1] C# DllImport的用法

[2] C#与win32 api数据类型对照

时间: 2024-09-29 09:20:45

《软件测试自动化之道》读书笔记 之 基于Windows的UI测试的相关文章

《软件测试自动化之道》读书笔记 之 基于反射的UI测试

<软件测试自动化之道>读书笔记 之 基于反射的UI测试 2014-09-24 测试自动化程序的任务待测程序测试程序  启动待测程序  设置窗体的属性  获取窗体的属性  设置控件的属性  获取控件的属性  方法调用  待测程序代码 测试自动化程序的任务 返回 基于反射的ui测试自动化程序,要完成的6项任务: 通过某种方式从测试套件程序中运行待测程序(AUT: Applicaton Under Test),以便于两个程序之间进行通信 操纵应用程序的窗体,从而模拟用户对窗体所实施的moving和r

《软件测试自动化之道》读书笔记 之 底层的Web UI 测试

<软件测试自动化之道>读书笔记 之 底层的Web UI 测试 2014-09-28 测试自动化程序的任务待测程序测试程序  启动IE并连接到这个实例  如何判断待测web程序完全加载到浏览器  操纵并检查IE Shell  操作待测Web页面上的HTML元素的值  验证Web页面上HTML元素  示例代码 测试自动化程序的任务 底层技术的核心是,通过直接调用mshtml.dll和shdocvw.dll库来访问并且操纵IE客户区域的HTML对象. 待测程序 新建一个网站“WebAUT”,删除原来

《软件测试自动化之道》读书笔记 之 目录导航

<软件测试自动化之道>读书笔记 之 目录导航 2014-10-09 源代码 第1章 API测试第2章 基于反射的UI测试第3章 基于Windows的UI测试第4章 测试套件设计模式第5章 请求-响应测试 第6章 基于脚本的Web UI测试第7章 底层的Web UI测试第8章 Web Service测试第9章 SQL存储过程测试 第10章 排列与组合第11章 ADO.NET测试第12章 XML测试

《软件测试自动化之道》读书笔记 之 SQL 存储过程测试

<软件测试自动化之道>读书笔记 之 SQL 存储过程测试 2014-09-28 待测程序测试程序   创建测试用例以及测试结果存储  执行T-SQL脚本  使用BCP工具导入测试用例数据  创建T-SQL 测试套件  当待测存储过程返回行集的时候,如何判断测试结果是否通过  当待测存储过程返回out参数时,如何判断测试结果是否通过  当待测存储过程没有返回值时,如何判断测试结果是否通过 许多基于Windows的系统都使用了SQL Server作为后台组件.待测程序经常通过存储过程来访问数据库.

《软件测试自动化之道》读书笔记 之 XML测试

<软件测试自动化之道>读书笔记 之 XML测试 2014-10-07 待测程序测试程序  通过XmlTextReader解析XML  通过XmlDocument解析XML  通过XmlPathDocument解析XML  通过XmlSerializer解析XML  通过DataSet解析XML   通过XSD Schema对XML文件进行验证  通过XSLT对XML文件进行修改  通过XmlTextWrite对XML文件进行写操作  比较两个XML文件是否严格相等  不考虑编码方式,比较两个X

《软件测试自动化之道》- 基于反射的UI自动化测试框架 - UI Automation Test Framework

测试自动化程序的任务 基于反射的ui测试自动化程序,要完成的6项任务: 通过某种方式从测试套件程序中运行待测程序(AUT: Applicaton Under Test),以便于两个程序之间进行通信 操纵应用程序的窗体,从而模拟用户对窗体所实施的moving和resizing操作 检查应用程序窗体,确定应用程序的状态是否准确 操纵应用程序控件的属性,从而模拟用户的一些操作,比如模拟在一个TextBox控件里输入字符 检查应用程序控件的属性,确定应用程序的状态是否准确 调用应用程序的方法,从而模拟一

《赢在测试2-中国软件测试专家访谈录》读书笔记

<赢在测试2-中国软件测试专家访谈录>读书笔记 2015-04-30 测试人物经历与观点  1.董杰 百度测试架构师    董杰的职业发展经历    如何成长为一个优秀的测试工程师?    如何开展软件测试工作?  2.邰晓梅 独立测试咨询顾问    邰晓梅职业发展经历    测试与开发的关系    对测试认识的三个阶段  3.一些分析:对测试的一些想法 职业发展是一个探索和尝试的过程,职业发展的目标是动态的,也可能会变. 测试人物经历与观点 返回 1.董杰 百度测试架构师 董杰的职业发展经历

VC++编程之道读书笔记(2)

第三篇 技术细节 第七章:细说开发人员必知必会的39个开发细节 细节36:单例模式的应用 在开发程序时,往往需要在整个工程中只需要一个类的实例.而这个实例一旦被创建就不能被其他的实例再创建了,通常我们称这个实现过程为单例模式. 既然要保证类只有一个实例,那么就需要其他的类不能使用实例化该类.因此,需要将其构造方法设为私有的,即使用private关键字修饰.同时,类中提供一个静态方法,该方法的返回值是该类的一个实例.这样就只能使用该静态方法来获取类的实例了,从而保证了唯一性. 下面通过具体代码来实

VC++编程之道读书笔记

第二篇 缪误21:位图数据是按照红绿蓝顺序存储的 大家都知道位图的颜色是由红.绿.蓝三个分量构成的,但是位图颜色数据存储的方式则不是按照这个顺序存储的,而是按照蓝.绿.红的顺序存储的.并且对于真彩色位图来说,位图的颜色数据是倒序存储的,即位图的第一行数据位于位图数据的最底部. 第三篇 细节12 :内存中的数组 在C++中通过数组可以操作内存,创建数组时需要为数组分配内存空间,操作数组时就是对内存空间中的数组元素进行操作.数组创建后,数组引用和数组元素分别存储在栈内存和堆内存中,并通过数组引用与数