Ana içeriğe atla

Zengin Yedek Kulubesi ve Interfaceler IV (Hatta TDD I)

Eski yazılarımızda Zengin Yedek Kulubesi adı altında üzerine gittiğimiz bir konu vardı. Amacımız tek programla birden fazla veritabanını desteklemekti. Bunun için çeşitli yöntemler üzerinde durmuş dbexpress ile de ufak bir örnek yapmıştık. Bu konunun ardından Interface'ler konusuna girip birkaç yazıda bu konuyla ilgili yazmıştık. Şimdi ise interfaceler sayesinde zengin yedek kulubesi oluşturmanın bir başka yolunu -bence en iyisi- göreceğiz. Interfacelerin temel varoluş şeklini hatırlarsak neyi nasıl yapacağımızı daha kolay anlama şansımız olabilir. Interfaceler sadece "Ne" sorusuna cevap veriyolarlardı. "Nasıl" sorusuna ise cevap vermiyorlardı. Bizde bu nimetten yararlanarak arabirim kodu üzerinde minumum oynama yaparak programımıza birden çok veritabanı ile çalışma esnekliğini kazandırmış olacaz. Toparlarsak; mantık şu şekilde olacak.
//Yeni Kayıt Ekleme İşlemi
Interface.Ad := 'Ahmet'
Interface.Soyad:= 'Çakar'
Interface.Ekle;
ShowMessage('kayıt eklendi');
Peki burdaki interface neyin interfaci veya neye atıfta bulunuyor. Interface.Ekle dediğimiz zaman hangi sınıfın ekle metodu çalışıyor? "veritabanı olarak paradox kullanmak istiyorum" düğmesine tıklandığında çalışan kod
Interface :=TParadox.Create(Database);
Eğer programın paradox veritabanını kullanmasını istiyorsak yukarıdaki gibi Interface nesnemize TParadox sınıfına ait bir nesneyi atıyoruz eğer programın Access veritabanını kullanmasını isteseydik bu sefer Interface :=TAccess.Create(Database); gibi bir satır yazmamız gerekecekti. Aynı şekilde programın Oracle kullanmasını isteseydik Interface :=TOracle.Create(Database); yazmamız kafi olacaktı. Peki bunun avantajı ne olacak ? Biz hangi veritabanını kullanırsak kullanalım yukarıda yazdığımız "Yeni Kayıt Ekleme İşlemi" metodundaki kodlarımızın hiçbirisi etkilenmeyecek. Oradaki kodlar Oracle seçmisek Oracle'a göre, Access seçmişsek Access'a göre , Firebird seçmiçsek Firebird'e göre sorunsuz bir şekilde çalışacaktır. Dezavantajı Nedir? Çok fazla kod yazmanız gerekecek. Yani kaç tane veritabanına destek vermek istiyorsanız o kadar Interface.Ekle; metodu yazmak zorunda kalacaksınız. Diyelim ki 3 tane veritabanına destek vermek istiyorsunuz. Access, Firebird ve Oracle. Bu en az 3 tane sınıfınız olacak demektir ve her sınıfın kendi Ekle metodunu da yazmanız gerekiyor demektir. Gerçi bu sınıfların içerisinde dbexpress, ado gibi teknolojileri kullanıp tek bir ekle metoduylada bu iş çözülebilir gibi olsada bana göre en güvenli ve en bağımsız çözüm yolu herbirini ayrı ayrı yazmaktır. Hepsini ayrı ayrı yapmanız size tam bir bağımsızlık kazandırır. Burda yapacağımız örneğin içeriği basitçe şu şekilde olacak. Örneğimiz iki veritabanını destekleyecek. Paradox ve Access. Üzerinde işlem yapacağımız tablo ise çok basit bir tablo. Tablonun alanları aşağıdaki gibi : KISILER TABLOSU : ID: Integer AD: Karakter SOYAD : Karakter Bu tabloyu hem paradoxta hem de access te oluşturduktan sonra bu tablolara erişecek iki sınıf tanımladım. TPrdxKisiler = Paradoxta oluşturulmuş olan kişiler tablosu üzerinde işlem yapacak olan sınıfımız TAccessKisiler = Accessta oluşturulmuş olan kişiler tablosu üzerinde işlem yapacak olan sınıfımız İki nesneninde çok fazla ortak yönü olduğundan bu nesleri bir ata nesneden türetmeyi tekrarlanan kod sayısını azaltmak açısından uygun gördüm ve bu nedenle her iki nesneyi de TAtaKisiler adlı bir sınıftan türettim. Interfacei uygulayan nesnede zaten bu nesne.... Kısaca dördü(Interface, Ata nesne ve diğer iki türetilmiş nesne) arasındaki ilişkiyi şu şekilde özetleyebiliriz. Diğer bir önemli hususta bu uygulamanın DUnit ile birim testlerinin yapılıyor olması. Yani sınıflarımızda yer alan Ekle, Düzenle, Sil gibi metodların doğru çalışıp çalışmadığını test eden kodlarımız var. TDD Üzerine adlı kısımda konuyla ilgili daha ayrıntılı bilgi bulabilirsiniz. Şimdi en başa geri dönelim. Veritabanımızda 3 tane alan bulunuyor. ID, AD ve SOYAD. İlk önce Interfacein bu alanları bir şekilde karşılaması gerekiyor. Yapısı gereği içeresinde her hangi bir değişken barındıramadığından bu alanları property olarak tanımlamamız gerekiyor. Değerleri okumak ve set etmek içinde yine birer tane prosedür ve fonksiyona ihtiyacımız olacak. E tabi birde Ekle, sil ve güncelle metodlarımız olacak. Interfacein oluşturulduğu kod aşağıdaki şekilde.
   IData = Interface
   ['{D1332F05-2543-42DB-9267-401304481BC1}']
     function  GetID():Integer;
     Procedure SetID(Const Value : Integer);
     function  GetAd():String;
     Procedure SetAd(Const Value : String);
     function  GetSoyAd():String;
     Procedure SetSoyAd(Const Value : String);

     property  ID:Integer read GetID write SetID;
     property  Ad:String read GetAd write SetAd;
     property  Soyad:String read GetSoyad write SetSoyad;

     procedure Ekle;
     procedure Sil;
     procedure Guncelle;

   end;
Sırada bu interfaci kullanan ve asıl kullanmak istediğimiz nesnelere atalık edecek olan TAtaKisiler sınıfının tanımı...
  TAtaKisiler = class(TInterfacedObject,IData)
  private
    fID:Integer;
    fAd:String;
    fSoyad:String;
    procedure SetID(const Value: Integer);
    function  GetID: Integer;
    function  GetAd: String;
    function  GetSoyad: String;
    procedure SetAd(const Value: String);
    procedure SetSoyad(const Value: String);
    { Private declarations }
  public
  constructor Create();virtual;abstract;
  property ID:Integer read GetID write SetID;
  property Ad:String read GetAd write SetAd;
  property Soyad:String read GetSoyad write SetSoyad;

  procedure Ekle;virtual;abstract;
  procedure Sil;virtual;abstract;
  procedure Guncelle;virtual;abstract;
    { Public declarations }
  end;
//

Bu sınıfın diğer sınıfların (TPrdxKisiler,TAccessKisiler) ortak bazı alan ve metodlarını içerdiği için çalışma sırasında her hangi bir şekilde bir örneğinin oluşturulmasını istemiyorum çünkü kendisi tek başına her hangi bir anlam ifade etmeyen bir sınıf. Bu yüzden Create yapılandırıcısını abstract anahtarıyla soyut hale getiriyorum. (constructor Create();virtual;abstract;) Eğer bu sınıfa ait bir nesne oluşturmak isterseniz Delphi bunu kabul etmez ve oluşturmaz. Her nesnede ortak olan alan ve metodları burda tanımlıyorum fakat her metodu diğer nesneler kendilerine göre yeniden düzenlemeleri gerektiğinden metod isimlerinin sonuna abstract anahtarını eklemeyi unutmuyorum. ve nihayetinde işte karşımızda kullanacağımız asıl sınıflardan biri....
  TPrdxKisiler = class(TAtaKisiler)
  private
    fDatabase : TDatabase;
    fQuery:TQuery;
    { Private declarations }
  public
  constructor Create(DataBase:TDatabase);reintroduce;
  destructor Destroy; override;
  procedure Ekle;override;
  procedure Sil;override;
  procedure Guncelle; override;
    { Public declarations }
  end;
bu da bir diğeri....
  TAccessKisiler = class(TAtaKisiler)
  private
    fAdoConnection : TAdoConnection;
    fQuery:TAdoQuery;
    { Private declarations }
  public
  constructor Create(AdoConnection:TAdoConnection);reintroduce;
  destructor Destroy; override;
  procedure Ekle;override;
  procedure Sil;override;
  procedure Guncelle; override;
    { Public declarations }
  end;
Private alanında tanımladığım nesnelerin tipine ve Create yapılandırıcısındaki parametre tipine dikkat edin. Gövde metodlarının hepsini buraya yazmayacam ama örnek olması için sadece TPrdxKişiler sınıfının metod gövdesini buraya ekliyorum.
{ TPrdxKisiler }

constructor TPrdxKisiler.Create(DataBase: TDatabase);
begin
 inherited;
 fDatabase :=DataBase;
 fQuery :=TQuery.Create(nil);
 fQuery.DatabaseName :='SADODATA';
end;

destructor TPrdxKisiler.Destroy;
begin
  FreeAndNil(fquery);
end;

procedure TPrdxKisiler.Ekle;
begin
fQuery.Close;
fQuery.SQL.Clear;
fQuery.SQL.Add('Insert Into KISILER (AD,SOYAD) '+#13+
               'Values (:AD,:SOYAD)');
fQuery.Params[0].AsString := fAd;
fQuery.Params[1].AsString := fSoyad;
fQuery.ExecSQL;
end;



procedure TPrdxKisiler.Guncelle;
begin
fQuery.Close;
fQuery.SQL.Clear;
fQuery.SQL.Add('Update KISILER  Set AD = :AD,'+#13+
               'SOYAD = :SOYAD Where ID = :ID');
fQuery.Params[0].AsString := fAd;
fQuery.Params[1].AsString := fSoyad;
fQuery.Params[2].AsInteger := fID;
fQuery.ExecSQL;

end;





procedure TPrdxKisiler.Sil;
begin
fQuery.Close;
fQuery.SQL.Clear;
fQuery.SQL.Add('Delete From KISILER Where ID = :ID');
fQuery.Params[0].AsInteger := fID;
fQuery.ExecSQL;
end;

Sıra geldi bunları kullanmaya... Formun üzerinde iki tane düğme var. Paradox kullanmak isteyen birisi "Paradox kullanmak istiyorum" adlı düğmeyi, Access kullanmak isteyen birisi ise "Access Kullanmak istiyorum" adlı düğmeyi tıklıyor. Bunun yanında kayıt silmek , güncellemek ve eklemek içinde 3 adet düğme bulunuyor. Tabi birde verilerin girilebileceği editler. Test etmek amacıyla sol tarafa iki adet grid yerleştirdim. Düğmlere tıkladıktan sonra bu gridlerden işlemlerin başarılı bir şekilde olup olmadığını burdan kontrol ediyorum. Interfacei formun public bir alanında Data:IData şeklinde tanımladıktan sonra ilgili düğmelerde interface uygun değerleri aktarıyorum.
procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
Data :=TPrdxKisiler.Create(Database1);
end;

procedure TForm1.SpeedButton2Click(Sender: TObject);
begin
 Data :=TAccessKisiler.Create(ADOConnection1);
end;
Ekle, sil, Düzenle düğmelerinin kodları ise şu şekilde...
procedure TForm1.Button1Click(Sender: TObject);
begin
Data.Ad := edit2.Text;
Data.Soyad:=edit3.Text;
Data.Ekle;
ShowMessage('kayıt eklendi');

end;

procedure TForm1.Button2Click(Sender: TObject);
begin
Data.ID := StrToInt(edit1.Text);
Data.Ad := edit2.Text;
Data.Soyad:=edit3.Text;
Data.Guncelle;
ShowMessage('kayıt güncellendi');

end;

procedure TForm1.Button3Click(Sender: TObject);
begin
Data.ID := StrToInt(edit1.Text);
Data.Sil;
ShowMessage('kayıt silindi');

end;
Programa yeni bir veritabanı desteği eklemek istediğinizde yapmanız gereken nedir? TPrdxKisiler gibi bir sınıf daha oluşturmak (mesela TFirebirdKisiler), programa "Firebird Kullan" başlıklı bir buton eklemek ve butonun koduna Data :=TFirebirdKisiler.Create(IBDatabase1); yazmak. Hepsi Bu. Aslında testler bana göre daha ilginç ama testleri şu an için buraya koymaya üşeniyorum. Kaynak kodu indirdiğiniz zaman DUnit klasörü altındaki test kodlarına bakmayı da unutmayın. Düşüncelerinizi de burda belirtirseniz çok sevinirim. //edit: test kodlarını yorum bölümüne ekledim ÖRNEK UYGULAMAYI İNDİRMEK İÇİN BURAYA TIKLAYIN. Bu arada RemObjects software'in Data Abstract adlı ürününe de bir gözatın...

Yorumlar

Sadettin POLAT dedi ki…
yorum olarak eklemekte bi zarar yok :)



unit SiniflarTests;

interface

uses
Siniflar,
TestFrameWork,DB, DBTables,ADODB,sysutils,sabitler;

type
TPrdxKisilerTests = class(TTestCase)
private
fDatabase :TDatabase;
fQuery :TQuery;
protected

procedure SetUp; override;
procedure TearDown; override;

published
ParadoxKisiler:TPrdxKisiler;
// Test methods
procedure TestEkle;
procedure TestSil;
procedure TestGuncelle;

end;

type
TAccessKisilerTests = class(TTestCase)
private
fAdoConnection:TADOConnection;
fQuery:TADOQuery;

protected

procedure SetUp; override;
procedure TearDown; override;

published
AccesKisiler:TAccessKisiler;
// Test methods
procedure TestEkle;
procedure TestSil;
procedure TestGuncelle;

end;

implementation

{ TPrdxKisilerTests }

procedure TPrdxKisilerTests.SetUp;
begin
inherited;
fDatabase :=TDatabase.Create(nil);
fDatabase.DriverName :='STANDARD';
fDatabase.Params.Add('PATH='+ ExtractFilePath(ParamStr(0)));
fDatabase.Params.Add('DEFAULT DRIVER=PARADOX');
fDatabase.Params.Add('ENABLE BCD=FALSE');
fDatabase.LoginPrompt := false;
fDatabase.DatabaseName :='SADODATA';
fDatabase.Open;
fQuery := TQuery.Create(nil);
fQuery.DatabaseName :='SADODATA';
ParadoxKisiler :=TPrdxKisiler.Create(fDatabase);
end;

procedure TPrdxKisilerTests.TearDown;
begin
inherited;
FreeAndNil(ParadoxKisiler);
FreeAndNil(fQuery);
FreeAndNil(fdatabase);
end;


procedure TPrdxKisilerTests.TestEkle;
var
MaxID:Integer;
begin

{
Bu işlemin testini iki farklı şekilde yapabiliriz.
1- tablonun id alanı otomatik arttığı için sorguyla tablodaki en büyük ID
değerini buluruz ve bunu bir değişkende saklarız. Hemen ardından tabloya
yeni bir kayıt ekleriz. Yeni eklediğimiz kaydın ID'si daha önceden elde
etmiş olduğumuz ID'nin bir fazlası olması gerekir. (normal şartlarda)
Buradan yola çıkarak en son eklediğimiz kaydı veritabanından çekip ilgili
alanların bizim atadığımız alanlara eşit olup olmadığını kontrol ederiz.

2- İkinci bir yöntem ise, kayıt ekleme işleminden önce tablonun kayıt sayısı
bulunur. Kayıt ekleme işleminin ardından kayıt sayısının bir artıp
artmadığı kontrol edilir. Bu yöntemin KayitEkle metodunu tam olarak test
ettiğini söyleyemeyiz ama fazladan bir test göz çıkarmaz :)
}


// 1. Yöntem DİKKAT ! tabloda kayıt yoksa doğru çalışmaz bu nedenle kafadan
// bir kayıt ekliyorum :)

ParadoxKisiler.Ad := 'işi sağlama';
ParadoxKisiler.Soyad :='almak için :)';
ParadoxKisiler.Ekle;


fQuery.Close;
fQuery.SQL.Clear;
fQuery.SQL.Add('Select max(ID) from KISILER');
fQuery.Open;
MaxID := fQuery.Fields[0].AsInteger;

ParadoxKisiler.Ad := 'sadettin';
ParadoxKisiler.Soyad :='polat';
ParadoxKisiler.Ekle;

fQuery.Close;
fQuery.SQL.Clear;
fQuery.SQL.Add('Select * from KISILER where id =' + inttostr(MaxID+1));

fQuery.Open;

Check(fQuery.Fields[0].AsInteger = MaxID + 1, 'Paradox.Ekle Hatalı [ID]');
//bu biraz sakat bi kontrol oldu ama neyse şimdilik iş görür

Check(fQuery.Fields[1].AsString = 'sadettin', 'Prdx.Ekle Hatalı [Ad]');
Check(fQuery.Fields[2].AsString = 'polat', 'Prdx.Ekle Hatalı [SoyAd]');


//2. yöntem //////////////////////////////////////////////////////////////////

fQuery.Close;
fQuery.SQL.Clear;
fQuery.SQL.Add('Select count(*) from KISILER');
fQuery.Open;
MaxID := fQuery.Fields[0].AsInteger;

ParadoxKisiler.Ad := 'şampiyon';
ParadoxKisiler.Soyad :='cimbom';
ParadoxKisiler.Ekle;

fQuery.Close;
fQuery.SQL.Clear;
fQuery.SQL.Add('Select count(*) from KISILER');
fQuery.Open;

Check(fQuery.Fields[0].AsInteger = MaxID + 1, 'Prdx.Ekle Hatalı [2.yöntem]');

end;

procedure TPrdxKisilerTests.TestGuncelle;
var
SeciliID:Integer;
begin

{
Veritabanından rastgele bir kayıt seçilir. İlgili alanları güncellenir.
Hemen ardından aynı kayıt tekrar seçilir ve alanların gerçekten güncellenip
güncellenmediği kontrol edilir. İşi sağlama almak için bu işlem iki kere
yapılabilir.

hiç kayıt yoksa hatalı sonuçlanabilir. riske girme kayıt ekle :)
}

ParadoxKisiler.Ad := 'xxx'; //en az bir kayıt olmasını sağlar
ParadoxKisiler.Soyad :='yyy';
ParadoxKisiler.Ekle;


fQuery.Close;
fQuery.SQL.Clear;
fQuery.SQL.Add('Select * from KISILER order by SOYAD');
fQuery.Open;
SeciliID := fQuery.Fields[0].AsInteger;

ParadoxKisiler.ID := SeciliID;
ParadoxKisiler.Ad := 'sadettin53';
ParadoxKisiler.Soyad :='polatRize';
ParadoxKisiler.Guncelle;

fQuery.Close;
fQuery.SQL.Clear;
fQuery.SQL.Add('Select * from KISILER where id =' + inttostr(SeciliID));
fQuery.Open;

Check(fQuery.Fields[0].AsInteger = SeciliID, 'Paradox.Güncelle Hatalı [ID]');
//aslında bu alanın değişmemesi lazım ama ya değişiyorsa :)

Check(fQuery.Fields[1].AsString = 'sadettin53', 'Prdx.Güncelle Hatalı [Ad]');
Check(fQuery.Fields[2].AsString = 'polatRize', 'Prdx.Güncelle Hatalı [SoyAd]');
end;

procedure TPrdxKisilerTests.TestSil;
var
KayitSayisi,SeciliID:Integer;
begin

{
Silme işlemi de iki şekilde test edilebilir.
1- Tablodan seçtiğimiz bir kaydın id'sini bir değişkende saklarız. Ardından
ilgili kaydı sileriz ve daha sonra değişkende sakladığımız id'nin tabloda
olup olmadığını kontrol ederiz.

2- Kayıt silme işleminden önce tablodaki kayıt sayısını alırız. Kaydı sileriz
kayıt sayısının bir azalıp azalmadığını kontrol ederiz.

}

//1. yöntem
fQuery.Close;
fQuery.SQL.Clear;
fQuery.SQL.Add('Select Count(*) from KISILER');
fQuery.Open;
KayitSayisi := fQuery.Fields[0].AsInteger; //kayit sayisi

fQuery.Close;
fQuery.SQL.Clear;
fQuery.SQL.Add('Select * from KISILER order by AD Desc');
fQuery.Open;
SeciliID := fQuery.Fields[0].AsInteger;


ParadoxKisiler.ID := SeciliID;
ParadoxKisiler.Sil;

fQuery.Close;
fQuery.SQL.Clear;
fQuery.SQL.Add('Select count(*) from KISILER');
fQuery.Open;

Check(fQuery.Fields[0].AsInteger = KayitSayisi - 1 , 'Paradox.Sil Hatalı [1. yöntem]');


//2.yöntem /////////////////////////////////////////////////////////////////
fQuery.Close;
fQuery.SQL.Clear;
fQuery.SQL.Add('Select * from KISILER order by SOYAD desc');
fQuery.Open;
SeciliID := fQuery.Fields[0].AsInteger;

ParadoxKisiler.ID := SeciliID;
ParadoxKisiler.Sil;

fQuery.Close;
fQuery.SQL.Clear;
fQuery.SQL.Add('Select count(*) from KISILER where id =' + inttostr(SeciliID));
fQuery.Open;

Check(fQuery.Fields[0].AsInteger = 0, 'Paradox.Sil Hatalı');
end;

{ TAccessKisilerTests }

procedure TAccessKisilerTests.SetUp;
begin
inherited;
fAdoConnection :=TADOConnection.Create(nil);
fAdoConnection.LoginPrompt := false;
fAdoConnection.ConnectionString := format(ConnectionString,[ExtractFilePath(ParamStr(0))+'KISILER.mdb']);
fAdoConnection.Open;
fQuery :=TADOQuery.Create(nil);
fQuery.Connection :=fAdoConnection;
AccesKisiler :=TAccessKisiler.Create(fAdoConnection);
end;

procedure TAccessKisilerTests.TearDown;
begin
inherited;
FreeAndNil(AccesKisiler);
FreeAndNil(fQuery);
FreeAndNil(fAdoConnection);
end;


procedure TAccessKisilerTests.TestEkle;
var
MaxID:Integer;
begin

// DİKKAT ! tabloda kayıt yoksa doğru çalışmaz bu nedenle kafadan
// bir kayıt ekliyorum :)

AccesKisiler.Ad := 'işi sağlama';
AccesKisiler.Soyad :='almak için :)';
AccesKisiler.Ekle;

//2. yol
fQuery.Close;
fQuery.SQL.Clear;
fQuery.SQL.Add('Select count(*) from KISILER');
fQuery.Open;
MaxID := fQuery.Fields[0].AsInteger;

AccesKisiler.Ad := 'şampiyon';
AccesKisiler.Soyad :='cimbom';
AccesKisiler.Ekle;

fQuery.Close;
fQuery.SQL.Clear;
fQuery.SQL.Add('Select count(*) from KISILER');
fQuery.Open;

Check(fQuery.Fields[0].AsInteger = MaxID + 1, 'Access.Ekle Hatalı [2.yöntem]');


// 1. Yöntem

fQuery.Close;
fQuery.SQL.Clear;
fQuery.SQL.Add('Select max(ID) from KISILER');
fQuery.Open;
MaxID := fQuery.Fields[0].AsInteger;

AccesKisiler.Ad := 'borland';
AccesKisiler.Soyad :='delphi';
AccesKisiler.Ekle;

fQuery.Close;
fQuery.SQL.Clear;
fQuery.SQL.Add('Select * from KISILER where ID =' + inttostr(MaxID+1));
fQuery.Open;

Check(fQuery.Fields[0].AsInteger = MaxID + 1, 'Access.Ekle Hatalı [ID]');
//bu biraz sakat bi kontrol oldu ama neyse şimdilik iş görür

Check(fQuery.Fields[1].AsString = 'borland', 'Acces.Ekle Hatalı [Ad]');
Check(fQuery.Fields[2].AsString = 'delphi', 'Acces.Ekle Hatalı [SoyAd]');



end;

procedure TAccessKisilerTests.TestGuncelle;
var
SeciliID:Integer;
begin

// DİKKAT ! tabloda kayıt yoksa doğru çalışmaz bu nedenle kafadan
// bir kayıt ekliyorum :)

AccesKisiler.Ad := 'işi sağlama';
AccesKisiler.Soyad :='almak için :)';
AccesKisiler.Ekle;

fQuery.Close;
fQuery.SQL.Clear;
fQuery.SQL.Add('Select * from KISILER order by SOYAD');
fQuery.Open;
SeciliID := fQuery.Fields[0].AsInteger;

AccesKisiler.ID := SeciliID;
AccesKisiler.Ad := 'marco';
AccesKisiler.Soyad :='cantu';
AccesKisiler.Guncelle;

fQuery.Close;
fQuery.SQL.Clear;
fQuery.SQL.Add('Select * from KISILER where ID =' + inttostr(SeciliID));
fQuery.Open;

Check(fQuery.Fields[0].AsInteger = SeciliID, 'Acces.Güncelle Hatalı [ID]');
//aslında bu alanın değişmemesi lazım ama ya değişiyorsa :)

Check(fQuery.Fields[1].AsString = 'marco', 'Acces.Güncelle Hatalı [Ad]');
Check(fQuery.Fields[2].AsString = 'cantu', 'Acces.Güncelle Hatalı [SoyAd]');
end;

procedure TAccessKisilerTests.TestSil;
var
KayitSayisi,SeciliID:Integer;
begin

//1. yöntem
fQuery.Close;
fQuery.SQL.Clear;
fQuery.SQL.Add('Select Count(*) from KISILER');
fQuery.Open;
KayitSayisi := fQuery.Fields[0].AsInteger; //kayit sayisi

fQuery.Close;
fQuery.SQL.Clear;
fQuery.SQL.Add('Select * from KISILER order by AD Desc');
fQuery.Open;
SeciliID := fQuery.Fields[0].AsInteger; //kayit sayisi


AccesKisiler.ID := SeciliID;
AccesKisiler.Sil;

fQuery.Close;
fQuery.SQL.Clear;
fQuery.SQL.Add('Select count(*) from KISILER');
fQuery.Open;

Check(fQuery.Fields[0].AsInteger = KayitSayisi - 1 , 'Access.Sil Hatalı');

//2.yöntem ///////////////////////////////////////////////////////////////////
fQuery.Close;
fQuery.SQL.Clear;
fQuery.SQL.Add('Select * from KISILER order by SOYAD desc');
fQuery.Open;
SeciliID := fQuery.Fields[0].AsInteger;

AccesKisiler.ID := SeciliID;
AccesKisiler.Sil;

fQuery.Close;
fQuery.SQL.Clear;
fQuery.SQL.Add('Select count(*) from KISILER where ID =' + inttostr(SeciliID));
fQuery.Open;

Check(fQuery.Fields[0].AsInteger = 0, 'Acces.Sil Hatalı [2.yol]');
end;

initialization

TestFramework.RegisterTest('SiniflarTests Suite',
TPrdxKisilerTests.Suite);
TestFramework.RegisterTest('SiniflarTests Suite',
TAccessKisilerTests.Suite);

end.
Adsız dedi ki…
Son derece yararlı bir makale. Tebrikler !
Adsız dedi ki…
http://www.turkish-property-world.com

Bu blogdaki popüler yayınlar

Yazılımı Oluşturan Bileşenler Nelerdir?

Yazılımı oluşturan bileşenlerden daha önce söz etmiştik. Şimdi bu bileşenlerin neler oldukları üzerinde biraz duralım. Yazılımı oluşturan bileşenler = Mantık + Veri + Belge + İnsan + Program. Bu bileşenlerin az çok neler olduğunu, neleri kapsadığını biliyoruz ama biz yine de kıyısından köşesinden açıklayalım. Zaten bu yazıdaki asıl amaç yazılım bileşenlerinden belgelemenin yerini ve önemi (dökümantasyon) vurgulamak. Mantık = Yazılım herşeyden önce bir işin bilgisayar aracılığı ile yapılması amacına yöneliktir. Bu nedenle bilgisayarlaştırılmak istenen işin mevcut mantığı bir şekilde yazılıma da yansılıtılmak zorundadır. Veri = Her tür yazılım mutlaka bir veri üzerinde çalışmak durumundadır. Veri işlemeyen yazılımın geliştirilmesi söz konusu değildir. Söz konusu olan veri dış ortamdan alınabileceği gibi yazılımın içerisinde de üretilebilir. Zaten yazılımın temel amacı veriyi bilgiye dönüştürmektir. İnsan = Doğal olarak yazılımın insan bileşeni iki boyutludur. Yazıl

Leyse li'l-insâni illâ mâ seâ

"Leyse li'l-insâni illâ mâ seâ" derken Hudâ; Anlamam hiç meskenetten sen ne beklersin daha? Mehmet Akif Ersoy / Durmayalim Leyse li'l-insâni illâ mâ seâ : Necm Süresi 39. Ayet. [İnsan için ancak çalıştığı vardır.] Meskenet: 1 . Miskinlik, beceriksizlik. 2 . Yoksulluk, fakirlik. (Türk Dil Kurumu) Olay zaten yeterince acik. Yan gelip yatma kardesim. Calis. Bu misralar yazildigi donemde bu anlami tasiyordu fakat zaman ilerledikce baska bir gercegi de gozler onune seriyor.Gerci bu gercek cok kapsamli bir kac satirla anlatilabilecek bir sey degil kaldiki benim bilgim de buna yeterli degil zaten. Ben giris cumlelerini verebilirim gerisini arastirmak yaziyi okuyanlara kalmis. (Matrix gibi bisey oldu bu yaw. Neo'nun kahinle bulusup yanindan ayrildiktan sonra Morpheus ile konusma sahnesi.) Yani kisaca sunu demek istiyorum. Ben bu misrayi ilk okudugumda hic birsey anlamadim. Bu misralari anlayabilmek icin kuran mealine ve turkce sozluklere bakmak zorunda k

Yunus sen bu dünyaya niye geldin?

Göçtü Kervan Ah nice bir uyursun uyanmaz mısın Göçtü kervan kaldık dağlar başında Çağrışı tellallar inanmaz mısın Göçtü kervan kaldık dağlar başında Emr-i hac göçeli hayli zamandır Muhammed cümleye dindir imandır Delilsiz gidilmez yollar yamandır Göçtü kervan kaldık dağlar başında Yunus sen bu dünyaya niye geldin Gece gündüz Hakkı zikretsin dilin Enbiyaya uğramaz ise yolun Göçtü kervan kaldık dağlar başında Yunus Emre