极限编程的集成测试工具-Dunit



简介

极限编程(Xtreme Program)的测试理念是,在开发程序的之前或者同时就要编写出相应的测试程序,而不是象通常那样等到测试阶段再来编写测试程序。 当程序完成时,它的测试程序也应该已经完成。从软件工程的普遍规律来看,每修正一个bug的同时会以20%的几率引入新的bug。而XP的测试方式是, 每当修改Bug或者重构代码后都要重复测试所有的测试案例,以免在修改代码时引入新的Bug,只有经过测试的重构才是有效的重构。而且,所有测试案 例的测试应该是全自动的,可以无需操作人员的介入,不论案例是否通过都将自动完成全部的测试。(注意:即使我们不使用XP的开发方式,对系统能够进行集成测试仍然是一个很好的做法。)

 

XP的测试框架中最重要的组成部分是TestCase(测试案例),TestResult(测试结果)和TestSuite(测试组)。其中TestSuite可以嵌套包含其它的 TestSuite和TestCase,构成一个简单的Composite模式。也就是说XP的测试是结构化的,是分层次的,类似于一颗树,在测试过程中我们可以选择测 试其中某些部分。基于上述的理念,极限编程创始人之一Kent Beck编写了JUnit测试框架用于Java的测试。下面我们将要介绍的DUnit则是一个基于极 限编程(Xtreme Program)理论的Delphi和Kylix集成测试框架。DUnit是一个开放源码的项目,它的官方网址位于
。还要说明的一点是DUnit是白盒测试工具,和基于脚本控制的程序进行交互的黑盒测试工具(如TestComplete, WinRunner等)是不同的。

文档目录结构

下面是DUnit开发包的目录结构:

目录名称

说明

DUnit

 

 

src

DUnit源代码

 

doc

一些说明文档,还包括Time2Help生成Api帮助文档

 

Contrib

非核心的一些工具

 

 

XPGen

一个可以自动生成Test Case的工具。

 

tests

DUnit框架本身的测试案例

 

examples

 

 

 

cmdline

示范如何在控制台程序中使用DUnit

 

 

collection

一个类似于Java的容器类的Delphi类的代码以及它的测试代码。

 

 

registration

演示几种注册测试案例方法的例子

 

 

structure

组织测试代码的方法

 

 

 

diffunit

将测试案例放在独立的单元中的示例

 

 

 

sameunit

将测试案例代码和被测试的程序代码放在同一个单元中的示例

 

 

registry

一个建立读写注册表的工具及其测试案例建立的教程。

 

 

embeddable

示范如果将 GUITestRunner嵌入到其他界面中的示例

 

 

TListTest

为Delphi中的TList类编写的测试案例

环境配置

要想使用DUnit,必须将DUnit的路径添加到Delphi的单元搜索路径中。在Delphi IDE中点击菜单Tools | Environment Options, 然后在弹出的对话框中选中Library页面,添加路径到Library Path中。见下图示意:

 

创建测试案例

现在假设你是一个测试人员,你的研发队伍中有人写了一个计算阶乘的函数,函数采用递归实现,代码如下:

unit Utility;



interface



function Factorial(N:Word):Integer;



implementation



function Factorial(N:Word):Integer;

begin

  if N=0 then

    Result:=1

  else

    Result:=N*Factorial(N-1);

end;



end.

 

你的任务是测试这个函数是否真的能够给出阶乘运算结果。首先新建一个测试工程,取名为ProjectTests,
然后将默认创建的窗体从项目中删除,添加DUnit的测试框架代码,代码示意如下:

program ProjectTests;



uses

  TestFramework,

  Forms,

  GUITestRunner;



{$R *.RES}



begin

  Application.Initialize;

  GUITestRunner.RunRegisteredTests;

end.

 

然后是创建要测试的案例,每个测试案例都要定义为TTestCase的子类,TTestCase类定义在TestFramework.pas
单元中,现在新建一个单元,名为TestUnit,然后在Uses部分添加TestFramework,定义一个TTestCase的子类
TFirstTestCase类,同时我们还要添加测试方法TestFatorial(注意:通常定义测试方法的前缀为Test),代码
示意如下:

 unit TestUnit;



interface



uses

  TestFrameWork, Utility;



type



  TFirstTestCase = class(TTestCase)

  private



  protected

  published

    procedure TestFactorial;

  end;



implementation



{ TFirstTestCase }

procedure TFirstTestCase.TestFactorial;

begin

  Assert(Factorial(3)=6, '阶乘运算错误!');

end;



initialization

  TestFramework.RegisterTest('TestUnit Suite',  TFirstTestCase.Suite);

end.



注意,每增加一个TestCase,我们都要将其注册到测试框架中,这需要在initialization部分增加测试案例注册代码:

  TestFramework.RegisterTest('TestUnit Suite',  TFirstTestCase.Suite);

另外,可以注意到测试方法TestFactorial必须是Published存取级别的方法,同时该方法必须没有任何的参数定义,
这是由于Delphi的RTTI(运行时类型信息)机制的限制。TestFactorial方法使用Assert断言来检查阶乘函数的结果是否正确。

 下面我们就可以运行一下这个测试程序了,运行后会显示一个测试框架的GUI界面,如下图所示:

 

可以看到最上边的面板按层次关系列出了当前的测试案例,首先是TestSuite,然后是TestCase,最下面是测试方法。
每个节点前都有一个CheckBox,我们可以通过在测试案例前打勾来确定是否测试案例的范围。

点击界面上的 按钮来运行测试,运行后的结果如下:

我们会发现,每个节点前有一个带颜色的方块,当没有运行时,所有节点的方块都为灰色,表示没有被测试。运行测试后,
如果该测试通过的话,方块变为绿色表示成功。下面的面板会显示所有的失败和异常,同时每个错误都会有相应的描述信息。
在上下两个面板之间的进度条表示测试的进展和成功的比率。

 

下面我们增加一个新的测试,故意让阶乘函数计算10000的阶乘,这时函数会因为溢出而抛出异常,来看DUnit如何检查这种
错误:

procedureTFirstTestCase.TestFactorialLimit;

begin

  //Check函数会检查表达式是否为真

 Check(Factorial(10000)>1,'阶乘越界');

end;

 

运行结果示意图如下:

可以看到如果测试失败,方块就变为粉色,这时测试通过率降到了50%。

 

复合测试

 

前面的例子相对比较简单一些,下面我们考虑一个更复杂的场景。假设你觉得Delphi虽然提供了很多的字符串处理函数,
但是参数比较多,调用起来不是很方便,所以想创建一个TStringClass类,将常用的字符串函数封装起来。下面就是
TStringClass类的代码示意:

unitStringClass;

interface

usesSysutils;

 

type

 TStringClass=class(TObject)

 private

   FStr:string;

 public

    constructorCreate(AStr:String);

   //返回字符串的大写形式

   functionUpperCase:string;

   //返回字符串的小写形式

   functionLowerCase:string;

   //返回前后加引号的字符串形式

   functionQuotedStr:string;

 end;

 

implementation

 

{ TStringClass }

 

constructorTStringClass.Create(AStr:String);

begin

 FStr:=AStr;

end;

 

functionTStringClass.LowerCase:string;

begin

 Result:=SysUtils.LowerCase(FStr);

end;

 

functionTStringClass.QuotedStr:string;

begin

 Result:=SysUtils.QuotedStr(FStr);

end;

 

functionTStringClass.UpperCase:string;

begin

 Result:=SysUtils.UpperCase(FStr);

end;

 

end.

 

接下来我们写一个TStringTestCase类来进行测试,下面是类的代码:

 

unitTestStringUnit;

 

interface

 

uses

 TestFrameWork, StringClass;

 

type

 

 TStringTestCase =class(TTestCase)

 private

   FStringClass:TStringClass;

 protected

    procedureSetUp;override;

   procedureTearDown; override;

 published

    procedureTestUpperCase;

   procedureTestLowerCase;

   procedureTestQuotedStr;

 end;

 

implementation

 

{ TStringTestCase }

 

procedureTStringTestCase.SetUp;

begin

  inherited;

  FStringClass:=TStringClass.Create('Test');

end;

 

procedureTStringTestCase.TearDown;

begin

  inherited;

  FStringClass.Free;

end;

 

procedureTStringTestCase.TestLowerCase;

begin

 Self.CheckEquals('test', FStringClass.LowerCase,'LowerCase error!');

end;

 

procedureTStringTestCase.TestQuotedStr;

begin

 Self.CheckEquals('''Test''', FStringClass.QuotedStr,'QuotedStr error!');

end;

 

procedureTStringTestCase.TestUpperCase;

begin

 Self.CheckEquals('TEST', FStringClass.UpperCase,'UpperCase error');

end;

 

initialization

 TestFramework.RegisterTest('TestStringUnit Suite', TStringTestCase.Suite);

end.

 

可以看到这个测试类同前面的TFirstTestCase类最大的不同之处在于TStringTestCase重载了TTestCase
基类的两个重要方法SetUp和TearDown,这两个方法类似于Contructor和Destructor,每次执行测试过程
前,SetUp会被调用,在执行完测试过程后,TearDown方法会被调用。我们可以在SetUp过程创建用于测
试的TStringClass类的实例,并在TearDown方法中释放TStringClass的实例,以避免在测试中反复构造
和释放TStringClass类所造成的不必要的系统开销。

另外可以看到在TStringTestCase的测试方法中,我使用了CheckEquals来检查测试是否通过,TTestCase
类本身还提供了很多类似于Check和CheckEquals的检查方法,具体使用可以参考API文档,这里就不赘述了。

 

重复测试

 

在实际开发过程中,我们经常会碰到一些资源泄漏的Bug(画刷,字体,句柄和内存没有释放),它们在程序
最开始的几次运行的时候可能不会暴露问题,而是在几十次、上百次运行之后才会把相应的资源消耗光,那
么如何使用DUnit来测试这类的问题呢?

 

如果是只需要运行5,6次就会暴露的问题,我们可以在运行测试程序时,多点几次运行按钮来重复测试,但是
如果需要几十遍甚至更多遍测试才能发现的问题,显然靠人手去点是不切实际的。DUnit考虑到了这点,因此
在TestExtensions.pas单元中提供了一个特殊的TRepeatedTest类来完成这项工作。下面是一个内存泄漏的例
子,在我的机器上,执行10次以上就会无法通过测试,代码示意如下:

unitTestLeakUnit;

interface

uses

 TestFrameWork, TestExtensions, SysUtils;

 type

  TLeakTestCase =class(TTestCase)

 private

   protected

    procedureAllocateMem;

 published

    procedureTestLeak;

 end;

 

implementation

 

{ TLeakTestCase }

 

procedureTLeakTestCase.AllocateMem;

var

 Handle: Pointer;

begin

 GetMem(Handle, 100000000);

end;

 

procedureTLeakTestCase.TestLeak;

begin

 Self.CheckException(AllocateMem, EOutOfMemory,'Memory leak');

end;

 

initialization

 TestFramework.RegisterTest('TestLeakUnit Suite',

    TRepeatedTest.Create(TLeakTestCase.Suite, 100));

end.

 

从代码可以看到,使用TRepeatedTest类很简单,只需要将需要重复运行的TestCase的Suite传递给
TRepeatedTest类的构造函数,同时指定要重复执行的次数就可以了,这是一个装饰(Decorator)模式的典型应用。

  TestFramework.RegisterTest('TestLeakUnit Suite',

TRepeatedTest.Create(TLeakTestCase.Suite, 100));

 

调整层次关系

 

从前面例子中我们可以看到测试案例的组织是有层次的,但是我们现在生成的默认的TestSuite都是只包含一个
TestCase,那么有时很可能需要将内容相近的测试放在同一个TestSuite下面,TestSuite下面既包含多个TestCase,
也包含子TestSuite,那么如何来做到呢?

 

下面修改TestUnit单元的Initialization部分的代码,将TStringTestCase注册在TFirstTestCase的TestSuite下面,
同时将TLeakTestCase的TestSuite也注册在TFirstTestCase的TestSuite下面,代码示意如下:

 

需要uses TestExtensions;第三个是多层测试,用于将类似的接口集中在一起测试。需要定义var ParentSuite,ChildSuite :TTestSuite;

 

initialization

//  TestFramework.RegisterTest('TestUnit Suite',

//    TFirstTestCase.Suite);

begin

 ParentSuite := TTestSuite.Create('Parent Suite');

  ChildSuite := TTestSuite.Create(' Child Suite');

  ParentSuite.AddTests(TFirstTestCase);

  ParentSuite.AddTests(TStringTestCase);

  ChildSuite.AddTest(TRepeatedTest.Create(TLeakTestCase.Suite, 100));

  ParentSuite.AddSuite(ChildSuite);

 

  TestFramework.RegisterTest(ParentSuite);

end;

 

另外注意要将其他几个测试单元的Initialization部分代码注释掉,运行后的示意图如下:

 

控制台模式的测试

 

现代软件工程方法,包括极限编程,都非常强调每日构建,持续集成,而如果每次构建系统都是由人手工完成的话,
成本比较高,效率比较低,同时非常容易出错,因此人们普遍采用自动批处理、Make文件、或者类似于Java Ant
的构建工具来创建运行版本。而创建一个可靠的程序运行版本的前提条件就是在创建前,程序应该能够通过所有
的测试。

 我们前面讲的测试程序都是基于GUI的,需要手工去运行测试用例,人工判断程序是否通过了所有的测试项目,
这显然无法做到完全的自动化。为此DUnit提供了另外一种运行方式,那就是在控制台模式下运行测试用例。
虽然在控制台模式下,测试案例程序不再有美观的界面和灵活的测试范围控制选项,但它可以无需人的参与而
自动运行全部的测试案例,如果有任何一个测试用例在测试过程中出现错误,DUnit将会返回一个非0的错误码
(数值为所有失败的错误数加上发生的异常数),这使得控制台测试程序很适合放在一个make文件或者应用于
自动测试过程中。将控制台的测试程序加入到批处理后,后续的程序可以根据退出码判断前面的测试是否通过,
从而决定是否继续执行后续的版本创建的工作了,这样就可以做到构建过程的完全自动化了。

 

要想将我们前面写的测试程序改为在控制台下运行是非常简单的,只要在ProjectTests.dpr文件中加入
{$APPTYPE CONSOLE}编译指令告诉Delphi生成控制台程序,同时添加一些判断代码就可以了,修改后的代码示意如下:

{$APPTYPE CONSOLE}

 

programProjectTests;

 

uses

 TestFramework{$IFDEF LINUX},

  QForms,

  QGUITestRunner{$ELSE},

  Forms,

  GUITestRunner{$ENDIF},

  TextTestRunner,

  TestUnitin'TestUnit.pas',

  StringClassin'StringClass.pas',

  TestStringUnitin'TestStringUnit.pas',

  TestLeakUnitin'TestLeakUnit.pas';

 

{$R *.RES}

 

begin

 Application.Initialize;

 

 ifSystem.IsConsole then

   TextTestRunner.RunRegisteredTests

 else

   GUITestRunner.RunRegisteredTests;

end.

 

在控制台模式下,DUnit会使用TextTestRunner来运行注册的测试,在GUI方式下会使用GUITextRunner来运行测试,
如果我们想要切换回GUI模式,只要将{$APPTYPE CONSOLE}指令注释掉就可以了。在控制台测试程序运行时,DUnit
会在每个测试运行时在控制台上输出一个点,如果在测试中发生了错误,它会输出字母F表示测试失败,输出字母E
表示测试中发生了一个预期外的异常。

 

另外DUnit的控制台程序也可以在控制台下启动GUI方式的测试,DUnit的Tests目录下的UnitTests.dpr中提供了这样
一个例子,这个程序通过判断控制台程序运行的选项决定运行文本的测试还是GUI的测试,代码示意如下:

 

begin

  ifFindCmdLineSwitch('text-mode', ['-','/'], true)then

   TextTestRunner.RunRegisteredTests(rxbHaltOnFailures)

 else

  begin

   Application.Initialize;

    Application.Title :='DUnit Tests';

   // RunRegisteredTests class methods are recommended

   TGUITestRunner.RunRegisteredTests;

 end;

end.

 

对GUI界面控制的测试

 

前面我们讲到的例子都是对非可视化的类进行测试,而Delphi最重要的功能之一就是能够通过拖放的方式快速生成非常
专业的界面,在国内外Delphi也被广泛的应用于前台界面程序的开发上。因此对于界面的控制操作,如TabOrder的布局、
界面的输入框是否正确地初始化了、界面是否能够响应某些快捷方式等等也就成为我们测试中很重要的一部分内容。
对于GUI的测试,我们要建立的TestCase需要从GUITesting.pas单元中的TGUITestCase基类继承,而不应该是从TTestCase
 类继承了。假设现在有这样系统登录对话框,它有两个标签,两个输入框,和两个按钮,见下图示意:

 

 

对于登录界面的测试要求是:当显示时,界面会先将焦点定位于用户名前的输入框,同时界面组件的TabOrder
顺序是先从上向下,然后从左到右,也就是说,用户名的TabOrder应该为0,密码输入框的TabOrder为1,确定
按钮的TabOrder为2,取消按钮的TabOrder为3。同时按下快捷键Enter后,将关闭对话框。

 

根据上面的测试要求实现的TestCase的代码示意如下:

 

unitTestDialogUnit;

 

interface

 

uses

 TestFrameWork, TestForm, Forms, Windows, Controls, GUITesting;

 

type

 

 TDialogTestCase =class(TGUITestCase)

 private

   FDialog:TFormTest;

 protected

    procedureSetUp;override;

   procedureTearDown; override;

 published

    procedureTestTabOrder;

   procedureTestKey;

 end;

 

implementation

 

{ TDialogTestCase }

 

procedureTDialogTestCase.SetUp;

begin

  inherited;

  FDialog:=TFormTest.Create(nil);

  GUI:=FDialog;

  FDialog.Show;

end;

 

procedureTDialogTestCase.TearDown;

begin

 GUI:=nil;

  FDialog.Free;

 inherited;

end;

 

procedureTDialogTestCase.TestKey;

begin

 FDialog.Edit1.SetFocus;

  Self.EnterKey(VK_RETURN);

  Check(FDialog.Visible=false,'Form Closed?')

end;

 

procedureTDialogTestCase.TestTabOrder;

begin

 CheckFocused('Edit1');

  Tab;

  CheckFocused('Edit2');

  Tab;

  CheckFocused('Button1');

  Tab;

  CheckFocused('Button2');

end;

 

initialization

 TestFramework.RegisterTest('TestDialogUnit Suite',

    TDialogTestCase.Suite);

end.

 

对代码进行一下说明,为了能对登录界面进行测试,我们首先在类的SetUp方法中建立起对话框的实例,并将实例赋值
给类的GUI属性。运行测试时,DUnit会按照类方法定义的顺序先执行TestTabOrder方法来判断TabOrder是否正确设定
了,首先调用基类TGUITestCase的CheckFocused方法检查Edit1是否在界面显示后最先获得了焦点,如果测试通过就
调用基类的Tab方法来执行焦点遍历,来检查TabOrder的顺序是否正确。接下来是执行TestKey方法,这里我先把焦点
定在Edit1上,然后调用基类的EnterKey输入回车键,如果窗体正确关闭的话,最后检查窗体是否可见。

 

辅助工具

 

为了简化编写测试案例的工作量,这里我将介绍一下如何使用Paul Spain编写的DUnit plug-in for Delphi向导来
简化工作量。向导可以在随书的光盘上找到,向导的安装程序会自动在Delphi IDE的主菜单上添加DUnit菜单。
DUnit菜单有两个创建测试案例的菜单:

  1. New Project...命令将会创建一个新的DUnit的项目的模板代码。
  2. New TestCase...命令将会创建一个新的DUnit的测试案例的模板代码。

新建项目

执行New Project...命令后,向导将会显示下面的对话框:

如果当前IDE中打开的项目名为Msg.dpr,向导会建议测试项目名称为Msg+Tests.dpr,同时我们可以修改Project Path
中建议的项目保存路径为我们指定的任意路径。设定好选项后,按下Enter键后,向导将会自动生成代码模版,
代码示意如下:

// Uncomment the following directive to create a console application
// or leave commented to create a GUI application...
// {$APPTYPE CONSOLE}

program MsgTests;

uses
  TestFramework{$IFDEF LINUX},
  QForms,  QGUITestRunner {$ELSE},
  Forms,  GUITestRunner  {$ENDIF},
  TextTestRunner;

{$R *.RES}

begin
  Application.Initialize;
{$IFDEF LINUX}
  QGUITestRunner.RunRegisteredTests;
{$ELSE}
  if System.IsConsole then
    TextTestRunner.RunRegisteredTests
  else
    GUITestRunner.RunRegisteredTests;
{$ENDIF}

end.

光有测试项目还不够,我们还要添加测试案例(Test Case)。选中DUnit | New TestCase...菜单,会显示创建TestCase
的对话框,示意如下:

注意,该向导默认建议的UnitPath是项目的路径再加一个dunit(见图中的Unit Path输入框)。这里我们删除结尾的
”dunit"”字符串,同时禁止Add to TestCase “uses” clause选项。按下Enter键后会生成如下的Test Case模版代码:

unit MsgTestsTests;

interface

uses
  TestFrameWork;
type
  TMsgTestsTests = class(TTestCase)
  private
  protected
  //   procedure SetUp; override;
  //   procedure TearDown; override;
  published
  // Add test methods here...
  end;

implementation

initialization
  TestFramework.RegisterTest('MsgTestsTests Suite',
    TMsgTestsTests.Suite);
end.

注意在生成代码前,会显示下面的对话框(这是这个向导的一个bug),我们直接选择Cancel就可以了。

除了DUnit Plugin之外,DUnit本身提供了一个XPGen的工具,XPGen通过使用递归下降的代码解析器分析Delphi单元文件
中的类定义,自动生成测试用例骨架代码。

XP的使用非常简单,先用Delphi打开.."Contrib"XPGen目录下的XPGen.dpr,编译运行后,将显示下面界面:

执行菜单命令File | Open,打开前面我们写的StringClass.pas单元,XPGen会自动生成下面的代码:

unitTest_StringClass;

 

interface

 

uses

 TestFramework,

  SysUtils,

  StringClass;

 

type

 

 CRACK_TStringClass =class(TStringClass);

 

  Check_TStringClass =class(TTestCase)

 public

    proceduresetUp;override;

   proceduretearDown; override;

 published

    procedureVerifyUpperCase;

   procedureVerifyLowerCase;

   procedureVerifyQuotedStr;

 end;

 

functionSuite: ITestSuite;

 

implementation

 

functionSuite: ITestSuite;

begin

 result := TTestSuite.Create('StringClass Tests');

 

  result.addTest(testSuiteOf(Check_TStringClass));

end;

 

procedureCheck_TStringClass.setUp;

begin

end;

 

procedureCheck_TStringClass.tearDown;

begin

end;

 

procedureCheck_TStringClass.VerifyUpperCase;

begin

 fail('Test Not Implemented Yet');

end;

 

procedureCheck_TStringClass.VerifyLowerCase;

begin

 fail('Test Not Implemented Yet');

end;

 

procedureCheck_TStringClass.VerifyQuotedStr;

begin

 fail('Test Not Implemented Yet');

end;

 

end.

 

之后我们就可以将生成的代码复制到Delphi中,然后将其保存起来。如果有很多要测试的类的话,XPGen无疑将极大的
减轻我们的工作量。

总结

在本文中我们探讨了如何使用DUnit来实现持续测试,持续集成。DUnit虽然不一定是保证软件质量的万灵丹,但是它确
实是一个很好的工具。相信经过大量实践,我们一定能够从中受益的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第1章 com部分 1.1 activex部分 1.1.1 activex控件之消失的事件 1.1.2 创建acfivex控件之高级编辑界面 1.1.3 数据库明了的acfivex控件 1.2 基于com的office开发 1.2.1 office自动化编程 1.2.2 创建office2000插件 1.3 基于com的数据库开发 1.3.1 adox的数据库开发 1.3.2 sqlserver-dmo数据库开发 1.3.3 ole结构化存储及其在公文包型数据库中的应用 第2章 shell部分 2.1 外壳扩展 2.1.1 搜索扩展 2.1.2 文件飞跃提示扩展 2.1.3 拖放控制扩展 2.1.4 命名空间扩展 2.1.5 实现autocomplete 2.1.6 属性页扩展 2.1.7 外壳执行操作记录器 2.2 未经公开的外壳奥秘 2.2.1 pltemldlist的基本概念 2.2.2 用外壳接口对系统进行管理 第3章 ide扩展部分 3.1 opentoolsapl简介 3.2 helloworld 3.3 消息通知器 3.4 将winamp集成delphi中 3.5 自动规范控件前缀命名的专家 3.6 to-dolist的增强 第4章 ie扩展部分 4.1 ie菜单扩展 4.2 ie按钮扩展 4.3 阻断弹出式广告的bho 4.4 ie右键菜单扩展 4.5 ie下载扩展 4.6 创建3721样式的google搜索扩展 4.7 ie异步可插入协议扩展 4.8 创建可自动填表的ie面板插件 第5章 vcl深度探索 5.1 action开发之七种武器 5.2 vcl拖放高级应用 5.3 高级停靠技术的实现 5.4 面向对象的界面复用技术 5.5 vcl中的容器类 5.6 所见即所得的delphiweb开发利器--intraweb开发指南 5.7 基于bold的uml模型驱动的数据库应用开发 5.7.1 object rdbms mapping原理简介 5.7.2 使用bold开发数据库应用 5.7.3 bold的代码迭代开发 第6章 delphi与设计模式 6.1 使用delphi实现设计模式 6.1.1 工厂模式 6.1.2 单例模式(singleton) 6.1.3 建造模式(builder) 6.1.4 原型模式(prototype) 6.2 结构模式 6.2.1 适配器模式(adapter) 6.2.2 合成模式(composite模式) 6.2.3 装饰模式(decorator模式) 6.2.4 门面模式(faqade模式) 6.2.5 桥模式(bridge模式) 6.2.6 代理模式(proxy) 6.2.7 享元模式(flyweight模式) 6.3 行为模式 6.3.1 策略模式(strategy模式) 6.3.2 模板模式(template method模式) 6.3.3 责任链模式(chain of responsibility模式) 6.3.4 观察者模式(observer模式) 6.3.5 命令模式(command模式) 6.3.6 备忘录模式(memento模式) 6.3.7 迭代子模式(iterator模式) 6.3.8 访问者模式(visitor模式) 6.3.9 调停者模式(mediator模式) 6.3.10 状态模式(state模式) 第7章 工具篇 7.1 极限编程集成测试工具-dunit 7.2 性能分析工具gpprofile 7.3 内存泄漏清道夫--memproof 7. 4 codesite应用指南

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值