Tomáš Hák
Test automation specialist
Blog
Tomáš Hák
Test automation specialist
Robot Framework je často používaným nástrojem pro automatizaci u nás v Teseně. Máme s ním bohaté zkušenosti z nejrůznějších projektů, ať už testování webových stránek, API a DB na backendu, nebo embedded zařízení či desktop a mobilních aplikací. Komunita kolem tohoto frameworku je velice rozsáhlá, kdy jsme sami jako Tesena členové Robot Framework Foundation. V rámci komunity probíhá intenzivní vývoj samotného frameworku a desítek rozšířujících knihoven. Sledovat všechno je velice obtížné, proto bych rád v tomto článku shrnul nejdůležitější novinky posledních dvou větších verzí, konkrétně 7.3 a 7.4. Pojďme na to.
Podtitul by mohl znít "typování proměných". Sice byla implementována řada dalších změn, jako stabilizace timeoutů, podpora Python 3.14, oprava JSON výstupů a embeded argumentů, ale to hlavní se týká právě možnosti nastavení typu proměnné, které lze použít v testu.
Abychom si vyjasnili, proč je toto tak důležitá změna, tak je třeba vědět, že dosud v RF, když jste vytvořili proměnnou, naplnili jste jí hodnotou, ale samotný typ proměnné se určil na základě jejího obsahu. Bylo proto nutné např. přetypovat na integer, protože se číslo mohlo interpretovat i jako string. Například to mohlo vypadat takto:
*** Test Cases ***
Example Without Types
${count}= Set Variable 10
${result}= Evaluate ${count} + 1
Log ${result}
Toto vypadá v pořádku, ale RF číslo 10 bral jako string. Mohlo se to řešit tak, že se to číslo definuje jako:
${count} Set Variable ${10}
Tedy syntaxí přes dolar a složené závorky. Případně si šlo pomoci konverzí na typ:
${count}= Convert To Integer ${count}
Bylo tedy komplikovanější si hlídat správné typy a nebo bylo třeba provádět přetypování. Celkově to ale prodlužovalo a znepřehledňovalo kód. Právě od verze 7.3 lze už při vytváření proměnné definovat její typ a s ním následně už můžeme počítat dále v kódu. Zde přepsaný stejný příklad jako výše:
*** Variables ***
${COUNT:int} 10
*** Test Cases ***
Example With Types
${result}= Evaluate ${COUNT} + 1
Log ${result}
Úplně stejně nyní lze typovat proměnné i jako vstupy keywordů. Opět prakticky příklad:
*** Keywords ***
Multiply
[Arguments] ${a:int} ${b:int}
${result}= Evaluate ${a} * ${b}
RETURN ${result}
Proměnné na vstupu se tak automaticky konvertují a pokud je vstup nevalidní, např. pokusíme se zadat textový řetězec nebo typ slovník, klíčové slovo vyvolá srozumitelnou chybu.
Samozřejmě typovat lze i proměnné použité ve FOR cyklu, nebo například při definování pole nebo proměnné typu slovník.
*** Variables ***
${VERSION: float} 7.3
${CRITICAL: list[int]} [3278, 5368, 5417]
@{HIGH: int} 4173 5334 5386 5387
&{DATES: date} rc1=2025-05-08 final=2025-05-15
&{NUMBERS: int=float} 1=2.3 4=5.6
FOR loop
FOR ${fib: int} IN 0 1 1 2 3 5 8 13
Log ${fib}
END
A poslední možnost, kterou bych zde rád zmínil, je typování hodnot, které zadáváme přes příkazovou řádku jako parametr --variable. Např.
--variable "BODY: dict:{'id': 3, 'surname': 'Robot'}"
--variable "START_TIME: datetime:now"
Typováním proměnných se psaní skriptu opět posunulo více skriptování v Pythonu a umožňuje nám lépe pracovat s hodnotami v testu. Zvolit můžeme notoricky známé typy jako float, int, boolean, date, datetime, list, dict a další.
A proč ještě je typování důležité? Umožní nám to odchytit chyby dříve, než až v Evaluate nebo běhu keywordu. Také ty chyby nevznikají náhodně podle toho jaká data zrovna dostaneme a zamezíme pracnému hledání příčíny. Celý kód je čitelnější , nemusíme řešit vlastní konverze, psaní apostrofů při vyhodnocování proměnných v IF podmínkách a ihned víme, co keyword očekává na vstupu a jaká je defaultní hodnota.
Tato verze obsahuje několik dílčích vylepšení a některé přístupy jsou označeny jako deprecated. Např. nově prázdnou proměnou lze pomocí VAR definovat jen pro scope=local. Pro ostatní (Test,Suite,Global) je třeba definovat hodnotu, nebo použít jako hodnotu ${EMPTY} .
Další změnou je rozšíření typování z verze 7.3 na některé standardní knihovny. Nově si knihovny a jejich KW kontrolují vstupní proměnné. Vše je pak čitelnější v Libdoc a vždy je pak uveden očekávaný typ.
Robot Framework 7.4 hlavně přináší „secret variables“ – proměnné určené pro práci s citlivými hodnotami (hesla, tokeny, klíče), které se automaticky maskují v output.xml, logu i reportu. Důležité je, že nejde o šifrování - hodnota se pouze „zapouzdří“ tak, aby se při běžném logování a předávání mezi keywordy nezobrazovala. V logu se pak místo skutečné hodnoty typicky objeví jen zástupná reprezentace (např. ). Skutečná hodnota je dostupná přes atribut .value (a dá se tedy získat v Python knihovnách nebo přes rozšířenou syntaxi), což je praktické, ale zároveň to znamená, že kdo má přístup k proměnné přes API/kód, hodnotu získat může.
V praxi se secret proměnné hodí hlavně ve chvíli, kdy nějaký keyword přijímá tajný údaj a dál ho posílá (např. do knihovny, do HTTP klienta, do DB konektoru). Bez secrets je častý problém, že se citlivá data „omylem“ objeví v trace logu, protože Robot Framework loguje argumenty/return values. Se secrets se zlepší bezpečnost citlivých dat, tedy hodnota se neschová jen v jednom keywordu, ale zůstává „tajná“ i při předávání dál. Současně v 7.4 některé standardní knihovny (např. OperatingSystem a Process) umí se secret hodnotami pracovat tak, aby je samy neprozradily v logu.
Praktický příklad, kdy použijeme tajný token z env. proměnné a předáme ho do keywordu, který ho použije, ale nebude ho nikde logovat.
*** Settings ***
Library AuthLibrary.py
*** Variables ***
${BASE_URL} https://api.example.test
${API_TOKEN: Secret} %{API_TOKEN}
*** Test Cases ***
Call API With Secret Token
Ping API ${BASE_URL} ${API_TOKEN}
from robot.api import logger
from robot.api.types import Secret
import requests
class AuthLibrary:
def ping_api(self, base_url: str, token: Secret):
# token se v logu nikdy nevypíše jako reálná hodnota
logger.info("Pinging API with bearer token (masked).")
headers = {"Authorization": f"Bearer {token.value}"}
r = requests.get(f"{base_url}/ping", headers=headers, timeout=10)
r.raise_for_status()
return r.text
Tady je podstatné, že v logu se nebude objevovat obsah tokenu, i když ho posíláte mezi keywordy – a v Pythonu si ho vytáhnete přes token.value až v místě, kde ho opravdu potřebujete..
Další zajímavý příklad je, když testujete databázi a na začátku testu se chcete k databázi připojit. Tedy složit connection string, jehož součástí je i heslo.
*** Variables ***
${DB_USER} appuser
${DB_PASS: Secret} %{DB_PASSWORD}
${DB_HOST} db.internal
${DB_PORT} 5432
*** Test Cases ***
Build Connection String Safely
# poskládáme DSN; heslo je secret, takže výsledný celek by se měl chovat bezpečně
${dsn: Secret}= Set Variable postgresql://${DB_USER}:${DB_PASS}@${DB_HOST}:${DB_PORT}/app
Connect Using DSN ${dsn}
Verze 7.5 je plánována na červen. Zatím se nedá jistě říci, co vše bude obsahovat. Ale v Githubu existuje štítek/milník 7.5, kde je vidět, na čem všem se pracuje a má ambici se do verze dostat. Vše je dostupné zde: https://github.com/robotframework/robotframework/milestone/82 . Hodně je tam zmíněná práce na dokumentaci (testů, suit a keywordů), hlavně možnost Markdown a HTML formátu, oddělení dokumentace pro argumenty a návratové hodnoty. Také se řeší metadata, výkon (zrychlení) vyhodnocení proměnných a práce se scope proměnných. Myslím, že to opět zlepší práci s psaním testů a na novinky se v létě zaměříme v dalším článku.
A co z nových funkcí využíváte na svém projektu nejčastěji vy? Napište mi.
Nenechejte si ujít nejnovější informace.
Vyplňte nám vaši e-mailovou adresu a dostávejte pravidelnou nálož informací ohledně nadcházejících kurzů, akcí a testingového know-how.
Chcete poradit?
Napište si o naši bezplatnou, neprodejní konzultaci zdarma. Vyplňte formulář a my se vám ozveme zpět.
Hlídací pes
Nenašeli jste termín, který by vám vyhovoval? ....
Upozornění