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.
Don't miss out on the latest updates.
Fill in your email address to stay informed about upcoming training sessions, events, and testing know-how.
Need Advice?
Request our free, non-sales consultation. Fill out the form and we will get back to you.
Watchdog
Did not find a date that works for you? ....
Notice