Lembro do primeiro projeto grande de automacao que peguei: uma suite com 200+ casos de teste em Robot Framework, todos usando variaveis soltas — ${nome_usuario}, ${email_usuario}, ${senha_usuario}, ${telefone_usuario} — passadas uma a uma como argumento para cada keyword. Era um inferno dar manutencao. Quando descobri dicionarios, foi como um interruptor na minha cabeca: o codigo ficou mais limpo, mais facil de ler e muito mais simples de evoluir. Desde entao, uso dicionarios em tudo que faco — Robot Framework, Python, TypeScript, Java. Este artigo mostra o porque e o como.
Se voce trabalha com automacao de testes, ja deve ter enfrentado o problema: variaveis demais, argumentos que nao param de crescer, codigo dificil de dar manutencao. Dicionarios resolvem isso de forma elegante. Neste guia, vou mostrar o que sao, como usar em cada framework/linguagem, e — mais importante — como fica o codigo sem dicionario para voce sentir a diferenca.
O que e um Dicionario?
Um dicionario e uma estrutura de dados chave-valor (key-value pair). Cada elemento tem uma chave unica associada a um valor. Em vez de ter nome = "Victor", email = "victor@teste.com" e senha = "123456" como variaveis soltas, voce agrupa tudo em um unico objeto:
USUARIO = {"nome": "Victor", "email": "victor@teste.com", "senha": "123456"}
Por que isso e util em automacao de testes?
- Agrupar massa de dados: dados de um usuario, configuracao de ambiente, headers de API — tudo num lugar so
- Reduzir parametros: uma funcao que recebe 5 parametros vira uma funcao que recebe 1 dicionario
- Facilitar data-driven testing: cada linha de massa vira um dicionario na lista
- Melhorar legibilidade:
usuario["email"]e mais claro queemail_usuario_1 - Flexibilidade: adicionar um novo campo nao quebra assinatura de funcao
Robot Framework: &{Dicionarios} com Collections
No Robot Framework, dicionarios sao representados pelo tipo &{} e manipulados pelas keywords da biblioteca Collections (ja embutida, sem instalacao extra).
Criando e acessando dicionarios
*** Settings ***
Library Collections
*** Variables ***
&{USUARIO} nome=Victor email=victor@teste.com senha=123456
*** Test Cases ***
Acessar Dicionario
Log Nome: ${USUARIO.nome}
Log Email: ${USUARIO.email}
Principais keywords de dicionario
*** Test Cases ***
Manipular Dicionario
&{pessoa} Create Dictionary nome=Maria idade=30
Set To Dictionary ${pessoa} email=maria@email.com
${nome} Get From Dictionary ${pessoa} nome
Should Be Equal ${nome} Maria
Dictionary Should Contain Key ${pessoa} idade
Dictionary Should Contain Item ${pessoa} nome Maria
Remove From Dictionary ${pessoa} idade
Dictionary Should Not Contain Key ${pessoa} idade
${chaves} Get Dictionary Keys ${pessoa}
${valores} Get Dictionary Values ${pessoa}
${itens} Get Dictionary Items ${pessoa}
Log Dictionary ${pessoa}
Exemplo pratico: massa de dados de usuario
*** Settings ***
Library Collections
*** Variables ***
&{USUARIO_VALIDO} nome=Victor email=victor@teste.com senha=123456
&{USUARIO_INVALIDO} nome= email=invalido senha=123
*** Keywords ***
Fazer Login
[Arguments] &{usuario}
Log Email: ${usuario.email}, Senha: ${usuario.senha}
# Aqui iria a acao de login real
Should Not Be Empty ${usuario.email}
*** Test Cases ***
Login Com Sucesso
Fazer Login &{USUARIO_VALIDO}
Login Com Email Invalido
Fazer Login &{USUARIO_INVALIDO}
Sem dicionario: como ficaria
*** Variables ***
${USUARIO_NOME} Victor
${USUARIO_EMAIL} victor@teste.com
${USUARIO_SENHA} 123456
*** Keywords ***
Fazer Login
[Arguments] ${nome} ${email} ${senha}
Log Nome: ${nome}, Email: ${email}
*** Test Cases ***
Login Com Sucesso
Fazer Login ${USUARIO_NOME} ${USUARIO_EMAIL} ${USUARIO_SENHA}
Problemas da abordagem sem dicionario:
- Se adicionar
${USUARIO_TELEFONE}, precisa mudar a keywordFazer Logine todas as chamadas - Argumentos sao posicionais — facil inverter ${nome} com ${email}
- Poluicao de variaveis no espaco global
- Dados de um mesmo dominio ficam espalhados
Com dicionario, adicionar telefone e so inserir no &{USUARIO} — a keyword continua recebendo um unico argumento.
Python: dict em automacao com pytest
Em Python, dicionarios sao nativos e onipresentes. Para automacao de testes com pytest, eles sao perfeitos para fixtures e data-driven tests.
import pytest
# Massa de dados como dicionario
USUARIO_VALIDO = {
"nome": "Victor",
"email": "victor@teste.com",
"senha": "123456"
}
USUARIO_INVALIDO = {
"nome": "",
"email": "invalido",
"senha": "123"
}
def fazer_login(usuario):
assert usuario["email"], "Email nao pode ser vazio"
print(f"Logando {usuario['nome']} com email {usuario['email']}")
return {"status": 200, "token": "abc123"}
@pytest.mark.parametrize("usuario", [USUARIO_VALIDO, USUARIO_INVALIDO])
def test_login(usuario):
resultado = fazer_login(usuario)
assert resultado["status"] == 200
Sem dicionario: o pesadelo dos parametros
def fazer_login(nome, email, senha):
assert email, "Email nao pode ser vazio"
print(f"Logando {nome} com email {email}")
@pytest.mark.parametrize("nome,email,senha", [
("Victor", "victor@teste.com", "123456"),
("", "invalido", "123")
])
def test_login(nome, email, senha):
resultado = fazer_login(nome, email, senha)
Percebeu a diferenca? Quando o teste tem 2 parametros, ate vai. Quando tem 8 (usuario com endereco, telefone, data de nascimento...), a versao com dicionario continua limpa; a sem, vira uma bagunça.
Bonus: dicionario aninhado para dados complexos
USUARIO_COMPLETO = {
"pessoal": {
"nome": "Victor",
"email": "victor@teste.com"
},
"endereco": {
"rua": "Av. Paulista",
"numero": 1000,
"cidade": "Sao Paulo"
},
"preferencias": {
"newsletter": True,
"tema": "escuro"
}
}
print(USUARIO_COMPLETO["endereco"]["cidade"]) # Sao Paulo
TypeScript: objetos e Map com Playwright
No ecossistema TypeScript/JavaScript, usamos objetos literais {} ou Map para dicionarios. Com Playwright, eles sao ideais para configurar navegadores, armazenar dados de teste e parametrizar acoes.
import { test, expect } from "@playwright/test";
interface Usuario {
nome: string;
email: string;
senha: string;
}
const USUARIO_VALIDO: Usuario = {
nome: "Victor",
email: "victor@teste.com",
senha: "123456"
};
async function fazerLogin(page: any, usuario: Usuario) {
await page.fill("[data-testid=email]", usuario.email);
await page.fill("[data-testid=senha]", usuario.senha);
await page.click("[data-testid=entrar]");
}
test("login com sucesso", async ({ page }) => {
await page.goto("/login");
await fazerLogin(page, USUARIO_VALIDO);
await expect(page.locator("[data-testid=bem-vindo]")).toContainText("Victor");
});
// Data-driven com array de dicionarios
test.describe("login data-driven", () => {
const usuarios = [
{ nome: "Victor", email: "victor@teste.com", senha: "123456", valido: true },
{ nome: "", email: "invalido", senha: "123", valido: false }
];
for (const usuario of usuarios) {
test("login com ${usuario.nome}", async ({ page }) => {
await page.goto("/login");
await fazerLogin(page, usuario);
if (usuario.valido) {
await expect(page.locator(".boas-vindas")).toBeVisible();
}
});
}
});
Sem dicionario multiplas variaveis
const nome = "Victor";
const email = "victor@teste.com";
const senha = "123456";
async function fazerLogin(page: any, nome: string, email: string, senha: string) {
await page.fill("[data-testid=email]", email);
await page.fill("[data-testid=senha]", senha);
}
// Chamada com 4 argumentos — facil errar a ordem
test("login", async ({ page }) => {
await fazerLogin(page, nome, email, senha);
});
Com o dicionario tipado (interface Usuario), o TypeScript ainda te da autocomplete e validacao em tempo de compilacao. Se esquecer um campo, o compilador avisa.
Java: HashMap com Selenium WebDriver
Em Java, usamos Map<String, String> (normalmente HashMap) como dicionario. No Selenium WebDriver, e amplamente usado para parametrizar testes, especialmente com DataProvider.
import java.util.HashMap;
import java.util.Map;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class LoginTest {
public void fazerLogin(WebDriver driver, Map<String, String> usuario) {
driver.findElement(By.id("email")).sendKeys(usuario.get("email"));
driver.findElement(By.id("senha")).sendKeys(usuario.get("senha"));
driver.findElement(By.id("entrar")).click();
}
@DataProvider(name = "usuarios")
public Object[][] getUsuarios() {
Map<String, String> usuario1 = new HashMap<>();
usuario1.put("nome", "Victor");
usuario1.put("email", "victor@teste.com");
usuario1.put("senha", "123456");
Map<String, String> usuario2 = new HashMap<>();
usuario2.put("nome", "");
usuario2.put("email", "invalido");
usuario2.put("senha", "123");
return new Object[][]{{usuario1}, {usuario2}};
}
@Test(dataProvider = "usuarios")
public void testLogin(Map<String, String> usuario) {
System.out.println("Logando: " + usuario.get("nome"));
// Driver e acoes viriam aqui
}
}
Sem dicionario: DataProvider inchado
@DataProvider(name = "usuarios")
public Object[][] getUsuarios() {
return new Object[][]{
{"Victor", "victor@teste.com", "123456"},
{"", "invalido", "123"}
};
}
@Test(dataProvider = "usuarios")
public void testLogin(String nome, String email, String senha) {
System.out.println("Logando: " + nome);
}
O problema e o mesmo: adicionar um campo significa mudar a assinatura do metodo, o DataProvider e todas as chamadas. Com Map, voce adiciona um put e pronto.
Tabela Comparativa: Com vs Sem Dicionario
| Aspecto | Sem Dicionario | Com Dicionario |
|---|---|---|
| Quantidade de variaveis | 5 variaveis soltas para 5 campos | 1 variavel com 5 campos |
| Adicionar novo campo | Mudar assinatura da funcao + todas as chamadas | Só adicionar ao dicionario |
| Parametros de funcao/keyword | 5+ argumentos posicionais | 1 argumento (dicionario) |
| Risco de inverter valores | Alto (argumentos posicionais) | Baixo (acesso por chave nomeada) |
| Data-driven testing | Tupla gigante com N colunas | Array de dicionarios — legivel e flexivel |
| Legibilidade | {usuario["email"]} — claro | Precisa lembrar a ordem dos parametros |
| Acoplamento | Baixo — dados e funcao acoplados por posicao | Baixo — dicionario desacopla dados da funcao |
Quando usar dicionario (e quando nao usar)
Use dicionario quando:
- Massa de dados: dados de usuario, configuracao de ambiente, headers de requisicao
- Data-driven testing: cada cenario e um dicionario numa lista
- Retorno de keywords/funcoes: uma keyword que precisa retornar multiplos valores
- Dados aninhados: estruturas complexas (usuario com endereco, preferencias etc.)
- APIs: payloads de requisicao e resposta sao dicionarios por natureza
Nao use dicionario quando:
- Dado simples e obvio: um unico ID, um nome simples — variavel direta e suficiente
- Performance critica: acesso direto a campo e mais rapido que hash lookup
- Perda de tipagem forte: em Java/TypeScript, prefira objetos tipados (interfaces/POJOs) a Map
quando o schema e fixo
Conclusao
Dicionarios sao uma das ferramentas mais uteis na caixa de ferramentas de um QA de automacao. Eles organizam dados, reduzem complexidade de assinaturas de metodos, facilitam data-driven testing e tornam o codigo mais facil de ler e manter.
Nao importa se voce usa Robot Framework, Python com pytest, TypeScript com Playwright ou Java com Selenium — o conceito e o mesmo: agrupar dados relacionados em uma unica estrutura chave-valor. A diferença entre um codigo que usa dicionarios e um que nao usa e a mesma entre uma caixa de ferramentas organizada e uma gaveta de coisas soltas.
Comece a usar dicionarios nos seus testes hoje. Seu eu do futuro — e seu time — vao agradecer.