运行待测程序的基本思想:
通过某种方式(进程, 线程),从测试套间程序中运行待测程序(AUT:Application Under Test),以便于实现两个程序之间的通信。
要使用反射技术通过UI来测试Windows窗体,必须要在测试套间所在的进程内创建一个单独的线程来运行被测程序。如果不这么做,而是通过利用进程Process.Start()的方法:
string exePath = "..//..//..//AUT//bin//Debug//AUT.exe";
System.Diagnostics.Process.Start(exePath);
会有一定的问题产生,因为:
这种方法虽然可以把程序运行起来,但是测试套间不能直接和被测程序进行通信,因为测试程序和被测程序运行在不同的进程中。要让测试程序能够与被测程序进行通信,诀窍就是要在测试程序中为被测程序产生一个单独的线程。这样,测试程序与被测程序就能运行在同一个进程里,从而可以相互通信。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms; using System.Threading; using System.Reflection; using System.Drawing; namespace TestingAUT { class Program { static void Main(string[] args) { try { Console.WriteLine("Launching Form...."); //Form theForm = null; string formName = "AUT.Form1"; string Path = @"C:/Users/btslabs/Desktop/TE/AUT/AUT/bin/Debug/AUT.exe"; Form theForm = LaunchApp(Path, formName); Console.WriteLine("AUT launched!"); Thread.Sleep(1500); Console.ReadKey(); } catch (Exception ex) { Console.WriteLine("Fatal error: " + ex.Message); Console.ReadKey(); } } //模块1,运行待测程序. static Form LaunchApp(string path, string formName) { Form result = null; //首先获得一个待测程序窗体对象的引用 //通过工厂机制来创建Assembly对象。 Assembly a = Assembly.LoadFrom(path); //Type的使用,其实就是不知道类名以及类的成员信息的情况下,一种泛泛使用class的概念. Type t = a.GetType(formName); //createInstance()是Assembly对象的方法, 它的参数是被创建实例的全名. //全名称参数是通过一个Type对象来调用的. result = (Form)a.CreateInstance(t.FullName); //using the wrapper class and Thread to launch the App AppState aps = new AppState(result); //要创建一个ThreadStart对象,需要传一个目标方法(Target method)给ThreadStart的构造函数. //这个目标方法必须返回void类型 //当线程开始执行时,要调用的就是这个目标方法. ThreadStart ts = new ThreadStart(aps.RunApp); //要创建一个Thread对象,需要传一个ThreadStart对象给Thread的构造函数 Thread thread = new Thread(ts); thread.ApartmentState = ApartmentState.STA; thread.IsBackground = true; thread.Start(); return result; } //定义一个外覆类以使Application.Run()传给ThreadStart class AppState { public Form myForm; public AppState(Form F) { this.myForm = F; } //目标是将一个有参数的方法转换成一个无参数的,且返回值为void的方法,供ThreadStart构造函数使用。 //因为ThreadStart构造函数使用一个委托,参数必须只是一个是无参数的方法名. public void RunApp() { Application.Run(myForm); } }