您的位置:首页 > 产品设计 > UI/UE

.Net软件UI界面测试自动化--反射技术

2011-08-16 13:33 330 查看
      在目前进行软件测试时,都或多或少的引入了自动化测试的概念,而且市面上也有好多软件自动化方面相关的工具,比如QTP,比如LoadRunner,但是这些工具要么售价不菲,要么对某些方面功能支持的不够全面,那么我们在引入软件自动化测试时,都需要考虑哪些方面呢?当然是最符合自己项目的工具最合适,同时费用也比较低,那么除了市面上这些商业软件外,还有没有哪些方法可以自己动手来做软件的自动化测试呢?答案是肯定的.

      本文将介绍实现软件自动化测试其中一种测试方法------反射技术,当然,此种方法仅限于对.Net软件使用,还有一些比较通用的方法,将在后续的文章中进行介绍(包括使用UIAutomation类以及Windows API).

      反射技术具体是什么原理,本文将不做任何介绍,大家可以去网上搜索一下,有很多这方面的文章介绍,本文只介绍如何使用反射技术进行.NET软件的UI界面的自动化测试.

      废话少说,多做实事!(本文所有代码均在VS2008环境下测试通过)

      一. 创建待测试程序

          1. 启动VS2008,建立一个C#的WinForm工程,并将工程文件名命名为AUT(Application Under Test)

          2. 创建的Form上的按钮布局,如下图所示

              


          3. 一个菜单(包含一个以及菜单File以及一个二级菜单Exit),一个TextBox,一个ComboBox,一个Button以及一个ListBox

        private System.Windows.Forms.MenuStrip menuStrip1;
private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem;
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.ComboBox comboBox1;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.ListBox listBox1;             
4. 给Button按钮添加一个消息响应函数    

        private void button1_Click(object sender, EventArgs e)
{
string tb = textBox1.Text;
string cb = comboBox1.Text;

if (tb == cb)
{
listBox1.Items.Add("Result is a tie");
}
else if (tb == "paper" && cb == "rock" ||
tb == "rock" && cb == "scissors" ||
tb == "scissors" && cb == "paper")
{
listBox1.Items.Add("The TextBox wins");
}
else
{
listBox1.Items.Add("The ComboBox wins");
}
}
           5. 给Exit菜单添加一个消息响应函数       
       private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Application.Exit();
}
           6.给ComboBox控件添加三个Item,分别为paper,rock,scissions

  7. 编译待测试程序,生成文件名为AUT.exe的待测试程序

      二. 创建自动化测试程序

           1. 启动VS2008,创建一个C#控制台程序,并命名为ReflectionUITest

           2. 在工程中添加两个引用:System.Windows.Form以及System.Drawing

           3. 在工程中添加以下using语句          

       using System;
       using System.Reflection;
       using System.Windows.Forms;
       using System.Threading;
       using System.Drawing;
       using System.IO;

           4. 编写启动待测试程序的函数

        static Form LaunchApp(string path, string formName)
{
Form result = null;
            //通过反射技术时,可以通过Assembly类来进行,此处将待测试程序动态加载生成Assembly类
            Assembly a = Assembly.LoadFrom(path);
            //获取Assembly类的类型
            Type t = a.GetType(formName);
            //创建Form的实例
result = (Form)a.CreateInstance(t.FullName);
            //设置线程启动时运行的函数
AppState aps = new AppState(result);
ThreadStart ts = new ThreadStart(aps.RunApp);
            //启动线程
            Thread thread = new Thread(ts);
thread.Start();
//返回Form实例
return result;
}

private class AppState
{
public readonly Form formToRun;

public AppState(Form f)
{
this.formToRun = f;
}

public void RunApp()
{
Application.Run(formToRun);
}
}
           5. 设置窗体的属性信息

        //定义一个委托事件
        delegate void SetFormPropertyValueHandler(Form f, string propertyName, object newValue);
static void SetFormPropertyValue(Form f, string propertyName, object newValue)
{
if (f.InvokeRequired)
{
Delegate d = new SetFormPropertyValueHandler(SetFormPropertyValue);
object[] o = new object[] { f, propertyName, newValue };
f.Invoke(d, o);
are.WaitOne();
}
else
{
                //获取窗体的类型
                Type t = f.GetType();
                //根据指定的属性来获取PropertyInfo信息
                PropertyInfo pi = t.GetProperty(propertyName);
                //设置属性值
                pi.SetValue(f, newValue, null);
are.Set();
}
}
           6. 获取窗体的属性

        delegate object GetFormPropertyValueHandler(Form f, string propertyName);
static object GetFormPropertyValue(Form f, string propertyName)
{
if (f.InvokeRequired)
{
Delegate d = new GetFormPropertyValueHandler(GetFormPropertyValue);
object[] o = new object[] { f, propertyName };
object iResult = f.Invoke(d, o);
are.WaitOne();
return iResult;
}
else
{
Type t = f.GetType();
PropertyInfo pi = t.GetProperty(propertyName);
object gResult = pi.GetValue(f, null);
are.Set();
return gResult;
}
}
           7. 设置窗体中指定控件的信息

        delegate void SetControlPropertyValueHandler(Form f, string controlName, string propertyName, object newValue);
static void SetControlPropertyValue(Form f, string controlName, string propertyName, object newValue)
{
if (f.InvokeRequired)
{
Delegate d = new SetControlPropertyValueHandler(SetControlPropertyValue);
object[] o = new object[] { f, controlName, propertyName, newValue };
f.Invoke(d, o);
are.WaitOne();
}
else
{
                //获取窗体的类型
                Type t1 = f.GetType();
                //根据控件名称获取指定的FieldInfo信息
                FieldInfo fi = t1.GetField(controlName, flags);
                //获取指定控件的对象
object ctrl = fi.GetValue(f);
                //获取指定控件对象的类型
Type t2 = ctrl.GetType();
                //查找指定的属性
                PropertyInfo pi = t2.GetProperty(propertyName);
                //设置属性值
                pi.SetValue(ctrl, newValue, null);
are.Set();
}
}
           8. 获取窗体中指定控件的信息

        delegate object GetControlPropertyValueHandler(Form f, string controlName, string propertyName);
static object GetControlPropertyValue(Form f, string controlName, string propertyName)
{
if (f.InvokeRequired)
{
Delegate d = new GetControlPropertyValueHandler(GetControlPropertyValue);
object[] o = new object[] { f, controlName, propertyName };
object iResult = f.Invoke(d, o);
are.WaitOne();
return iResult;
}
else
{
Type t1 = f.GetType();
FieldInfo fi = t1.GetField(controlName, flags);
object ctrl = fi.GetValue(f);
Type t2 = ctrl.GetType();
PropertyInfo pi = t2.GetProperty(propertyName);
object gResult = pi.GetValue(ctrl, null);
are.Set();
return gResult;
}
}
           9. 执行指定的函数

        delegate void InvokeMethodHandler(Form f, string methodName, params object[] parms);
static void InvokeMethod(Form f, string methodName, params object[] parms)
{
if (f.InvokeRequired)
{
Delegate d = new InvokeMethodHandler(InvokeMethod);
f.Invoke(d, new object[] { f, methodName, parms });
are.WaitOne();
}
else
{
Type t = f.GetType();
MethodInfo mi = t.GetMethod(methodName, flags);
mi.Invoke(f, parms);
are.Set();
}
}
           10. 声明需要使用到的变量

        static BindingFlags flags = BindingFlags.Public |
               BindingFlags.NonPublic |
                                                   BindingFlags.Static |
                                    BindingFlags.Instance;
static AutoResetEvent are = new AutoResetEvent(false);
           11. 编写测试代码

            try
{
Console.WriteLine("\nStart test scenario");
Console.WriteLine("\nLaunching Form1");

Form theform = null;
string formName = "AUT.Form1";
string path = Directory.GetCurrentDirectory() + "\\AUT.exe";
theform = LaunchApp(path, formName);

Thread.Sleep(1000);

Console.WriteLine("\nMoving Form1");
Point pt = new Point(600, 200);
SetFormPropertyValue(theform, "Location", pt);

Console.WriteLine("\nGetting Form1 Location");
Point lt = (Point)GetFormPropertyValue(theform, "Location");
Console.WriteLine("X: " + lt.X.ToString() + " Y: " + lt.Y.ToString());

Console.WriteLine("\nSetting TextBox to 'rock'");
SetControlPropertyValue(theform, "textBox1", "Text", "rock");

Console.WriteLine("\nSetting ComboBox to 'scissors'");
SetControlPropertyValue(theform, "comboBox1", "Text", "scissors");

Console.WriteLine("\nClicking button1");
object[] parms = new object[] { null, EventArgs.Empty };
InvokeMethod(theform, "button1_Click", parms);

bool pass = true;

Console.WriteLine("\nCheckint listBox1 for 'TextBox wins'");
ListBox.ObjectCollection oc = (ListBox.ObjectCollection)GetControlPropertyValue(theform, "listBox1", "Items");

string s = oc[0].ToString();
if (s.IndexOf("TextBox wins") == -1)
{
pass = false;
}

if (pass)
{
Console.WriteLine("\n-- Scenario result = Pass --");
}
else
{
Console.WriteLine("\n-- Scenario result = Fail --");
}

Console.WriteLine("\nClicking File->Exit in 3 Seconds");
Thread.Sleep(3000);
InvokeMethod(theform, "exitToolStripMenuItem_Click", parms);

Console.WriteLine("\nEnd test scenario");
}
catch (System.Exception ex)
{
Console.WriteLine("Fatal error: " + ex.Message);
}
           12. 编译生成测试程序并运行,OK,大功告成

     
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息