有时候,在开发环境中测试核心业务职能,可能需要花很长而宝贵的时间。
幸运地是有很多简单而且自动化的测试平台。尽管如此,这个操作却不会总是能提供预期的结果。有时,它需要人为进行检查和评价。
此外,在一个大型项目中,编译几十个类,每一点变动是非常耗费时间和精力的,自动测试将不会达到预期的行为。OBP控制台测试框架是一个非常简单,轻量级的类库,它用于测试你的业务对象,但它没有一个像windows forms,web, silverlight 、WPF的图形界面。
OBP控制台测试库的主要目的是:在将代码整合到相关项目中之前,检查它的核心业务功能。
在测试类有下列行为:
在运行时,通过自定义属性和反射找出测试类和测试方法
提供测试人员提供一个简单菜单式的控制台的用户界面
允许重复使用菜单(控制台上的)
便利地显示的业务对象的集合,并能便利从中选择单独的业务对象进行测试。
文章中的一些定义
测试方法 :能通过执行一些动作来验证开发项目的行为、动作、过程。
测试类 :是包含一个或多个测试方法的类。它也可能还包含测试类成员来执行重叠测试。
菜单 :是在控制台上显示一系列的活动,允许测试人员使用键盘调用一个给定的测试方法。
结构:
整个类库是建立在一个简单的类上:CustomConsoleTest。这个类完成以下行动:
1、它使用反射浏览所有子类的方法并找出有“TestMethod”属性的方法。
2、使用“TestMethod”属性,它能正确显示在菜单上使用的方法的名称。
测试时,简化了业务对象集合的显示,以及简化在集合中选择单独的业务对象。
3、为了进行测试,你需要实例化一个CustomConsoleTest子类(这个类是抽象的)和调用方法“Execute”方法。
在这个简单的类中,神奇之处是一个测试类可以嵌入其他的测试类,执行父类中的测试方法能调用子类的Execute方法。因此,你能很快建立一个分层控制台菜单,用于在整合之前专注于核心业务功能的测试。
实现:
所有的测试类都要继承CustomConsoleTest。下面是构造函数:
当CustomConsoleTest子类被实例化,执行以下操作:
1、使用反射去查找有自定义属性TestMethod的方法。
2、当一个方法有TestMethod属性,它被添加到一个类名为MethodItem的集合,这个集合包含MethodInfo实例和方法的名称。
一旦测试方法发现,它将显示在菜单上,允许测试人员通过键盘上的键调用的测试方法。
为了完成这些,测试人员必须调用方法“Execute”的方法,这个方法浏览方法集合和在菜单上显示测试方法友好名称(如[TestMethod("List Machines")]中就显示List Machines)。
为了重复的测试,因此能实现重复菜单,测试类可以嵌入其他测试类,调用测试方法也将调用嵌入类的"Execute"。代码如下:
为了方便地显示和选择集合中的项,我添加一个泛型函数来简化集合处理,这假设集合实现了通用接口IEnumerable<T>。
SelectItem方法使在控制台模式下选择测试方法更加容易:
为了显示菜单,我将寻找到的测试方法放在MethodItem类中
示例:
将所有的功能展示在一个机器和零配件的示例中,应用程序包括两种类型的业务对象: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
=
; 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 {
get
;
private
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
=
; 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 {
get
;
private
set
; }
public
static
List
<
SparePart
>
Parts
{
get
;
private
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();
}
}
为了更精细显示的业务对象,我重写的方法GetDescription,它本身是以ToString方法为基础。
代码
class
PartTest : CustomConsoleTest
{
protected
override
string
GetDescription(
object
e)
{
if
(e
is
SparePart)
{
var p
=
e
as
SparePart;
return
string
.Format(
"
Machine :
{
}
-
{
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