一个简单的自动化测试架构的实现(C#)
2012-05-30 22:23
543 查看
一个简单的自动化测试架构的实现(C#)
翻看自己以前写的代码,突然间看到以前模拟的一个自动化测试架构的实现。幸好自己有写学习笔记的习惯,整理一下,贴出来,以备忘。特性会作为元数据嵌入到程序集,通过反射机制能够得到这些元数据信息。程序员可以自己定义特性,对特性进行某种格式的定义,并利用特性来影响自己编写代码编译后的程序集(assmbly)自定义特性在编译时作为元数据被编译到程序集中,运行时通过反射机制被读取。这应该是这个自动化测试架构的立足点。
特性的应用:特性一般会在设计框架时很有用。
1. 利用反射机制,作为特性的元数据可以反过来在运行时影响代码的运行配置项,(例如:Windows Form程序中[STAThread]和[MTAThread用于表明应用程序的线程模型是单线程单元还是多线程--是否可以这样归属有待商榷)或者为特殊的操作方法以特性作标记,以便在运行时做特殊处理(在P/Invoke中DLLImport特性标记方法转化为托管方法)。
2. 可以用于构建管理项目程序集工具:特性表现为某种特殊注释,而注释内容可以在编译后从程序集(例如TestCaseClass.DLL)中读取出来,从而可以通过特性内容的注释和读取实现对程序集中各种类型和方法进行管理(例如可以筛选特定特性的方法执行)。
该框架定义了[ClassInitiative][ClassCleanup][TestMethod]等特性以标记测试函数,而[TestMethod]中还可以定义一些特性参数[TestProperty]去将testmethod分类。在运行时要从待测程序集(dll)中读取相应函数,并保证不同函数的运行顺序。该框架有一系列函数来完成这项工作,这些函数负责运行待测程序集中特定特性标记所标记的函数。如InvokeInitiative()运行标记有[ClassInitiative]的函数;InvokeTestMethod()运行标记[TestMethod]的函数,并用这个InvokeXXX()函数调用先后顺序保证这几种特性函数运行顺序。而这几个InvokeXXX函数中利用反射机制去筛选相应的函数去运行。其中InvokeTestMethod()应该有参数,通过主函数的开关传入,以筛选特定特性的方法。
自定义特性时要注意的
1. 自定义特性继承自System.Attribute.
2. 特性参数分为环境参数和命名参数,如果特性类有自己的构造函数,则参数是必选的,为命名参数;剩下的参数为命名参数。在特性中应用命名参数必须加上参数名称。可以重载构造函数以满足不同组合。
部分定义特性的代码:
namespace AttributesClass { [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] public sealed class ClassCleanupAttribute:Attribute { public ClassCleanupAttribute() { } } } namespace AttributesClass { [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] public sealed class ClassInitializeAttribute:Attribute { public ClassInitializeAttribute() { } } } namespace AttributesClass { [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] public sealed class DescriptionAttribute:Attribute { private string description; public string Description { get { return this.description; } set { this.description = value; } } public DescriptionAttribute(string text) { this.description = text; } } } namespace AttributesClass { [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] public sealed class PriorityAttribute:Attribute { private int priorityLevel; public int Level { get { return this.priorityLevel; } set { this.priorityLevel = value; } } public PriorityAttribute(int level) { this.priorityLevel = level; } } } namespace AttributesClass { [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] public sealed class TestPropertyAttribute:Attribute { #region Fileds private string propertyName = null; private string propertyValue = null; #endregion #region Proerties public string Name { get { return this.propertyName; } set { this.propertyName = value; } } public string Value { get { return this.propertyValue; } set { this.propertyValue = value;} } #endregion #region Constructors public TestPropertyAttribute(string strPropertyName, string strPropertyValue) { this.propertyName = strPropertyName; this.propertyValue = strPropertyValue; } #endregion } }
RunTest函数是重中之重。它完成功能如下:
查找TestProperty限定的方法,找到后查找所在类是否有ClassInitialize和ClassCleanup方法,如果有则先执行前者然后执行该方法最后执行后者。
public void RunTest(string name, string value) { List<string> selectedMethods = SearchMethodByTestProperty(name, value); foreach (string method in selectedMethods) { string[] strSplitMethod = method.Split('.'); string nameSpaceName = strSplitMethod[0]; string className = strSplitMethod[1]; string methodName = strSplitMethod[2]; Console.WriteLine(nameSpaceName + '.' + className); Console.WriteLine("-------------------------------------------------------"); Type typeClass = assmeblyObject.GetType(nameSpaceName + '.' + className); MethodInfo testMethod = typeClass.GetMethod(methodName); object classObject = assmeblyObject.CreateInstance(nameSpaceName+'.'+className); MethodInfo[] methodArray = typeClass.GetMethods(); foreach (MethodInfo objMethod in methodArray) { object[] classInitializeAttributes = objMethod.GetCustomAttributes(typeof(AttributesClass.ClassInitializeAttribute), true); if (classInitializeAttributes.Length == 1) { Console.WriteLine("You are invoking the classInitialize method..."); Console.WriteLine(objMethod.Name + @"() "); objMethod.Invoke(classObject, null); //InvokeIntialize(classObject, objMethod); } } //InvokeTestMethod(classObject, method); Console.WriteLine("You are invoking the Select method..."); Console.WriteLine(methodName + @"() "); testMethod.Invoke(classObject, null); foreach (MethodInfo objMethod in methodArray) { object[] classCleanupAttributes = objMethod.GetCustomAttributes(typeof(AttributesClass.ClassCleanupAttribute), true); if (classCleanupAttributes.Length == 1) { //InvokeCleanup(classObject, objMethod); Console.WriteLine("You are invoking the classCleanup method..."); Console.WriteLine(objMethod.Name + @"() "); objMethod.Invoke(classObject, null); } } Console.WriteLine(""); } }
模拟实现架构代码笔记:
1. 特性定义应该为public Sealed 以避免继承和便于命名空间外的类或函数调用(自定义特性通常情况下很少被继承,并且定义好的特性大多数情况下还是命名空间外引用的)
2. 定义特性时应该使用[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]来指定该特性是用于标记方法,类还是成员变量特性的。
3. 别调用的测试类DemoTest由于会被主调用函数调用也应该声明为public。
4. 约定测试程序集里所有方法种类一致便于管理.(倘若测试Assmbly里既有静态方法又有非静态方法的话,那么在主调用函数反射时必须考虑到不同种类的方法,invoke 时的不同,非静态方法必须得先实例化才能invoke)
5. 该架构里所有方法都是非静态的,主调用函数实现非静态方法必须得先实例化一个类,显然比较麻烦。 为什么不写成非静态的呢。(因为倘若用到某个类中的方法,必须默认得去调用Initialize和Cleanup函数[如果这些函数存在的话],如果用静态方法的话就必须的自己去判定查找调用这些方法,显然实现起来比较麻烦)
不足:
1 并没有完成对多限定条件下的查询方法
2 目前为止所有的测试方法必须不包含参数(包含参数的方法很容易实现,可以考虑在运行时XML传递参数)
3 PropertyDemoTest类结构不太清晰,可以考虑重构一下
4 可以增加更多的自定义特性完成更为复杂的操作
由于只是简单模拟框架,实现功能较为简单,更为复杂的功能可以以后再加,这个架构最大的好处是耦合度小,可扩展性强。
全部源码可去csdn下载,连接:http://download.csdn.net/detail/fl815824/4340631
很多优秀的架构其基本原理很相似,无非是在易用性和用户习惯或者考虑到成本等问题上增加或者裁减了某些特性功能。例如VS单元测试功能,LEAF,Nuint。这个自动化测试架构应该和NUint框架是一致的。另外VS中已经集成了单元测试的控件。
基本实现原理跟这个差不多少参看链接:http://hi.baidu.com/widebright/blog/item/04759058143725db9c82041b.html
利用.net自定义特性实现元数据扩展,可以为我们设计架构时添加新的思路和解决方法,不过读取元数据必将牵涉到反射机制而反射机制性能比较低。
示例代码参考链接:
/article/4624845.html
有关于反射相关信息参考以前写的笔迹和以下连接
http://msdn.microsoft.com/zh-cn/library/f7ykdhsy(v=VS.80).aspx
相关文章推荐
- 一个简单的自动化测试架构的实现(C#)
- 简介 WatiN是一个开源的用于Web测试自动化的类库,从watir中获得的灵感,使用C#开发。WatiN通过与浏览器的交互来实现自动化,使用起来具有轻便,简单的特点。目前最新版本为2.0,加入了对
- 简单的性能自动化测试架构设计和实现(pylot)-python
- sql server 关于表中只增标识问题 C# 实现自动化打开和关闭可执行文件(或 关闭停止与系统交互的可执行文件) ajaxfileupload插件上传图片功能,用MVC和aspx做后台各写了一个案例 将小写阿拉伯数字转换成大写的汉字, C# WinForm 中英文实现, 国际化实现的简单方法 ASP.NET Core 2 学习笔记(六)ASP.NET Core 2 学习笔记(三)
- C#真他妈神奇,一个函数都不用写就能实现一个简单的邮件发送工具
- 实现自动化测试,首先不是一个技术问题
- 收了100元辛苦费,写了一个最简单的C#ASP.NET的3层架构例子代码
- C#使用泛型数组简单实现一个列表List
- 简单分享一个轻量级自动化测试框架目录结构设计
- [C# 网络编程系列]专题十二:实现一个简单的FTP服务器
- C#实现一个功能简单的web浏览器
- 用C#实现一个简单的图书管理系统(课程设计)
- Xcode自带的instrument中的Automation实现自动化测试简单使用
- 简单代码实现C#中运行另外一个程序
- 一个小型的网站,比如个人网站,可以使用最简单的html静态页面就实现了,配合一些图片达到美化效果,所有的页面均存放在一个目录下,这样的网站对系统架构、性能的要求都很简单,随着互联网业务的不断丰富,网站
- 解决android自动化测试中锁屏问题-简单的实现
- 用python实现一个简单的测试用例
- C#借助API实现黑盒自动化测试工具的编写(转)
- WPF学习——制作一个简单的录入界面(2):用C#编程实现所有控件的功能
- 一个简单的AJAX实现,基于C#的ASP.Net,包括服务器端的程序代码