Garantir a qualidade de uma API pode não ser algo trivial. Testes comportamentais podem auxiliar nisso, mas nem sempre são facilmente implementáveis. Agora imagine poder utilizar uma linguagem de alto nível, próxima a natural, em Português, para poder realizar estes testes? Isso tudo utilizando ferramentas open source? Nesta palestra vamos abordar como utilizamos o Behave para testar uma API Rest, trazendo os pontos positivos, dificuldades encontradas e as soluções adotadas.
1. Globalcode – Open4education
Garantindo a qualidade da sua API
REST com Behave
Alex S. Garzão
Projetista de Software
Yuri Z. Pinheiro
Analista de Qualidade
ZAP Imóveis
www.linkedin.com/in/alexgarzao/ www.linkedin.com/in/yurizp
2. Globalcode – Open4education
Agenda
• Nosso contexto
• Projeto, desafios, problemas e soluções
• O que é BDD
• O que é Behave
• Nossa proposta
• Demonstração
• Resultados
• Lições aprendidas
• Próximos passos
3. Globalcode – Open4education
Vamos nos conhecer
• Testes automatizados. Quem aqui utiliza?
• BDD. Quem conhece? Quem utiliza?
• Behave. Quem conhece? Quem utiliza?
5. Globalcode – Open4education
Primeiros desafios
• Regras de negócio instáveis
• Definição do escopo em andamento
• Entendimento do projeto não era claro
• Novas tecnologias na empresa
6. Globalcode – Open4education
O que isso ocasionou?
• Baixa qualidade de código (Bugs a rodo)
• Retrabalho do time
• Time desmotivado
7. Globalcode – Open4education
Qual a solução?
• Testes, obviamente
• Começamos com testes manuais
• Mas isso não escala
• Tester virou gargalo da equipe
• Vamos automatizar :-)
8. Globalcode – Open4education
Em busca de soluções
● Aplicação em Python
○ É possível, mas partiríamos do zero :-/
● Curl
○ Fácil para testes pontuais
● Postman
○ Legal, mas a automação dele é trabalhosa
● Robot framework
○ Técnico demais
● Lettuce
○ Legal, mas foi descontinuado
● Behave
9. Globalcode – Open4education
O que é o BDD?
• Técnica de desenvolvimento ágil
• Encoraja interação entre técnicos e “não técnicos”
• Foco no negócio, e não nos detalhes técnicos
• Exemplos descrevem o comportamento da
aplicação
• São executáveis (documentação viva)
• São testes regressivos
11. Globalcode – Open4education
O que é o Behave?
• Utilizado para a prática de automação de testes
• Open source
• Suporte para BDD em Python
• Permite a escrita de cenários de teste
• Linguagem próxima a “natural”
12. Globalcode – Open4education
Exemplo Behave - Calcular fatorial
Funcionalidade: Calcular o fatorial
Cenário: Fatorial de 0
Dado eu tenho o número 0
Quando eu calculo este fatorial
Então eu vejo o número 1
Cenário: Fatorial de 2
Dado eu tenho o número 2
Quando eu calculo este fatorial
Então eu vejo o número 2
Cenário: Fatorial de 4
Dado eu tenho o número 4
Quando eu calculo este fatorial
Então eu vejo o número 24
13. Globalcode – Open4education
Funcionalidade: Calcular o fatorial
Cenário: Fatorial de 0
Dado eu tenho o número 0
Quando eu calculo este fatorial
Então eu vejo o número 1
@given(u'eu tenho o número {number}')
def step_impl(context, number):
context.number = int(number)
@when(u'eu calculo este fatorial')
def step_impl(context):
context.number = factorial(context.number)
@then(u'eu vejo o número {expected}')
def step_impl(context, expected):
expected = int(expected)
assert context.number == expected
14. Globalcode – Open4education
• Métodos de uma API Rest
• Exemplo: Rota para cadastro de imóveis
• Endpoint: https://api.meusite.com/imoveis
• JSON: {
proprietario: "fulano de tal",
endereco: "Rua A, 520",
valor: 450000
}
O que queríamos testar?
15. Globalcode – Open4education
Oh shit!
• Behave é uma ferramenta genérica
• Não entende API RESTful
• HTTP? JSON? GET/POST/PUT/DELETE?
• Endpoint? Request? HTTP status code?
16. Globalcode – Open4education
Nossa proposta...
• Ferramenta open source
• Utilizando o Behave
• Permite a escrita de testes automatizados
• Entende o que é uma API RESTful
• Cenários de testes são executáveis
• Escritos em português
18. Globalcode – Open4education
Esquema do Cenário: Como usuário tento cadastrar imóveis
Dado que eu quero cadastrar um imóvel
E o proprietário é <nome> e o endereço é <endereço> e o
valor é <valor>
Quando eu tento cadastrar o imóvel
Então eu recebo o código 200
Exemplos: Dados válidos para imóveis
| nome | endereço | valor |
| Proprietário 01 | Rua A POA RS | 1000.00 |
| Proprietário 02 | Rua B POA RS | 2000.00 |
• Step confuso de entender
• Steps muito específicos
• Reutilização engessada
• A cada novo step, uma nova implementação
20. Globalcode – Open4education
Esquema do Cenário: Como usuário tento cadastrar imóveis
Dado que eu quero cadastrar um imóvel
E o proprietário é <nome>
E o endereço é <endereço>
E o valor é <valor>
Quando eu tento cadastrar o imóvel
Então eu recebo o código 200
Exemplos: Dados válidos para imóveis
| nome | endereço | valor |
| Proprietário 01 | Rua A POA RS | 1000.00 |
| Proprietário 02 | Rua B POA RS | 2000.00 |
• Maior reutilização :-)
• Melhor legibilidade
• A cada novo step uma nova implementação :-(
22. Globalcode – Open4education
Esquema do Cenário: Como usuário quero cadastrar imóveis
Dado que eu quero cadastrar um imóvel
E o campo nome do proprietário é <nome>
E o campo endereço do imóvel é <endereço>
E o campo valor do imóvel é <valor>
Quando eu tento cadastrar o imóvel
Então eu recebo o status que indica imóvel criado
Exemplos: Dados válidos para imóveis
| nome | endereço | valor |
| Proprietário 01 | Rua A POA RS | 1000.00 |
| Proprietário 02 | Rua B POA RS | 2000.00 |
• Não temos mais steps específicos por campo
• Utilizamos alias (apelidos) para campos, códigos de status,
endpoints, ...
24. Globalcode – Open4education
Esquema do Cenário: Mapeando os campos do JSON
Dado que eu quero mapear os campos do JSON
E o campo <alias> é <tipo> e corresponde a <campo>
Quando eu tento mapear os campos
Então nenhuma falha ocorre
Exemplos: Campos do método de imóveis
| alias | tipo | campo |
| nome do proprietário | string | proprietario |
| endereço do imóvel | string | endereco |
| valor do imóvel | number | valor |
• É fácil criar novos campos
• Fazer manutenção (trocar tipo, nome no JSON, …)
• Independência na criação de cenários
• Técnicos e não técnicos
26. Globalcode – Open4education
Cenário: Como usuário quero listar meus imóveis
Dado que eu quero listar os meus imóveis
Quando eu busco a lista de imóveis
Então eu recebo o status que indica requisição válida
E obtenho a lista de dados abaixo
| nome do proprietário | endereço do imóvel |
| Proprietário 01 | Rua A POA RS |
| Proprietário 02 | Rua B POA RS |
• Validamos tipagem
• Validamos só os campos necessários
• Onde está o valor?
28. Globalcode – Open4education
Cenário: Como usuário quero listar meus imóveis
Dado que eu quero listar os meus imóveis
Quando eu busco a lista de imóveis
Então eu recebo o status que indica requisição válida
E obtenho a lista de dados abaixo
| nome do proprietário | data e hora criação |
| Proprietário 01 | <nao nulo> |
| Proprietário 02 | <nao nulo> |
• Temos outros tipos de validações
• <nao vazio>
• <nulo>
• <vazio> ou “”
• Não temos validações complexas
• > 20, < 100, ...
30. Globalcode – Open4education
Esquema do Cenário: Como usuário quero cadastrar imóveis
Dado que eu quero cadastrar um imóvel
E o campo nome do proprietário é <nome>
E o campo endereço do imóvel é <endereço>
E o campo valor do imóvel é <valor>
Quando eu tento cadastrar o imóvel
Então eu recebo o status que indica imóvel criado
Exemplos: Dados válidos para imóveis
| nome | endereço | valor |
| Proprietário 01 | Rua A POA RS | <nulo> |
| Proprietário 02 | <vazio> | 250000 |
| Proprietário 03 | “ A B C ” | 350000 |
32. Globalcode – Open4education
Esquema do Cenário: Como usuário quero cadastrar imóveis
Dado que eu quero cadastrar um imóvel
E o campo nome do proprietário é <nome>
E o campo endereço do imóvel é <endereço>
E o campo valor do imóvel é <valor>
Quando eu tento cadastrar o imóvel
Então eu recebo o status que indica imóvel criado
E guardo o retorno em <variável>
Exemplos: Dados válidos para imóveis
| nome | endereço | valor | variável |
| Proprietário 01 | Rua A POA RS | 150000 | imóvel 01 |
| Proprietário 02 | Rua B POA RS | 250000 | imóvel 02 |
• Permite reutilização de dados não previsíveis em outros
cenários
33. Globalcode – Open4education
Cenário: Como usuário quero listar meus imóveis
Dado que eu quero listar os meus imóveis
Quando eu busco a lista de imóveis
Então eu recebo o status que indica requisição válida
E obtenho a lista de dados abaixo
| nome do proprietário | endereço do imóvel |
| $imóvel 01.nome do proprietário | Rua A POA RS |
| $imóvel 02.nome do proprietário | Rua B POA RS |
• Variáveis podem ser utilizadas em qualquer step
• Podemos acessar qualquer campo do JSON
35. Globalcode – Open4education
Resultados
• Fomos
• De poucos testes manuais para 90% de cobertura
(testes automatizados)
• Ganho de tempo
• Temos testes sendo executados a todo momento
• Para cada novo bug temos um cenário de teste
• Facilidade em desenvolver novos testes
36. Globalcode – Open4education
Resultados
• Confiança na qualidade
• Confiança para realizar alterações críticas
• Qualquer pessoa, técnica ou não, consegue
desenvolver novos cenários
37. Globalcode – Open4education
Lições aprendidas
• Tempo para girar a roda é alto
• Dependência de API’s externas? Mock
• Setup dos dados no início dos testes
• Criar o banco, inserir dados de configuração, ...
• Não usar dados fictícios
• Rodar os testes em homologação
• Em produção é um plus
• Feature deve ser independente
• Cenário independente melhor ainda!