熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Delphi編程 >> 正文

Delphi中用TDD:一個簡單的實現

2013-11-11 21:04:45  來源: Delphi編程 

  最近因工作的關系又再次搞了一些時候的Delphi開發因為Java的影響也就開始思想如何在Delphi開發中用TDD的方法這篇文章就是要談談TDD在Delphi中的應用我想網上已有很多的文章談到這方面的話題我這篇也只是談談我自己的經驗而已

  那從何說起呢?用個具體的例子會更好的說明問題試想我們想開個動物繁殖中心不過我們現階段還沒有特定的動物先把這中心搞起來再說不過中心是離不開動物的我們就先定義個接口

  IAnimal = Interface

  procedure Mate

  procedure Eat

  procedure GiveBirth

  End

  這個接口定義了每種動物的三個基本功能Eat(吃) Mate(交配) GiveBirth(生產) 為了簡單起見我們只處理母的公的不在考慮之內有了接口我們就可以定義繁殖中心

  TAnimalCare= class

  private

  FIntf IAnimal

  public

  constructor Create(AnIntf IAnimal)

  procedure Reproduction

  end

  TAnimalCare 是處理繁殖的一個類它需要依靠IAnimal才可以繁殖不過它並沒有鎖定任何的動物

  所以在建立時需要注人一個基於IAnimal的類

  有了IAnimal TAnimalCare 我們需要個測試Project來對它們進行測試DUnit是Delphi的很好的單元測試工具如你用的是Delphi DUnit已經在裡面 如用的是早些的版本可在DUnit下載安裝

  建立好Test Project後我們可以加入下面的這個TestCase

  TestTAnimalCare = class(TTestCase)

  strict private

  FAnimalCare TAnimalCare

  public

  procedure SetUp override

  procedure TearDown override

  published

  procedure TestReproduction

  end

  在SetUp這裡需要個基於IAnimal的類才可以至到目前我們並沒有定義一個同時我們也不需要因為我們還沒有特定的動物那麼如何來滿足這條件以便測試能進行下去呢?這裡我們可以用到一種叫Mock的東西在Delphi可用PascalMock 大家可在這下載安裝後我們就可以定義個TAnimalMock

  TAnimalMock = class(TMock IAnimal)

  public

  procedure Mate

  procedure Eat

  procedure GiveBirth

  end

  procedure TestTAnimalCareSetUp

  begin

  FMock = TAnimalMockCreate

  FAnimalCare = TAnimalCare

  Create(FMock)

  end

  有了TAnimalMock我們已基本滿足了編譯的要求可以通過編譯是可以開始TDD的時候了讓我們先完善TestReproduction 先寫些期望然後verify看有沒有達到

  procedure TestTAnimalCareTestReproduction

  begin

  // Expectations

  FMockExpects(Mate

  FMockExpects(Eat

  FMockExpects(GiveBirth

  FAnimalCareReproduction

  FMockVerify(check

  end

  這些期望是很自然的交配(mate)營養(eat)是生產(GiveBirth)的必須條件否則是無法繁殖的我們跑一下測試失敗

  TestReproduction EMockVerifyException

  at  $BA

  check

  Unexpected call to GiveBirth() <—— Dont match expectations

  Expected

  Mate()

  Eat()

  GiveBirth()

  Called

  GiveBirth() <—— Dont match expectations

  為什麼?看看

  procedure TAnimalCareReproduction

  begin

  FintfGiveBirth

  end

  原來我們只調用GiveBirth而沒調用Mate() Eat() 不合我們的期望改成如下

  procedure TAnimalCareReproduction

  begin

  FIntFMate

  FIntFEat

  FintfGiveBirth

  end

  再跑下測試成功!

  總結

  用Dependency Injection 將基於IAnimal的類注入TAnimalCare 把有關IAnimal的一些具體的實現從TAnimalCare中分離出來

  用Mock來實現一個基於IAnimal的類以便測試

  IAnimal TAnimalCare碼如下

  unit MyObjects

  interface

  uses

  classes

  type

  IAnimal = Interface

  procedure Mate

  procedure Eat;
    procedure GiveBirth;
  End;

  TAnimalCare= class
  private
    FIntf : IAnimal;
  public
    constructor Create(AnIntf : IAnimal);
    procedure Reproduction;
  end;

  implementation

  { TAnimalCare }

  constructor TAnimalCareCreate(AnIntf: IAnimal);
begin
  inherited Create;
  FintF := AnIntf;
end;

  procedure TAnimalCareReproduction;
begin
  FIntFMate;
  FIntFEat;
  FintfGiveBirth;
end;

  end
測試碼如下

  unit TestMyObjects;

  interface

  uses
  TestFramework classes MyObjects PascalMock;
type

  TAnimalMock = class(TMock IAnimal)
  public
    procedure Mate;
    procedure Eat;
    procedure GiveBirth;
  end;

  TestTAnimalCare = class(TTestCase)
  strict private
    FMock : TAnimalMock;
    FAnimalCare: TAnimalCare;
  public
    procedure SetUp; override;
    procedure TearDown; override;
  published
    procedure TestReproduction;
  end;

  implementation

  procedure TestTAnimalCareSetUp;
begin
  FMock := TAnimalMockCreate;
  FAnimalCare := TAnimalCareCreate(FMock);
end;

  procedure TestTAnimalCareTearDown;
begin
  FAnimalCareFree;
  FAnimalCare := nil;
  FMockFree;
  FMock := nil;
end;

  procedure TestTAnimalCareTestReproduction;
begin
  // Expectations
  FMockExpects(Mate);
  FMockExpects(Eat);
  FMockExpects(GiveBirth);

  FAnimalCareReproduction;
  FMockVerify(check);

  end;

  { TAnimalMock }

  procedure TAnimalMockEat;
begin
  selfAddCall(Eat);
end;

  procedure TAnimalMockGiveBirth;
begin
  selfAddCall(GiveBirth);
end;

  procedure TAnimalMockMate;
begin
  selfAddCall(Mate);
end;

  initialization
  RegisterTest(TestTAnimalCareSuite);
end


From:http://tw.wingwit.com/Article/program/Delphi/201311/8431.html
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.