Univerzální testovací nástroj Robot Framework

3. 12. 2019
Doba čtení: 22 minut

Sdílet

V dnešním článku si představíme univerzální testovací nástroj nazvaný Robot Framework. Ten je určen pro tvorbu akceptačních testů, ovšem používá se například i pro testování uživatelského rozhraní aplikací.

Obsah

1. Univerzální testovací nástroj Robot Framework

2. Instalace nástroje Robot Framework

3. Nejjednodušší testovací scénář aneb „Hello world“ pro Robot Framework

4. Základní formát testovacího scénáře

5. Další možný formát testovacího scénáře

6. Zvýraznění tabulkového formátu testů

7. Formát založený na TSV

8. Testovací scénář s větším množstvím test casů

9. Přepis předchozího scénáře do „tabulkového“ formátu

10. Testovací scénář s testem, který skončí s chybou

11. Klíčové slovo Repeat Keyword

12. Implementace vlastního klíčového slova v Pythonu

13. Klíčové slovo vytvořené v Pythonu způsobující pád testu

14. Klíčová slova realizovaná formou metod

15. Různé typy logovacích zpráv

16. Zajištění pádu testu s využitím aserce

17. První skutečný testovací scénář – test funkce kalkulačky

18. Korektní práce s parametry klíčových slov

19. Repositář s demonstračními příklady

20. Odkazy na Internetu

1. Univerzální testovací nástroj Robot Framework

Na stránkách serveru root.cz jsme se seznámili již s několika různými knihovnami a frameworky určenými pro tvorbu a spouštění softwarových testů. Připomeňme si, že pro prakticky každý moderní programovací jazyk existuje minimálně jedna knihovna použitelná pro psaní jednotkových testů (unit test); ve skutečnosti ovšem těchto knihoven bude pro daný jazyk pravděpodobně existovat hned několik. Ovšem jednotkové testy tvoří jen jedinou vrstvu (základnu) takzvané „testovací pyramidy“. Nad nimi se nachází funkční testy, integrační testy, různé formy benchmarků, BDD testy, testy grafického uživatelské rozhraní atd. Z již popsaných nástrojů pro tvorbu těchto testů zmiňme například knihovnu Behave (BDD testy psané v Pythonu), Godog (BDD testy psané v Go), knihovnu Frisby (testy REST API, implementace pro Go), různé varianty knihovny expect (testování aplikací s příkazovou řádkou) atd. Knihovny a frameworky pro testování je však možné používat i u méně mainstreamových jazyků, například v Clojure [1] [2] [3] apod.

Dnes se – prozatím ovšem ve stručnosti – seznámíme s některými vlastnostmi nástroje nazvaného Robot Framework, který je naprogramován v Pythonu, ovšem lze ho použít společně s dalšími programovacími jazyky (ať již přímo či nepřímo, což si vysvětlíme příště). Jedná se o nástroj použitelný mj. pro psaní akceptačních testů (které tvoří vlastní testovací pyramidu používanou paralelně s klasickou testovací pyramidou), ovšem lze ho použít i pro zápis BDD testů, testů grafického uživatelského rozhraní (založeného například na webových technologiích) atd. Robot Framework je navržen velmi obecně, což sice zajišťuje jeho velkou flexibilitu, ovšem na druhou stranu nemusí být zpočátku zřejmé, jakým způsobem je ho vlastně možné použít. Z tohoto důvodu si dnes ukážeme jak základní formát zápisu testovacích scénářů, tak i způsob implementace jednotlivých klíčových slov (keyword) v Pythonu (klíčová slova vlastně přestavují základní stavební kameny implementace testovacích scénářů).

Obrázek 1: Logo nástroje Robot Framework.

2. Instalace nástroje Robot Framework

Nástroj Robot Framework je navržen modulárním způsobem. Obsahuje jádro představované (z pohledu uživatele) spustitelnými soubory robot a rebot. Toto jádro je doplněno o několik standardních knihoven se sadou základních klíčových slov. Doinstalovat je možné i další knihovny (moduly), například modul zajišťující testování webových aplikací přes Selenium (SeleniumLibrary) atd. Dnes si ovšem vystačíme „pouze“ s jádrem Robot Frameworku a se základními klíčovými slovy, která rozšíříme pomocí kódu napsaného v Pythonu.

Samotná instalace jádra Robot Frameworku je snadná a můžeme pro ni použít nástroj pip či pip3. Pro jednoduchost je v tomto článku instalace provedena pouze pro aktivního uživatele, stejně dobře je však možné použít virtuální prostředí Pythonu (virtualenv), provést instalaci do systémových adresářů atd.:

$ pip3 install --user robotframework

Instalace by měla být velmi krátká, protože samotné jádro frameworku je relativně malé a kompaktní. Po dokončení instalačního procesu si zkontrolujte, zda je na PATH dostupný spustitelný soubor robot:

$ which robot
 
/home/tester/.local/bin/robot

A následně je možné tento soubor spustit:

$ robot --version
 
Robot Framework 3.1.2 (Python 3.7.4 on linux)
Poznámka: v případě, že spustitelný soubor robot nebyl nalezen, zkontrolujte obsah adresáře „~/.local/bin“, popř. aktuální obsah proměnné prostředí PATH:
$ echo $PATH
 
/home/tester/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/tester/bin:/home/tester/.local/bin/:/opt/go/bin:/home/tester/go/bin

3. Nejjednodušší testovací scénář aneb „Hello world“ pro Robot Framework

Podívejme se nyní na zcela nejjednodušší, ovšem plně funkční testovací scénář, který obsahuje test nazvaný „Demo“ s jediným krokem – vytištěním řetězce „Hello world“ do automaticky vytvářeného logovacího souboru. Scénář je uložen v souboru pojmenovaném „test01.robot“ a má následující obsah:

*** Test Cases ***
Demo
    Log  Hello world
Poznámka: pozor si dejte na to, aby mezi slovem „Log“ a „Hello“ byly zapsány minimálně dvě mezery, popř. aby zde byl znak tabulátoru (HT: Horizontal Tab). Tuto podivnou podmínku si vysvětlíme později.

Tento test je možné bez dalších nastavování spustit, a to bez nutnosti připravovat adresář s projektem atd. Spuštění se provede příkazem:

$ robot test01.robot

Po spuštění by se měly do terminálu vypsat informace o spuštěných a úspěšně dokončených testech, včetně informace o tom, že byly vytvořeny i soubory s výsledky testu i se zprávami poslanými do logu. Cesta k těmto souborům je zobrazena v absolutní podobě, což je rozumné, protože adresářová struktura s testy a pomocnými knihovnami může být v reálných projektech i dosti složitá; navíc dokážou některé terminály takto zapsanou cestu zvýraznit ve formě aktivního odkazu pro otevření v prohlížeči:

==============================================================================
Test01
==============================================================================
Demo                                                                  | PASS |
------------------------------------------------------------------------------
Test01                                                                | PASS |
1 critical test, 1 passed, 0 failed
1 test total, 1 passed, 0 failed
==============================================================================
Output:  /home/tester/src/Python/robot-framework-examples/article01/output.xml
Log:     /home/tester/src/Python/robot-framework-examples/article01/log.html
Report:  /home/tester/src/Python/robot-framework-examples/article01/report.html

Podrobnější výsledky spuštěných testů nalezneme ve výše zmíněných vygenerovaných HTML stránkách, které lze například (v případě spuštění na CI) uložit do artefaktu atd., protože samotné stránky obsahují všechna potřebná data (CSS + pomocné JavaScriptové funkce). Základem je soubor report.html se shrnutými výsledky spuštěných testů:

Obrázek 2: Shrnuté výsledky spuštěných testů ve vygenerované HTML stránce.

K dispozici jsou ovšem i logovací informace, které jsou rozděleny podle jednotlivých scénářů a případů (stránka obsahuje rozklikávací bloky):

Obrázek 3: Logovací informace získané po spuštění testů. Samotný text „Hello world“ naleznete na screenshotu zcela dole.

4. Základní formát testovacího scénáře

V předchozí kapitole jsme si řekli, že v samotné implementaci testu je nutné mezi slovo „Log“ a „Hello“ vložit minimálně dvě mezery, tedy že poslední řádek textového souboru s testem má vypadat takto:

    Log  Hello world

Je tomu tak z toho důvodu, že testovací scénáře mají formát připomínající tabulku a tím pádem je nutné rozlišit mezery umístěné v jedné buňce tabulky („Hello world“ je z tohoto pohledu jediná buňka) a mezery použité pro oddělení jednotlivých buněk tabulky. Ostatně i mezery na začátku řádku, tedy před slovem „Log“, slouží pro specifikaci prázdné buňky v prvním sloupci pomyslné tabulky.

Ostatně si můžeme snadno vyzkoušet, co se stane ve chvíli, kdy namísto dvou (či více) mezer mezi slovy „Log“ a „Hello“ použijeme mezeru jedinou:

*** Test Cases ***
Demo
    Log Hello world

Pokusíme se spustit takto upravený test:

$ robot test02.robot

Tentokrát je ovšem nahlášena chyba, a to v samotném formátu testu:

==============================================================================
Test02
==============================================================================
Demo                                                                  | FAIL |
No keyword with name 'Log Hello world' found.
------------------------------------------------------------------------------
Test02                                                                | FAIL |
1 critical test, 0 passed, 1 failed
1 test total, 0 passed, 1 failed
==============================================================================
Output:  /home/tester/src/Python/robot-framework-examples/article01/output.xml
Log:     /home/tester/src/Python/robot-framework-examples/article01/log.html
Report:  /home/tester/src/Python/robot-framework-examples/article01/report.html
Poznámka: samotné chybové hlášení nám vlastně naznačuje, jakým způsobem se testovací scénáře zpracovávají. Slova oddělená maximálně jednou mezerou jsou považována za keyword (klíčová slova), dvěma či více mezerami se naopak klíčová slova oddělují od svých parametrů. To, že klíčová slova jsou ve skutečnosti souslovími, sice na první pohled může působit divně (minimálně na vývojáře používající klasické programovací jazyky), ovšem testovací scénáře jsou díky tomu čitelnější.

5. Další možný formát testovacího scénáře

Ve skutečnosti existují i další možné formáty zápisů testovacího scénáře. Můžeme například pro oddělení jednotlivých buněk pomyslné tabulky použít znak Tab, pochopitelně tehdy, pokud máte správně nastavený textový editor (aby Taby neexpandoval na mezery). V následujícím výpisu je mezi slova „Log“ a „Hello“ vložena právě tabelační zarážka (což je naznačeno vloženým řádkem):

*** Test Cases ***
Demo
    Log Hello world
       ^

V textovém editoru Vim je možné si nechat zobrazit řídicí znaky volbou:

:set list

S následujícím výsledkem (řídicí znaky jsou zvýrazněny tučným písmem):

*** Test Cases ***$
Demo$
    Log^IHello world$

6. Zvýraznění tabulkového formátu testů

Poměrně často se setkáme s tím, že se tabulkový formát testů zvýrazňuje přímo v testovacím scénáři s využitím znaků |. Právě na tomto formátu je nejlépe patrné, že i hlavičky jednotlivých sekcí (zde *** Test Cases ***) jsou vlastně pouhými buňkami tabulky. Taktéž je zřejmé, že klíčové slovo „Log“ má parametr „Hello world“:

| *** Test Cases *** |             |             |
| Demo               |             |             |
|                    | Log         | Hello world |
Poznámka: předchozí chybný zápis s jedinou mezerou mezi „Log“ a „Hello“ by tedy odpovídal chybnému formátu testu:
| *** Test Cases *** |                 |
| Demo               |                 |
|                    | Log Hello world |

Význam a určitá elegance tohoto způsobu zápisu vynikne zejména ve chvíli, kdy bude scénář obsahovat větší množství sekcí, více testovaných případů atd.:

| *** Settings ***   |                  |   |
| Library            | Test16.py        |   |
|                    |                  |   |
| *** Test Cases *** |                  |   |
| Adder #1           |                  |   |
|                    | Add              | 1 | 2
|                    | Result should be | 3 |
|                    |                  |   |
| Adder #2           |                  |   |
|                    | Add              | 0 | 0
|                    | Result should be | 0 |
|                    |                  |   |
| Adder #3           |                  |   |
|                    | Add              | 1 | -1
|                    | Result should be | 0 |

Alternativně:

| *** Settings ***   |                  |   |
| Library            | Test16.py        |   |
 
| *** Test Cases *** |                  |   |
| Adder #1           |                  |   |
|                    | Add              | 1 | 2
|                    | Result should be | 3 |
|                    | Add              | 2 | 3
|                    | Result should be | 5 |
|                    | Add              | 4 | 5
|                    | Result should be | 9 |
 
| Adder #2           |                  |   |
|                    | Add              | 0 | 0
|                    | Result should be | 0 |
 
| Adder #3           |                  |   |
|                    | Add              | 1 | -1
|                    | Result should be | 0 |
Poznámka: pokud se s využitím Robot Frameworku tvoří akceptační testy, tak může být právě tabulková forma vhodná, protože se vlastně jedná o úřední dokument mnohdy zpracovávaný lidmi, kteří mají tabulky v oblibě :-)

7. Formát založený na TSV

Dalším formátem testů podporovaných Robot Frameworkem je formát odvozený od TSV neboli Tab-separated values. Jedná se o jeden z nejjednodušších formátů – textový soubor, v němž každý řádek představuje jeden řádek tabulky a jednotlivé buňky na řádku jsou odděleny znakem Tab. Speciální znaky (včetně samotných tabů a konců řádků v buňkách) jsou uloženy v podobě známé například z céčkovské větve programovacích jazyků – \n, \t, \\ atd. Povšimněte si, že se jedná o jednodušeji implementovatelný formát, než je tomu v případě CSV s jeho mnoha variantami, ne vždy stoprocentně dodržovaným standardem, problematickým znakem konce řádku atd.

V případě použití TSV může vypadat testovací scénář takto. Na posledním řádku jsou naznačeny konce tabelačních zarážek (ty lze v mnoha editorech nastavit na zvolené indexy znaků):

*** Test Cases ***
Demo
                        Log     Hello world
                       ^       ^

Nepatrně složitější testovací scénář může vypadat následovně. Taby (nikoli mezery) jsou zvýrazněny zeleným pozadím:

Obrázek 4: Testovací scénář uložený v souborech typu TSV.

Výhoda použití TSV (pochopitelně v některých situacích) začne být zřejmá, pokud si uvědomíme, že soubory tohoto typu lze snadno vytvářet a editovat v prakticky každém tabulkovém procesoru:

Obrázek 5: Předchozí soubor, tentokrát otevřený v tabulkovém procesoru.

8. Testovací scénář s větším množstvím test casů

V dalším demonstračním příkladu je ukázáno, jakým způsobem lze zapsat testovací scénář s trojicí test casů (případů). Jednotlivé casy není zapotřebí oddělovat, protože rozlišení mezi krokem testu a začátkem nového test casu je provedeno na základě odsazení řádků (dvě či více mezer == přechod na další buňku pomyslné tabulky):

*** Test Cases ***
Case1
    Log  Case#1
Case2
    Log  Case#2
Case3
    Log  Case#3

Pochopitelně nám ovšem nikdo nebrání vložit do testovacího scénáře oddělovací prázdné řádky:

*** Test Cases ***
 
Case1
    Log  Case#1
 
Case2
    Log  Case#2
 
Case3
    Log  Case#3

Po spuštění testu příkazem robot by se měla zobrazit tabulka s výsledky všech testů, které byly provedeny:

$ robot test06.robot

V tomto případě všechny testy proběhnou v pořádku, protože jediným příkazem je Log:

==============================================================================
Test06
==============================================================================
Case1                                                                 | PASS |
------------------------------------------------------------------------------
Case2                                                                 | PASS |
------------------------------------------------------------------------------
Case3                                                                 | PASS |
------------------------------------------------------------------------------
Test06                                                                | PASS |
3 critical tests, 3 passed, 0 failed
3 tests total, 3 passed, 0 failed
==============================================================================
Output:  /home/tester/src/Python/robot-framework-examples/article01/output.xml
Log:     /home/tester/src/Python/robot-framework-examples/article01/log.html
Report:  /home/tester/src/Python/robot-framework-examples/article01/report.html

Ve webovém prohlížeči si můžeme prohlédnout vygenerované soubory s výsledky:

Obrázek 6: Přehled s výsledky testovacího scénáře. Zelená barva naznačuje, že všechny testy skončily korektně.

Obrázek 7: Podrobnější pohled na jednotlivé kroky testu.

Obrázek 8: Podrobnější pohled na jednotlivé kroky testu, informace z logovacího souboru.

9. Přepis předchozího scénáře do „tabulkového“ formátu

Jen pro úplnost si ukažme, jak se předchozí test může přepsat do „tabulkového“ formátu. Je to ve skutečnosti velmi snadné:

| *** Test Cases *** |             |        |
|                    |             |        |
| Case1              |             |        |
|                    | Log         | Case#1 |
|                    |             |        |
| Case2              |             |        |
|                    | Log         | Case#2 |
|                    |             |        |
| Case3              |             |        |
|                    | Log         | Case#3 |
|                    |             |        |

10. Testovací scénář s testem, který skončí s chybou

Můžeme si pochopitelně vyzkoušet i testovací scénář, ve kterém jeden test skončí s chybou; zde konkrétně zajištěnou použitím standardního klíčového slova Fail. Scénář bude vypadat následovně:

*** Test Cases ***
Case1
    Log  Case#1
Case2
    Fail  Failure!!!
Case3
    Log  Case#3

Test spustíme standardním způsobem:

$ robot test08.robot

Výsledky nyní budou podle očekávání odlišné, což je patrné již při pohledu na tabulku zobrazenou v průběhu testování nástrojem robot:

==============================================================================
Test08
==============================================================================
Case1                                                                 | PASS |
------------------------------------------------------------------------------
Case2                                                                 | FAIL |
Failure!!!
------------------------------------------------------------------------------
Case3                                                                 | PASS |
------------------------------------------------------------------------------
Test08                                                                | FAIL |
3 critical tests, 2 passed, 1 failed
3 tests total, 2 passed, 1 failed
==============================================================================
Output:  /home/tester/src/Python/robot-framework-examples/article01/output.xml
Log:     /home/tester/src/Python/robot-framework-examples/article01/log.html
Report:  /home/tester/src/Python/robot-framework-examples/article01/report.html

To, že alespoň jeden test skončil s chybou, je patrné již při prvním pohledu na vytvořenou stránku, která je nyní červená:

Obrázek 9: Přehled s výsledky testovacího scénáře. Červená barva naznačuje pád alespoň jednoho testu.

Obrázek 10: Podrobnější pohled na jednotlivé kroky testu.

Obrázek 11: Podrobnější pohled na jednotlivé kroky testu, informace z logovacího souboru (červeně jsou označena problémová místa).

11. Klíčové slovo Repeat Keyword

V sadě standardních klíčových slov nalezneme mj. i slovo Repeat Keyword, které slouží, jak ostatně jeho název naznačuje, pro opakování jiného klíčového slova neboli opakování jednoho kroku testu. Opakování je možné specifikovat více způsoby – počtem opakování, celkovou dobou trvání opakování atd. Ukažme si, jak lze zajistit zápis pěti stejných vět do logovacího souboru:

*** Test Cases ***
Repeated message demo
    Repeat Keyword      5 times    Log    Hello world
Poznámka: povšimněte si, že samotný krok testu je představován čtyřmi buňkami pomyslné tabulky (tomuto dělení musí odpovídat i mezery mezi buňkami):
  1. Slovem Repeat Keyword
  2. Specifikací počtu opakování 5 times
  3. Slovem, které se má opakovat Log
  4. Parametrem opakovaného slova Hello world

Zkusme si nyní tento test spustit:

$ robot test09.robot

Průběh testu – vypíše se pouze jediný krok!:

==============================================================================
Test09
==============================================================================
Repeated message demo                                                 | PASS |
------------------------------------------------------------------------------
Test09                                                                | PASS |
1 critical test, 1 passed, 0 failed
1 test total, 1 passed, 0 failed
==============================================================================
Output:  /home/tester/src/Python/robot-framework-examples/article01/output.xml
Log:     /home/tester/src/Python/robot-framework-examples/article01/log.html
Report:  /home/tester/src/Python/robot-framework-examples/article01/report.html

Teprve při pohledu na obsah logu je patrné, že skutečně došlo k opakovanému vypsání zprávy „Hello world“:

Obrázek 12: Podrobnější pohled na jednotlivé kroky testu, informace z logovacího souboru

12. Implementace vlastního klíčového slova v Pythonu

Existence standardních klíčových slov samozřejmě nebude pro tvorbu skutečných akceptačních testů dostatečná, takže musíme mít k dispozici mechanismus pro vytvoření nových klíčových slov. Ve skutečnosti je to mnohdy až triviálně snadné, o čemž se přesvědčíme v této kapitole i v kapitolách navazujících. Vytvoříme testovací scénář, v němž se bude používat nové klíčové slovo test definované ve zdrojovém souboru Test10.py. V testovacím scénáři je nutné specifikovat použití nové knihovny, a to v sekci settings:

*** Settings ***
Library         Test10.py
 
*** Test Cases ***
Demo
    test

Jak vlastně vypadá definice nového klíčového slova v Pythonu? V tom nejjednodušším možném případě se může jednat o běžnou funkci, jejíž název odpovídá klíčovému slovu (případná podtržítka pak oddělují jednotlivé části klíčového slova):

def test():
    print("TEST")

To je vše – není zapotřebí provádět žádné importy, používat dekorátory atd. atd. (do funkcí lze předávat parametry, ovšem tuto problematiku si vysvětlíme později). O tom, že test bude moci být spuštěn, se přesvědčíme snadno:

$ robot test10.robot

S výsledkem:

==============================================================================
Test10
==============================================================================
Demo                                                                  | PASS |
------------------------------------------------------------------------------
Test10                                                                | PASS |
1 critical test, 1 passed, 0 failed
1 test total, 1 passed, 0 failed
==============================================================================
Output:  /home/tester/src/Python/robot-framework-examples/article01/output.xml
Log:     /home/tester/src/Python/robot-framework-examples/article01/log.html
Report:  /home/tester/src/Python/robot-framework-examples/article01/report.html

13. Klíčové slovo vytvořené v Pythonu způsobující pád testu

Vzhledem k tomu, že nová klíčová slova naprogramovaná například v Pythonu (popřípadě v Javě) tvoří základ testů, musíme znát způsob, jak dát Robot Frameworku najevo, že dané slovo (tedy jeden krok testu) zhavaroval. K tomuto účelu lze použít buď běžnou asserci (vyhazující výjimku), nebo výjimku vyhodit explicitně:

def test():
    raise Exception("fatal error")

Testovací scénář upravíme takovým způsobem, aby používal nový modul Test11.py:

*** Settings ***
Library         Test11.py
 
*** Test Cases ***
Demo
    test

Upravený scénář spustíme:

$ robot test11.robot

A ze zobrazené tabulky ihned zjistíme, že k pádu testu skutečně došlo, podle našich předpokladů:

==============================================================================
Test11
==============================================================================
Demo                                                                  | FAIL |
fatal error
------------------------------------------------------------------------------
Test11                                                                | FAIL |
1 critical test, 0 passed, 1 failed
1 test total, 0 passed, 1 failed
==============================================================================
Output:  /home/tester/src/Python/robot-framework-examples/article_01/output.xml
Log:     /home/tester/src/Python/robot-framework-examples/article_01/log.html
Report:  /home/tester/src/Python/robot-framework-examples/article_01/report.html

14. Klíčová slova realizovaná formou metod

V předchozích dvou kapitolách jsme si ukázali, že nová klíčová slova lze definovat formou běžných Pythonovských funkcí. Jedná se o nejjednodušší způsob, který však má jednu zásadní nevýhodu – funkce nemá implicitně přístup ke kontextu, v němž je spuštěna. A kontext je většinou nutné si nějakým způsobem zapamatovat (například mezi několika kroky testu). Proto si v dalším příkladu ukážeme, jak lze nové klíčové slovo realizovat metodou. Je to prakticky stejně snadné:

class Test12:
    def __init__(self):
        print("INIT")
 
    def test(self):
        print("TEST")

V případě, že je třída Test12 uložena v souboru pojmenovaném Test12.py (Javovská konvence), není zapotřebí testovací scénář žádným zásadním způsobem modifikovat:

*** Settings ***
Library         Test12.py
 
*** Test Cases ***
Demo
    test

Spuštění testu bude probíhat stejným způsobem, jako tomu bylo u předchozích demonstračních příkladů.

15. Různé typy logovacích zpráv

Do logovacího souboru lze ukládat zprávy různých typů, což ostatně není žádná specialita Robot Frameworku. Pro logování lze i v Robot Frameworku použít standardní Pythonovskou knihovnu logging a v ní deklarované funkce info, debug, warn/warning, error či critical. Vytvořme si nyní novou funkci s několika metodami (a tedy i několika klíčovýmii slovy):

from logging import debug, error, info, warn
 
class Test13:
    def __init__(self):
        print("INIT")
 
    def try_logging_module_info(self):
        info("info message")
 
    def try_logging_module_debug(self):
        debug("debug message")
 
    def try_logging_module_warning(self):
        warn("warning message")
 
    def try_logging_module_error(self):
        error("error message")

Testovací scénář bude obsahovat tři test casy, z nichž každý bude volat jinou kombinaci klíčových slov:

*** Settings ***
Library         Test13.py
 
*** Test Cases ***
Log1
    Try Logging Module Info
    Try Logging Module Debug
 
Log2
    Try Logging Module Debug
    Try Logging Module Warning
 
Log3
    Try Logging Module Debug
    Try Logging Module Error
Poznámka: povšimněte si, že klíčová slova se zapisují s jednotlivými částmi oddělenými mezerou, zatímco ve zdrojovém kódu pochopitelně musíme použít podtržítko.

Výsledky běhu testu:

==============================================================================
Test13
==============================================================================
Log1                                                                  | PASS |
------------------------------------------------------------------------------
Log2                                                                  | PASS |
------------------------------------------------------------------------------
Log3                                                                  | PASS |
------------------------------------------------------------------------------
Test13                                                                | PASS |
3 critical tests, 3 passed, 0 failed
3 tests total, 3 passed, 0 failed
==============================================================================
Output:  /home/tester/src/Python/robot-framework-examples/article01/output.xml
Log:     /home/tester/src/Python/robot-framework-examples/article01/log.html
Report:  /home/tester/src/Python/robot-framework-examples/article01/report.html

Všimněte si, že všechny testy proběhly v pořádku (PASS), protože i zavolání funkce logging.error je jen zápis informace do logu a nikoli pád:

Obrázek 13: Různé typy zpráv zapsaných do logovacího souboru jsou zvýrazněny různými barvami.

16. Zajištění pádu testu s využitím aserce

Jen pro úplnost si ukažme, jak lze zajistit pád testu s využitím příkazu assert. Při nesplnění podmínky uvedené za tímto klíčovým slovem se vyhodí výjimka:

from logging import debug, error, info, warn
 
class Test14:
    def __init__(self):
        print("INIT")
 
    def try_logging_module_info(self):
        info("info message")
 
    def try_logging_module_debug(self):
        debug("debug message")
 
    def try_logging_module_warning(self):
        warn("warning message")
 
    def try_logging_module_error(self):
        error("error message")
        assert False

Samotný testovací scénář mohl zůstat prakticky nezměněn, bylo nutné pouze modifikovat jméno zdrojového souboru s definicí nových klíčových slov:

*** Settings ***
Library         Test14.py
 
*** Test Cases ***
Log1
    Try Logging Module Info
    Try Logging Module Debug
 
Log2
    Try Logging Module Debug
    Try Logging Module Warning
 
Log3
    Try Logging Module Debug
    Try Logging Module Error

Po spuštění testů je již sémantika vylepšena – za zprávou vypsanou do logu pomocí funkce logging.error skutečně následuje pád daného test casu:

==============================================================================
Test14
==============================================================================
Log1                                                                  | PASS |
------------------------------------------------------------------------------
Log2                                                                  | PASS |
------------------------------------------------------------------------------
Log3                                                                  | FAIL |
AssertionError
------------------------------------------------------------------------------
Test14                                                                | FAIL |
3 critical tests, 2 passed, 1 failed
3 tests total, 2 passed, 1 failed
==============================================================================
Output:  /home/tester/src/Python/robot-framework-examples/article01/output.xml
Log:     /home/tester/src/Python/robot-framework-examples/article01/log.html
Report:  /home/tester/src/Python/robot-framework-examples/article01/report.html

Obrázek 14: Pohled na výsledky běhu testu.

Obrázek 15: Podrobnější pohled na test case, který zhavaroval.

17. První skutečný testovací scénář – test funkce kalkulačky

Předchozí příklady byly poměrně umělé, protože jsme si potřebovali ukázat základní vlastnosti Robot Frameworku. Ukažme si tedy nyní první skutečný testovací scénář, v němž budeme testovat operátor součtu. Pro tento účel budou vytvořena dvě klíčová slova Add a Result Should Be. První klíčové slovo bude akceptovat dva parametry, které sečte a uloží do kontextu (ten je představován vlastní instancí třídy Test16). Druhé klíčové slovo porovná vypočtený výsledek s očekávaným výsledkem a v případě neshody způsobí pád příslušného test casu:

class Test15:
    def __init__(self):
        print("INIT")
 
    def add(self, x, y):
        self.result = x + y
 
    def result_should_be(self, expected):
        assert self.result == expected, "{} != {}".format(self.result, expected)

Testovací scénář bude rozsáhlejší, protože v něm budeme zjišťovat výsledky tří operací součtu:

*** Settings ***
Library         Test15.py

*** Test Cases ***
Adder #1
    Add  1  2
    Result should be  3

Adder #2
    Add  0  0
    Result should be  0

Adder #3
    Add  1  -1
    Result should be  0

Spuštění tohoto scénáře může být zklamáním, protože všechny tři test casy zhavarují:

==============================================================================
Test15
==============================================================================
Adder #1                                                              | FAIL |
12 != 3
------------------------------------------------------------------------------
Adder #2                                                              | FAIL |
00 != 0
------------------------------------------------------------------------------
Adder #3                                                              | FAIL |
1-1 != 0
------------------------------------------------------------------------------
Test15                                                                | FAIL |
3 critical tests, 0 passed, 3 failed
3 tests total, 0 passed, 3 failed
==============================================================================
Output:  /home/tester/src/Python/robot-framework-examples/article01/output.xml
Log:     /home/tester/src/Python/robot-framework-examples/article01/log.html
Report:  /home/tester/src/Python/robot-framework-examples/article01/report.html

Z vygenerovaných chybových zpráv lze snadno odvodit, kde nastala chyba: parametry byly do metod předány jako řetězce a operátorem + došlo ke spojení těchto řetězců, nikoli k součtu.

Obrázek 16: Celkový pohled na výsledky testů.

Obrázek 17: Podrobnější pohled na výsledky testů.

Celý testovací scénář můžeme zapsat i ve formě tabulky, což může být v mnoha případech lepší způsob. Povšimněte si, že parametry klíčových slov musí být umístěny do zvláštních sloupců:

| *** Settings ***   |                  |   |
| Library            | Test16.py        |   |
 
| *** Test Cases *** |                  |   |
| Adder #1           |                  |   |
|                    | Add              | 1 | 2
|                    | Result should be | 3 |
|                    | Add              | 2 | 3
|                    | Result should be | 5 |
|                    | Add              | 4 | 5
|                    | Result should be | 9 |
 
| Adder #2           |                  |   |
|                    | Add              | 0 | 0
|                    | Result should be | 0 |
 
| Adder #3           |                  |   |
|                    | Add              | 1 | -1
|                    | Result should be | 0 |

18. Korektní práce s parametry klíčových slov

Úprava námi vytvořených klíčových slov takovým způsobem, aby se jejich parametry zpracovávaly jako celá čísla (popř. čísla s plovoucí řádovou čárkou), je v Pythonu relativně přímočará. Použijeme konverzní funkci int a ponecháme na této funkci, aby v případě špatného vstupu vyhodila výjimku typu ValueError:

class Test16:
    def __init__(self):
        pass
        print("INIT")
 
    def add(self, x, y):
        self.result = int(x) + int(y)
 
    def result_should_be(self, expected):
        assert self.result == int(expected), "{} != {}".format(self.result, expected)

Samotný testovací scénář zůstane prakticky nezměněn:

*** Settings ***
Library         Test16.py
 
*** Test Cases ***
Adder #1
    Add  1  2
    Result should be  3
 
Adder #2
    Add  0  0
    Result should be  0
 
Adder #3
    Add  1  -1
    Result should be  0

Výsledky ovšem již budou odpovídat tomu, že skutečně testujeme funkci operátoru pro součet dvou čísel a nikoli pro spojení dvou řetězců:

==============================================================================
Test16
==============================================================================
Adder #1                                                              | PASS |
------------------------------------------------------------------------------
Adder #2                                                              | PASS |
------------------------------------------------------------------------------
Adder #3                                                              | PASS |
------------------------------------------------------------------------------
Test16                                                                | PASS |
3 critical tests, 3 passed, 0 failed
3 tests total, 3 passed, 0 failed
==============================================================================
Output:  /home/tester/src/Python/robot-framework-examples/article01/output.xml
Log:     /home/tester/src/Python/robot-framework-examples/article01/log.html
Report:  /home/tester/src/Python/robot-framework-examples/article01/report.html

Obrázek 18: Celkový pohled na výsledky testů.

bitcoin_skoleni

Obrázek 19: Podrobnější pohled na výsledky testů.

19. Repositář s demonstračními příklady

Zdrojové kódy všech dnes použitých demonstračních příkladů byly uloženy do Git repositáře, který je dostupný na adrese https://github.com/tisnik/robot-framework-examples (stále na GitHubu :-). V případě, že nebudete chtít klonovat celý repositář, můžete namísto toho použít odkazy na jednotlivé příklady, které naleznete v následující tabulce:

# Příklad Stručný popis Cesta
1 test01.robot základní formát testovacího scénáře https://github.com/tisnik/robot-framework-examples/blob/master/arti­cle01/test01.robot
2 test02.robot chybný formát (špatný oddělovač) https://github.com/tisnik/robot-framework-examples/blob/master/arti­cle01/test02.robot
3 test03.robot použití znaku Tab namísto mezer https://github.com/tisnik/robot-framework-examples/blob/master/arti­cle01/test03.robot
4 test04.robot zvýraznění tabulkového formátu testů https://github.com/tisnik/robot-framework-examples/blob/master/arti­cle01/test04.robot
5 test05.robot formát založený na TSV https://github.com/tisnik/robot-framework-examples/blob/master/arti­cle01/test05.robot
6 test06.robot více test casů v jediném scénáři https://github.com/tisnik/robot-framework-examples/blob/master/arti­cle01/test06.robot
7 test07.robot zvýraznění tabulkového formátu testů https://github.com/tisnik/robot-framework-examples/blob/master/arti­cle01/test07.robot
8 test08.robot test case, který po svém spuštění zhavaruje https://github.com/tisnik/robot-framework-examples/blob/master/arti­cle01/test08.robot
9 test09.robot klíčové slovo Repeat Keyword https://github.com/tisnik/robot-framework-examples/blob/master/arti­cle01/test09.robot
       
10 Test10.py definice nového klíčového slova https://github.com/tisnik/robot-framework-examples/blob/master/arti­cle01/Test10.py
11 test10.robot použití nového klíčového slova https://github.com/tisnik/robot-framework-examples/blob/master/arti­cle01/test10.robot
       
12 Test11.py klíčové slovo způsobující pád test casu https://github.com/tisnik/robot-framework-examples/blob/master/arti­cle01/Test11.py
13 test11.robot použití nového klíčového slova https://github.com/tisnik/robot-framework-examples/blob/master/arti­cle01/test11.robot
       
14 Test12.py klíčové slovo definované jako metoda https://github.com/tisnik/robot-framework-examples/blob/master/arti­cle01/Test12.py
15 test12.robot použití nového klíčového slova https://github.com/tisnik/robot-framework-examples/blob/master/arti­cle01/test12.robot
       
16 Test13.py různé typy logovacích zpráv https://github.com/tisnik/robot-framework-examples/blob/master/arti­cle01/Test13.py
17 test13.robot použití nových klíčových slov https://github.com/tisnik/robot-framework-examples/blob/master/arti­cle01/test13.robot
       
18 Test14.py různé typy logovacích zpráv + použití aserce https://github.com/tisnik/robot-framework-examples/blob/master/arti­cle01/Test14.py
19 test14.robot použití nových klíčových slov https://github.com/tisnik/robot-framework-examples/blob/master/arti­cle01/test14.robot
       
20 Test15.py první implementace kalkulačky (chybný způsob) https://github.com/tisnik/robot-framework-examples/blob/master/arti­cle01/Test15.py
21 test15.robot test kalkulačky https://github.com/tisnik/robot-framework-examples/blob/master/arti­cle01/test15.robot
       
22 Test16.py první implementace kalkulačky (korektní způsob) https://github.com/tisnik/robot-framework-examples/blob/master/arti­cle01/Test16.py
23 test16.robot test kalkulačky https://github.com/tisnik/robot-framework-examples/blob/master/arti­cle01/test16.robot

20. Odkazy na Internetu

  1. Stránka projektu Robot Framework
    https://robotframework.org/
  2. GitHub repositář Robot Frameworku
    https://github.com/robotfra­mework/robotframework
  3. Robot Framework (Wikipedia)
    https://en.wikipedia.org/wi­ki/Robot_Framework
  4. Tutoriál Robot Frameworku
    http://www.robotframeworktu­torial.com/
  5. Robot Framework Documentation
    https://robotframework.or­g/robotframework/
  6. Robot Framework Introduction
    https://blog.testproject.i­o/2016/11/22/robot-framework-introduction/
  7. robotframework 3.1.2 na PyPi
    https://pypi.org/project/ro­botframework/
  8. Robot Framework demo (GitHub)
    https://github.com/robotfra­mework/RobotDemo
  9. Robot Framework web testing demo using SeleniumLibrary
    https://github.com/robotfra­mework/WebDemo
  10. Robot Framework for Mobile Test Automation Demo
    https://www.youtube.com/wat­ch?v=06LsU08slP8
  11. Selenium
    https://selenium.dev/
  12. SeleniumLibrary
    https://robotframework.org/
  13. The Practical Test Pyramid
    https://martinfowler.com/ar­ticles/practical-test-pyramid.html
  14. Acceptance Tests and the Testing Pyramid
    http://www.blog.acceptance­testdrivendevelopment.com/ac­ceptance-tests-and-the-testing-pyramid/
  15. Programovací jazyk Clojure – testování s využitím knihovny Expectations
    https://www.root.cz/clanky/pro­gramovaci-jazyk-clojure-testovani-s-vyuzitim-knihovny-expectations/
  16. Programovací jazyk Clojure – některé užitečné triky použitelné (nejenom) v testech
    https://www.root.cz/clanky/pro­gramovaci-jazyk-clojure-nektere-uzitecne-triky-pouzitelne-nejenom-v-testech/
  17. Použití jazyka Gherkin při tvorbě testovacích scénářů pro aplikace psané v Clojure
    https://www.root.cz/clanky/pouziti-jazyka-gherkin-pri-tvorbe-testovacich-scenaru-pro-aplikace-psane-v-nbsp-clojure/
  18. Tab-separated values
    https://en.wikipedia.org/wiki/Tab-separated_values
  19. A quick guide about Python implementations
    https://blog.rmotr.com/a-quick-guide-about-python-implementations-aa224109f321
  20. Python 2.7 will retire in…
    https://pythonclock.org/

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.