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

    1unit TestuCalc;
    2{
    3
    4  Delphi DUnit Test Case
    5  ----------------------
    6  This unit contains a skeleton test case class generated by the Test Case Wizard.
    7  Modify the generated code to correctly setup and call the methods from the unit 
    8  being tested.
    9
   10}
   11
   12interface
   13
   14uses
   15  TestFramework, uCalc;
   16
   17type
   18  // Test methods for class TCalc
   19
   20  TestTCalc = class(TTestCase)
   21  strict private
   22    FCalc: TCalc;
   23  public
   24    procedure SetUp; override;
   25    procedure TearDown; override;
   26  published
   27    procedure TestAdd;
   28    procedure TestMulti;
   29  end;
   30
   31implementation
   32
   33procedure TestTCalc.SetUp;
   34begin
   35  FCalc := TCalc.Create;
   36end;
   37
   38procedure TestTCalc.TearDown;
   39begin
   40  FCalc.Free;
   41  FCalc := nil;
   42end;
   43
   44procedure TestTCalc.TestAdd;
   45var
   46  ReturnValue: Integer;
   47  j: Integer;
   48  i: Integer;
   49begin
   50  // TODO: Setup method call parameters
   51  ReturnValue := FCalc.Add(i, j);
   52  // TODO: Validate method results
   53end;
   54
   55procedure TestTCalc.TestMulti;
   56var
   57  ReturnValue: Integer;
   58  j: Integer;
   59  i: Integer;
   60begin
   61  // TODO: Setup method call parameters
   62  ReturnValue := FCalc.Multi(i, j);
   63  // TODO: Validate method results
   64end;
   65
   66initialization
   67  // Register any test cases with the test runner
   68  RegisterTest(TestTCalc.Suite);
   69end.

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í.


Nabízíme Delphi školení na různá témata, primárně ve Vaší firmě.

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

Partial English version.

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 nebo burzy práce).

Pokud chcete podpořit tento server libovolnou částkou, můžete použít PayPal. Moc děkuji.

Delphi Certified Developer

O Delphi.cz

Delphi je jediný moderní RAD nástroj podporující tvorbu nativních aplikací pro platformu Win32, Win64 , Mac OSX a na iPhone a Android (s výhledem na další platformy díky FireMonkey) na současném trhu (včetně Windows 8.1).

V současnosti je světová komunita přes dva miliónů vývojářů.

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.

Anketa

Poslední komentáře

Comment RSS