超级简单:一个超轻量级的测试平台

    有时候,在开发环境中测试核心业务职能,可能需要花很长而宝贵的时间。

    幸运地是有很多简单而且自动化的测试平台。尽管如此,这个操作却不会总是能提供预期的结果。有时,它需要人为进行检查和评价。

    此外,在一个大型项目中,编译几十个类,每一点变动是非常耗费时间和精力的,自动测试将不会达到预期的行为。OBP控制台测试框架是一个非常简单,轻量级的类库,它用于测试你的业务对象,但它没有一个像windows forms,web, silverlight 、WPF的图形界面。

    OBP控制台测试库的主要目的是:在将代码整合到相关项目中之前,检查它的核心业务功能。

  在测试类有下列行为:

    在运行时,通过自定义属性和反射找出测试类和测试方法

    提供测试人员提供一个简单菜单式的控制台的用户界面

    允许重复使用菜单(控制台上的)

    便利地显示的业务对象的集合,并能便利从中选择单独的业务对象进行测试。

  文章中的一些定义

    测试方法 :能通过执行一些动作来验证开发项目的行为、动作、过程。

    测试类 :包含一个或多个测试方法的类。它也可能还包含测试类成员来执行重叠测试。

    菜单 :是在控制台上显示一系列的活动,允许测试人员使用键盘调用一个给定的测试方法。

  结构:

   整个类库是建立在一个简单的类上:CustomConsoleTest。这个类完成以下行动:

   1、它使用反射浏览所有子类的方法并找出有“TestMethod”属性的方法。

   2、使用“TestMethod”属性,它能正确显示在菜单上使用的方法的名称。

       测试时,简化了业务对象集合的显示,以及简化在集合中选择单独的业务对象。

   3、为了进行测试,你需要实例化一个CustomConsoleTest子类(这个类是抽象的)和调用方法“Execute”方法。

   在这个简单的类中,神奇之处是一个测试类可以嵌入其他的测试类,执行父类中的测试方法能调用子类的Execute方法。因此,你能很快建立一个分层控制台菜单,用于在整合之前专注于核心业务功能的测试。

  实现:

  所有的测试类都要继承CustomConsoleTest。下面是构造函数:

CustomConsoleTest
 public CustomConsoleTest()
        {
            var t 
= this.GetType();
            
int i = 0;
            
string name = null;
            
// find the methods
            foreach (var m in t.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
            {
                
if (IsValidMethod(m, ref name))
                {
                    var item 
= new MethodItem(name, m);
                    _methods.Add(_menuKeys[i], item);
                    
++i;
                }
            }
        }

   当CustomConsoleTest子类被实例化,执行以下操作:

   1、使用反射去查找有自定义属性TestMethod的方法。

   2、当一个方法有TestMethod属性,它被添加到一个类名为MethodItem的集合,这个集合包含MethodInfo实例和方法的名称。

   一旦测试方法发现,它将显示在菜单上,允许测试人员通过键盘上的键调用的测试方法。

   为了完成这些,测试人员必须调用方法“Execute”的方法,这个方法浏览方法集合和在菜单上显示测试方法友好名称(如[TestMethod("List Machines")]中就显示List Machines)。

   为了重复的测试,因此能实现重复菜单,测试类可以嵌入其他测试类,调用测试方法也将调用嵌入类的"Execute"。代码如下:

Execute
 public void Execute()
        {
            
char c = '*';
            
while ((c != 'q'&& (c != 'Q'))
            {
                
foreach (var p in _methods)
                    Console.WriteLine(
"{0} - {1}", p.Key, p.Value.DisplayText);
                Console.WriteLine(
"q - Quit");
                Console.WriteLine();
                c 
= Console.ReadKey(true).KeyChar;
                
if (_methods.ContainsKey(c))
                    
try
                    {
                        var m 
= _methods[c];
                        m.Method.Invoke(
thisnull);
                    }
                    
catch (Exception ex)
                    {
                        Console.ForegroundColor 
= ConsoleColor.Red;
                        Console.WriteLine(
"An exception has occured when invoking the method {0}",
                            ex);
                    }
            }
        }

   为了方便地显示和选择集合中的项,我添加一个泛型函数来简化集合处理,这假设集合实现了通用接口IEnumerable<T>。 

DisplayCollection
protected void DisplayCollection<T>(IEnumerable<T> aCollection)
{
    
if (aCollection.Count() == 0)
        Console.WriteLine(
"No item in the collection");
    
int i = 1;
    _elts.Clear();
    
foreach (var e in aCollection)
    {
        Console.WriteLine(
"{0} - {1}", i, GetDescription(e));
        _elts.Add(i, e);
        
++i;                
    }
    Console.WriteLine();
}

   SelectItem方法使在控制台模式下选择测试方法更加容易:

代码
  protected T SelectItem<T>(IEnumerable<T> aCollection) where T : class
        {
            DisplayCollection
<T>(aCollection);
            
            
while (true)
            {
                Console.WriteLine(
"Type the element number or q to exit");
                var text 
= Console.ReadLine();
                
if ((text == "q"|| (text == "Q"))
                    
return null;
                
try
                {
                    
int index = Convert.ToInt32(text);
                    
if (_elts.ContainsKey(index))
                        
return (T)_elts[index];
                    
else
                        Console.WriteLine(
"The list does not contain that number, try again !");
                }
                
catch
                {
                    Console.WriteLine(
"Wrong value");
                }
            }
        }

   为了显示菜单,我将寻找到的测试方法放在MethodItem类中

代码
 class MethodItem
    {
        
internal MethodItem(string aDisplayText, MethodInfo aMethod)
        {
            DisplayText 
= aDisplayText;
            Method 
= aMethod;
        }

        
internal string DisplayText { getprivate set; }

        
internal MethodInfo Method { getprivate set; }
    }

 示例:

   将所有的功能展示在一个机器和零配件的示例中,应用程序包括两种类型的业务对象:Machine(机器)和SparePart(零配件)。

 

代码
class Machine : Asset
{
   //机器类中有添加零配件AddPart方法。CreateInstances静态的构建方法,零配件列表:List<SparePart>
    
internal void AddPart(SparePart aPart)
    {
        Parts.Add(aPart);
        AddWeight(aPart.Weight);
    }
    
    
public Machine(string aName)
        : 
base(aName)
    {
        Parts 
= new List<SparePart>();
    }
    
    
public static void CreateInstances()
    {
        Machines 
= new List<Machine>();
        
for (int i = 0; i < new Random().Next(10+ 1; i++)
            Machines.Add(
new Machine(string.Format("Machine{0}", i)));
    }
    
    
public static List<Machine> Machines
    {
        
get;
        
private set;
    }
    
    
public List<SparePart> Parts { getprivate set; }
}

 零配件类:

代码
class SparePart : Asset
{
    
public SparePart(Machine aMachine, string aName, double aWeight):
        
base(aName)
    {
        Machine 
= aMachine;
        Weight 
= aWeight;
        aMachine.AddPart(
this);            
    }
    
    
public static void CreateInstances()
    {
        Parts 
= new List<SparePart>();
        var random 
= new Random();
        
foreach(var m in Machine.Machines)
            
for (int i = 0; i < random.Next(5); i++)
            {
                var part 
= new SparePart(m, string.Format
                    (
"{0}-part{1}", m.Name, i),
                    random.NextDouble());
                Parts.Add(part);
            }
    }
    
    
public Machine Machine { getprivate set; }
    
    
public static List<SparePart> Parts
    { 
getprivate set; }
}

 要实现我的测试操作,我需要三个类:MachineTest测试Machine,PartTest测试spare部分,SoftwareTest中嵌入这两个的测试。

代码
/// <summary>
/// this class is used to test software
/// </summary>
class SoftwareTest : CustomConsoleTest
{
    
/// <summary>
    
/// machine test
    
/// </summary>
    private MachineTest _machineTest = new MachineTest();
    
    
/// <summary>
    
/// part test
    
/// </summary>
    private PartTest _partTest = new PartTest();
    
    [TestMethod(
"Machines")]        
    
private void ExecuteMachineTest()
    {
        _machineTest.Execute();
    }
    
    [TestMethod(
"Parts")]
    
private void ExecutePartTest()
    {
        _partTest.Execute();
    }
    
    
static SoftwareTest()
    {
        Machine.CreateInstances();
        SparePart.CreateInstances();
    }
}

 

代码
class MachineTest : CustomConsoleTest
{
    [TestMethod(
"List Machines")]
    
private void ListMachines()
    {
        DisplayCollection
<Machine>(Machine.Machines);
    }
    
    
protected override string GetDescription(object e)
    {
        
if(e is Machine)
        {
         var m 
= e as Machine;
         
return string.Format("Machine {0} | {1:0.00} | Parts : {2}",
             m.Name, m.Weight, m.Parts.Count);
        }
        
return base.GetDescription(e);
    }
}

  为了更精细显示的业务对象,我重写的方法GetDescription,它本身是以ToString方法为基础。

代码
class PartTest : CustomConsoleTest
{
    
protected override string GetDescription(object e)
    {
        
if (e is SparePart)
        {
            var p 
= e as SparePart;
            
return string.Format("Machine : 
                {0- {1}", p.Machine.Name, p.Name);
        }
        
return base.GetDescription(e);
    }
    
    
/// <summary>
    
/// selection
    
/// </summary>
    [TestMethod("Select A Part")]
    
protected void TestSelect()
    {
        var p 
= SelectItem<SparePart>(SparePart.Parts);
        
if (p != null)
            Console.WriteLine(
"You have selected the part {0}", p.Name);
    }
}

 总结:

    以我个人开发大型软件系统的经验,自动化测试是很好,但还往往不够,在非常特别的情况,要耗很多时间去测试。我的做法很重要一点是没有软件界面部分,在控制台项目中进行测试非常的快。

参考代码:/Files/zhuqil/TestBO.zip

参考原文:http://www.codeproject.com/KB/cs/SimpleConsoleTestClass.aspx

 



(全文完)


以下为广告部分

您部署的HTTPS网站安全吗?

如果您想看下您的网站HTTPS部署的是否安全,花1分钟时间来 myssl.com 检测以下吧。让您的HTTPS网站变得更安全!

SSL检测评估

快速了解HTTPS网站安全情况。

安全评级(A+、A、A-...)、行业合规检测、证书信息查看、证书链信息以及补完、服务器套件信息、证书兼容性检测等。

SSL证书工具

安装部署SSL证书变得更方便。

SSL证书内容查看、SSL证书格式转换、CSR在线生成、SSL私钥加解密、CAA检测等。

SSL漏洞检测

让服务器远离SSL证书漏洞侵扰

TLS ROBOT漏洞检测、心血漏洞检测、FREAK Attack漏洞检测、SSL Poodle漏洞检测、CCS注入漏洞检测。

posted @ 2010-02-02 10:53  麒麟  阅读(3280)  评论(10编辑  收藏  举报