Unit testing

vložil Radek Červinka 26. července 2011 23:09

Jedna z důležitých věcí je testování. Nevím jak vy, ale já nesnáším opakované testy. Tj. člověk udělá nějaké změny a následně by měl přetestovat úplně všechno. Ale všichni známe jak to dopadne …

A proto je vhodné použít unit testing, tj. nástroj, který za nás bude opakovaně provádět testy, které mu předepíšeme. Pro Delphi se jedná o DUnit, který je navíc součástí vyšších verzí Delphi (tj. od D2007 nebo možná i starších).

Předpokládá se, že píšete kód za pomocí tříd - ale to většinou není problém.

Mějme tuto primitivní třídu jako ukázku.

unit uCalc;

interface
type
  TCalc = class
  public
    function Add(i, j: Integer):Integer;
    function Multi(i, j: Integer):Integer;
  end;

implementation

{ TCalc }

function TCalc.Add(i, j: Integer): Integer;
begin
  Result := i + j;
end;

function TCalc.Multi(i, j: Integer): Integer;
begin
  Result := i * j;
end;

end.

Pro testování je zapotřebí založit nový projekt, který bude obsahovat DUnit framework.

DUnit

DUnit

DUnit

Zde vyberte zda se bude jednat o GUI tester nebo jen console tester (to určuje jak bude vypadat tester, nikoliv co se dá testovat). Console verze je vhodná třeba jako součást dávkového testování.

Nyní máme prázdný projekt s frameworkem, přidáme naši třídu a jdeme na testování. Vrátíme se opět do prvního menu, kde nám mezitím přibyla nová položka Test Case.

DUnit

Po jejím zvolení můžeme vybrat unit s testovanou třídou a zároveň vybereme metody, které chceme testovat. V našem případě viz obrázek.

DUnit

Nyní už vybereme jen výsledný soubor, kde bude uložen náš Test Case a je to. Wizard vygeneruje základní kostru.

DUnit

unit TestuCalc;
{

  Delphi DUnit Test Case
  ----------------------
  This unit contains a skeleton test case class generated by the Test Case Wizard.
  Modify the generated code to correctly setup and call the methods from the unit 
  being tested.

}

interface

uses
  TestFramework, uCalc;

type
  // Test methods for class TCalc

  TestTCalc = class(TTestCase)
  strict private
    FCalc: TCalc;
  public
    procedure SetUp; override;
    procedure TearDown; override;
  published
    procedure TestAdd;
    procedure TestMulti;
  end;

implementation

procedure TestTCalc.SetUp;
begin
  FCalc := TCalc.Create;
end;

procedure TestTCalc.TearDown;
begin
  FCalc.Free;
  FCalc := nil;
end;

procedure TestTCalc.TestAdd;
var
  ReturnValue: Integer;
  j: Integer;
  i: Integer;
begin
  // TODO: Setup method call parameters
  ReturnValue := FCalc.Add(i, j);
  // TODO: Validate method results
end;

procedure TestTCalc.TestMulti;
var
  ReturnValue: Integer;
  j: Integer;
  i: Integer;
begin
  // TODO: Setup method call parameters
  ReturnValue := FCalc.Multi(i, j);
  // TODO: Validate method results
end;

initialization
  // Register any test cases with the test runner
  RegisterTest(TestTCalc.Suite);
end.

Metody SetUp a TearDown jsou určeny k vytvoření a zrušení testované třídy (nebo k inicializaci pro testování atd). Metody TestAdd a TestMulti jsou kostry bez validace.

Všimněte si, že testovací metody jsou published, což je důležité - testovací framework pomocí RTTI zjišťuje, co se má testovat. Tj. všechny published metody jsou určeny pro testování. Další důležitou informací je, že testovací třída je následníkem TTestCase, která obsahuje celkem dost metod, které můžeme použít.

Ale zpět. Upravíme testy:

procedure TestTCalc.TestAdd;
var
  ReturnValue: Integer;
  j: Integer;
  i: Integer;
begin
  i := 10;
  j := 15;
  ReturnValue := FCalc.Add(i, j);
  // spatna hodnota jako ukazka
  CheckEquals(24, ReturnValue, 'Add vrátilo špatný výsledek');
end;

procedure TestTCalc.TestMulti;
var
  ReturnValue: Integer;
  j: Integer;
  i: Integer;
begin
  i := 10;
  j := 11;
  ReturnValue := FCalc.Multi(i, j);
  CheckTrue(ReturnValue = 110);
end;

DUnit

Každý Test Case je jedna větev stromu, dají se volit jednotlivé větve nebo jen testy. A to je v podstatě základ testování.

Tagy: , , , , ,

Návody

Komentáře

27.7.2011 23:03:10 #

pepak

Automatické testování mě dost zajímá, protože by mi mohlo ušetřit spoustu starostí. Ale tenhle triviální příklad asi není to správné, co by mi ukázalo efektivní použití této techniky. Nevěděl bys o nějakém zdroji, který by to probíral víc do hloubky, ale na reálných příkladech? Když jsem to hledal, tak jsem vesměs narážel na teoretické floskulky, že "se dá automaticky testovat" atd., ale nikdy jsem nenarazil na nic, co by mi to předvedlo na rozumném příkladu.

pepak

27.7.2011 23:20:21 #

Radekc

Já si s tím teď trochu hraji, a tohle je základ - musel jsem vysvětlit princip, nikde jsem to moc přehledně nenašel.

http://blogs.embarcadero.com/nickhodges/2010/04/15/39401 (poslední ze série článků)
je tam odkaz na kompletní brutální unit test (http://cc.embarcadero.com/item/27675)

a tohle mne taky zaujalo
http://www.stevetrefethen.com/blog/ModelingUIForAutomatedGUITesting.aspx

Ale já osobně - jelikož mám všechny formuláře následníkem bázového - tak jsem toho využil a postupně je volám a aspoň tak otestuji, že mi to otevře DB data a nespadne. Dále to mám vymyšleno tak, že budu mít testovací DB v určité konfiguraci a to budu využívat pro kontrolu dotazů (tj. Insert, Update, TransactionRollback). Ale uvidím. Zatím mám cca 50 testů.

Radekc

29.7.2011 16:52:53 #

Ladislav Starý

Unit testy, programování řízené testy, refactoring, extrémní programování a další techniky zpopularizovala Java, takže asi nejvíc informací bude v materiálech věnovaných Javě.

Psaní unit testů dle materiálů, které jsem četl, vyžaduje trochu odlišné psaní kódu, aby bylo snadné kód testovat po malých kouscích.

Tady je několik odkazů, na které jsem teď narazil:
http://www.dagblog.cz/2011_01_23_archive.html#6246118999339359130
http://www.dagblog.cz/2011_06_12_archive.html#5427119770257908807
http://www.abclinuxu.cz/poradna/programovani/show/327640

V té diskuzi se zmiňují o knize Working Effectively with Legacy Code, kterou u nás vydal Computer Press (http://knihy.cpress.cz/udrzba-kodu-prevzatych-programu.html).

Ještě poznámka k DUnit. Je to poměrně starý projekt, který byl původně opensource a Borland (možná až CodeGear) ho začlenil do Delphi. Pro starší verze (funkční je od Delphi 5) je ke stažení na webu http://dunit.sourceforge.net/

Ladislav Starý

1.8.2011 21:54:27 #

Tomas Hruska

Pak je jeste na dunit postaveny framework OpenCTF - http://openctf.sourceforge.net/ - k testovani komponent na formularich nebo v dataModulech. Mimochodem, testy (samozrejme command line verzi) muzete zaradit jako jednu z uloh FinalBuilderu a podle vysledku se zaridit.

Tomas Hruska

1.8.2011 23:12:00 #

Radekc

OpenCTF - něco takového jsem hledal, to si musím vyzkoušet. Díky!

Radekc

Komentování ukončeno

Naše nabídka

MVP
Ing. Radek Červinka - Embarcadero MVP
profil na linkedin, Twitter:@delphicz

Nabízím placené poradenství a konzultace v oblasti programování a vývoje SW.
Dále nabízíme i vývoj speciálního software na zakázku.

Neváhejte nás kontaktovat (i ohledně reklamy).

love Delphi

O Delphi.cz

Delphi je moderní RAD nástroj podporující tvorbu nativních aplikací pro platformu Win32, Win64, Mac OSX, Linux a na iPhone a Android.

Delphi.cz je nezávislý portál pro uživatele Delphi. Portál není koncipován pro úplné začátečníky, i když i ti se zde nebudou nudit, ale spíše na programátory, kteří již něco znají a chtějí své znalosti dále rozvíjet a sledovat novinky.

Poslední komentáře

Comment RSS

Dle měsíců