Recentemente, mudei o projeto - cheguei a um novo desenvolvimento, onde antes de mim não havia testes, manuais ou automáticos. O cliente não impôs condições no kit de ferramentas (exceto que era Python), então eu fiz minha própria escolha. Neste artigo, explicarei por que, nessas condições, escolhi o Robot Framework. E no final, haverá alguns exemplos especialmente escritos para o artigo que ilustram o que estamos falando.

Faço automação de teste há mais de 10 anos, e cerca de três deles interagiram com o Robot Framework.
Como observei acima, há pouco tempo cheguei a um novo projeto, onde comecei a testar a automação do zero. Não posso falar sobre o projeto - NDA. Observo apenas que esta é uma ferramenta legal de automação, que no futuro deve economizar muitos recursos humanos. É construído a partir de microsserviços. Até agora, meu trabalho diz respeito a quatro deles, mas no futuro expandirei minhas atividades para outras pessoas - tudo se resume ao fato de eu ter apenas 8 horas de trabalho por dia. Tudo leva tempo.
A falta de teste no caso deste projeto foi idêntica à falta de ferramentas recomendadas. Como parte da pilha Python, eu tinha liberdade de escolha. E eu tirei vantagem disso.
Por que o Robot Framework?
Eu acho que posso ser atribuído aos fãs do Robot Framework. Parece-me que quase tudo pode ser feito.
Em outros projetos, a empresa usa pytest. No entanto, na minha opinião, ele não possui esses recursos, pois é limitado pelos recursos do Python. Você acabou de escrever o código Python e observe que espera um certo valor nessa variável. Para o meu gosto, é simples, mas abstrato demais. Muito ficou à mercê do desenvolvedor, que precisará adicionar todos os recursos úteis à mão. O Robot Framework faz isso sozinho. Aqui estão quatro pontos que vale a pena levar para o seu projeto.
Flexibilidade
O próprio Robot Framework é escrito em Python (ou seja, ele pode fazer tudo o que o Python pode) e, para isso, existem muitas bibliotecas criadas pela comunidade, o que expande bastante a gama de problemas a serem resolvidos.
Sob o Robot Framework, você pode escrever facilmente suas próprias bibliotecas, integrando-as a quase tudo, e tudo funcionará imediatamente. Não são necessárias muletas ou bicicletas.
Além disso, o Robot Framework permite que você escreva testes paramétricos (modelos), o que acelera bastante o trabalho da ferramenta de automação.
Língua russa em testes
Um dos pontos fundamentais é que a palavra-chave (análogos de métodos convencionais no Robot Framework, que por algum motivo historicamente é chamada dessa maneira) pode ser escrita em russo. Como resultado, os textos dos testes estão, é claro, longe da linguagem literária, mas à primeira vista fica claro o que está acontecendo lá. Antes de tudo, isso é necessário não pelos desenvolvedores finais, mas, por exemplo, pelas partes interessadas. Eles podem abrir os testes de forma independente e ver o que exatamente acontece lá: "Selecione um elemento aleatório de ...", etc.
Marcação
O Robot Framework funciona bem com tags. Você não pode apenas executar testes com uma tag específica, mas também analisar relatórios com a ajuda deles. O arquivo de log contém estatísticas sobre tags, com base nas quais você pode executar alguma ação se pensar sobre a organização das tags com antecedência.
Convenientemente, você não precisa escrever todas as tags em um longo calçado em cada teste, mas pode incorporar testes em uma estrutura em árvore. No meu caso, fica assim: o primeiro nível é um microsserviço, o segundo é o tipo de teste, o terceiro é o próprio teste (é conveniente colocar um arquivo init contendo tags para o que está incorporado dentro).
Criei uma tag para cada microsserviço, cada abordagem de teste (testes de fumaça, testes CRUD, integração etc.). Eu posso executar testes de um tipo específico ou apenas para um serviço específico. Também identifico o tipo de função - lista ou detalhado. E se o produto responsável pela lista funcionar com "interrupções" no produto, todos os testes com essa tag ficarão vermelhos, independentemente de onde eles estão localizados e com o que eles se relacionam.
Por tags, vinculo autotestes a Jira. Quando o bug do rastreador fecha, e o teste do vermelho fica verde, ainda temos um histórico do que exatamente mudou. Muitos meses depois, se o teste ficar vermelho novamente, podemos ver quais etapas foram tomadas para corrigir o problema da última vez e até assumir que isso levou à repetição do bug.
Outra tag especial que adicionei para erros não críticos. O GitLab não nos permite fazer nada com a compilação se pelo menos um teste falhar. Isso é lógico - até que todos os bugs sejam corrigidos, não podemos lançar um produto ou mesmo um sprint semanal. Mas temos bugs de baixa prioridade e insignificantes. Para eles, selecionei uma tag que permite que o Robot Framework não descarte o conjunto inteiro, a menos que especificamente esses testes (testes com essa tag) falhem.
Great log
A análise de log é parte integrante do teste. Aconteça o que acontecer no momento em que os testes são executados, o Robot Framework escreve absolutamente tudo. Até o momento em que tive que escrever um wrapper especial que oculta o logon e a senha do log para conectar ao banco de dados.
Esses detalhes ajudam a entender muito mais rapidamente qual é o motivo do travamento do teste - o sistema em teste está funcionando incorretamente ou é algo que não é levado em consideração no teste e precisa ser corrigido? A resposta a esta pergunta nem sempre é óbvia. Erros de desenvolvedores e testadores são distribuídos 50/50.
Em outras ferramentas - no mesmo pytest - você pode criar o mesmo log detalhado. Mas a tarefa de gerá-lo recai sobre o desenvolvedor que escreve os testes. Ele precisa pensar em que tipo de entradas de log são realmente necessárias.
O que está no projeto agora
Desde o momento em que comecei a usar o Robot Framework, vários meses se passaram. No momento, o Robot Framework implementou mais de 200 testes e, como mencionado acima, há integração com o GitLab, que ajuda a verificar as alterações feitas no produto desenvolvido (casos de teste com identificadores que permitem vincular autoteste a eles são armazenados no testrail).
Para calcular a cobertura, escrevi um utilitário que pega uma lista de APIs de back-end da Swagger e a compara com o que foi testado. Assim, temos um entendimento claro da cobertura atual. Por exemplo, sabemos que hoje esse microsserviço é coberto por inteiro, enquanto o outro é coberto por 98%. E depois de adicionar novas funcionalidades que ainda não estão refletidas nos testes, a cobertura cai. Dessa forma, você pode planejar que o próximo sprint seja implementado por mim.
Naturalmente, o projeto está se desenvolvendo ainda mais. Por exemplo, agora estamos implantando um servidor simulado (
meu colega já escreveu no Habré sobre o que é e por que é necessário).
Agora para praticar
Os exemplos acima foram projetados especificamente para o artigo ilustrar as idéias acima. Se você quiser experimentar esses exemplos, todos serão publicados
em nosso repositório .
O exemplo de teste mais simples
Vamos começar com o teste mais simples no Robot Framework.
No exemplo abaixo, uma sessão é criada primeiro para um determinado recurso obviamente acessível (no nosso caso,
en.wikipedia.org/wiki ). Ao chamar Get root (/), verificamos o código de status 200.
*** Settings *** Documentation smoke-. Library RequestsLibrary *** Variables *** ${base_url} https://en.wikipedia.org/wiki ${url} / *** Test Cases *** Wiki Create session conn ${base_url} disable_warnings=1 ${response} Get request conn ${url} Delete all sessions Should be equal ${response.status_code} ${200}
Testes de modelo (paramétricos)
O Robot Framework permite criar padrões de teste. Se transferirmos o teste do exemplo anterior para a visualização do modelo, poderemos escalá-lo facilmente adicionando chamadas com os argumentos necessários. Por exemplo, vamos verificar a resposta 200 para páginas com biografias de cientistas.
*** Settings *** Documentation smoke-. . ... . Library RequestsLibrary Test Setup Test Teardown Test Template Smoke- *** Variables *** ${base_url} https://en.wikipedia.org/wiki *** Test Cases *** /Isaac_Newton /Albert_Einstein /Stephen_Hawking *** Keywords *** Create session conn ${base_url} disable_warnings=1 Delete all sessions Smoke- [Arguments] ${url} ${response} Get request conn ${url} Should be equal ${response.status_code} ${200}
Marcando e lendo logs
Continuamos a melhorar o teste mais simples.
Tendo um modelo como um único ponto de entrada, podemos adicionar facilmente a verificação do ano de nascimento do cientista. Dessa forma, confirmamos que a página carregada exibe os dados corretos.
Além disso, no exemplo abaixo, coloquei a palavra-chave existente em nomes russos - para o meu gosto, para que o teste seja mais organizado. Como testador, eu sempre me irritava com métodos chamados "como se estivesse em inglês", mas completamente analfabetos. É sempre melhor escrever no idioma que você conhece.
*** Settings *** Documentation smoke-. . ... . ... . ... . Library RequestsLibrary Test Setup Test Teardown Test Template Smoke- *** Variables *** ${base_url} https://en.wikipedia.org/wiki *** Test Cases *** [Tags] Newton /Isaac_Newton 1642 [Tags] Einstein /Albert_Einstein 1879 [Tags] Hawking /Stephen_Hawking 1942 ( ) [Tags] Numbers /123456789 1899 *** Keywords *** Create session conn ${base_url} disable_warnings=1 Delete all sessions Smoke- [Arguments] ${url} ${expected_word} ${response} Get request conn ${url} Should be equal ${response.status_code} ${200} ... msg= GET ${url} , 200 . ${response.text} ${expected_word} [Arguments] ${text} ${expected_word} Should contain ${text} ${expected_word} msg= ${expected_word}!
Preste atenção em
[Tags]
. Você pode adicionar tags aqui, o que, como escrevi acima, ajudará a avaliar problemas no nível do relatório. Da mesma forma,
Force Tags
no arquivo __init __. Robot (veja o exemplo
em nosso repositório ) permite definir tags para todos os testes no diretório, incluindo os aninhados. Se a marcação for realizada corretamente, sem mesmo ler os nomes dos testes em si e sem rastrear sua lógica, podemos assumir com bastante precisão que ela não funciona no projeto de teste.
Veja o relatório sobre o lançamento desses testes. Para maior clareza, adicionei um teste que encontrará um erro.
As estatísticas do relatório são sua parte mais importante.

No nosso exemplo, os testes com a etiqueta de
numbers
não passaram completamente (temos 1 em 1, mas na vida real haverá, por exemplo, 17 em 20). Pode-se supor que o problema esteja nesta página.
Tags ajudam a executar testes seletivamente. Para executar todos os testes com uma tag específica na linha de inicialização, você deve especificar:
--include <tag>
Até operações lógicas com tags são suportadas:
-- include <tag>AND<tag>
Por exemplo, se você deseja executar apenas o teste de fumaça para testes com a tag de números, adicione:
--include smokeANDnumbers
Testes não críticos
Vamos seguir para truques que simplificam bastante o trabalho.
Depois de marcar o teste com tags, você pode definir um ou mais deles como "não críticos". Um teste com essa tag ainda mostrará erros (se houver), mas, no final, esses erros não serão interpretados como "inválidos". Eu uso essa opção quando alguns bugs menores foram levados em conta, inseridos no rastreador de bugs, mas ainda não foram corrigidos. Sem ele, os autotestes incluídos no IC, após a detecção de problemas conhecidos, não permitirão a montagem do projeto, e isso nem sempre é conveniente.
Adicione um novo teste:
( ) [Tags] Letters Known /abcdefghi 1799
Na inicialização, a tag adicionada é definida como "não crítica" usando a chave:
--noncritical Known
Palavra-chave em python
Com o exemplo a seguir, ilustrarei como adicionar minha biblioteca.
Crie uma nova palavra-chave "Gere uma matriz de números". Seu objetivo é óbvio (para isso eu amo nomes russos).
from random import randint from typing import List from robot.api.deco import keyword class ArrayGeneratorLibrary: ROBOT_LIBRARY_SCOPE = 'GLOBAL' @keyword(" ") def generate_array(self, length: int, minimal: int, maximal: int) -> List[int]: result = [] for i in range(int(length)): result.append(randint(int(minimal), int(maximal))) return result
Conectamos a biblioteca no teste:
Library libraries.ArrayGeneratorLibrary
e use-o:
, python. ${array} ${5} ${2} ${8} Log to console ${array}
Não esqueça que se você tiver uma estrutura aninhada, deve separá-la com pontos, como no exemplo.
Outro truque: os números passados em
${}
são tratados como int, não como strings!
Argumentos em linha
Outra coisa interessante são os argumentos internos, que são passados não no final da ligação, como de costume, mas diretamente em seu corpo.
Para ilustrar, escreveremos um wrapper para o gerador de array criado acima, que permite o uso dos argumentos internos:
${n} , ${from} ${to} ${result} ${n} ${from} ${to} [Return] ${result}
Agora você pode escrever assim:
. ${array} 5 , 2 8 Log to console ${array}
Substituição de parte do nome do método, python insert e loops
O próximo truque que eu realmente gosto sobre o Robot Framework é a substituição de parte do nome. Suponha que tenhamos dois métodos: um seleciona números pares e o outro ímpar.
[Arguments] ${list} ${evens} Evaluate [i for i in $list if i % 2 == 0] [Return] ${evens} [Arguments] ${list} ${odds} Evaluate [i for i in $list if i % 2 != 0] [Return] ${odds}
A palavra-chave
Evaluate
usada acima permite executar uma linha de código python "aqui". Observe que, se você não deseja substituir um pedaço da string pelo conteúdo da variável, ou seja, passar um link para ela, deve especificar o nome da variável imediatamente após o sinal
$
sem chaves!
E assim, você pode chamar os dois métodos, substituindo a parte diferente do nome:
, . . ${types} Create list ${array} 5 , 12 28 FOR ${type} IN @{types} ${numbers} Run keyword ${type} ${array} log to console ${numbers} END
Decoradores de Métodos
Sim, o Robot Framework permite que você escreva um decorador para outras palavras-chave!
Para ilustrar esse recurso, escrevemos um decorador que seleciona números negativos na resposta de qualquer método que retorna uma lista.
, [Arguments] ${keyword} @{args} &{kwargs} ${list} Run keyword ${keyword} @{args} &{kwargs} ${negs} Evaluate [i for i in $list if i < 0] [Return] ${negs}
Observe:
@{args}
são todos argumentos sem nome;
&{kwargs}
são todos argumentos nomeados.
Tendo esse grupo, você pode redirecioná-los, criando um decorador.
Trabalhar com o decorador ficará assim:
${negs} , 10 -5 5 log to console ${negs}
Em vez de uma conclusão
Nos exemplos acima, mostrei os principais recursos do Robot Framework, que tornam a vida muito mais fácil. Mas suas fichas não estão limitadas a esta lista.
Se você tiver alguma dúvida, escreva nos comentários. Selecionaremos a direção principal do interesse pela leitura e responderemos às perguntas com a continuação do texto.
O autor do artigo: Vladimir Vasyaev.
PS Publicamos nossos artigos em vários sites do Runet. Assine nossas páginas no
canal VK ,
FB ou
Telegram para descobrir todas as nossas publicações e outras notícias do Maxilect.