SlideShare uma empresa Scribd logo
1 de 53
Baixar para ler offline
Automação e Virtualização de
serviços REST com
RestAssured + Wiremock + Docker
@eliasnogueira
Passos...
1 Entender a documentação da API
2 Pensar nos testes com uma divisão de pipeline
3 Criar uma versão inicial da arquitetura
4 Criar os testes e definir as suítes de testes
5 Criar mocks para resolver problemas
* massa de dados, dependências, indisponibilidades
API do TDC
https://www.globalcode.com.br/api
Expõe a API de consulta a:
§ Eventos
§ Modalidades
§ Coordenadores
§ Palestrantes
§ Palestras
Através de um ClientID e um
Secret é gerado um
Access-Token em OAuth2
Possui a documentação via
OpenAPI para download na
própria página de acesso
1.
Entender a
documentação da API
Entender os controllers
§ operações
§ endpoints
§ parâmetros de entrada
§ saída
§ autenticação
2.
Pensar nos testes com
uma divisão de
pipeline
API
Pipeline
Health Check
Contrato
Funcional
Aceitação
Garantir que o endpoint está respondendo
HTTP 200
Garantir que o endpoint não teve seus
atributos alterados
Garantir que o endpoint funciona ou apresenta
os resultados de falha esperados
Garantir que um conjunto de endpoints
funcionam como na UI
3.
Criar uma versão
inicial da arquitetura
Arquitetura
src test
Geração do Access Token
necessário para a execução
dos testes
Leitor de Configurações
para ler, ao menos, os
dados de autenticação
beans e builders
suportar melhor a escrita
dos testes
BaseTest
para remover a duplicidade
de pré-condição
json schemas
schemas dos recursos para
o teste de contrato
Suítes de Teste
habilitará a rápida
execução de testes
4.
Criar testes e definir as
suítes de teste
Rest-Assured
http://rest-assured.io
DSL Java para testar e validar APIs REST.
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;
public class ExemploRestAssured {
@Test
public void boasVindas() {
given().
param("nome", "Elias").
when().
post("/cadastro").
then().
body("mensagem", is("Olá Elias"));
}
}
Rest-Assured
http://rest-assured.io
DSL Java para testar e validar APIs REST.
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;
public class ExemploRestAssured {
@Test
public void boasVindas() {
given().
param("nome", "Elias").
when().
post("/cadastro").
then().
body("mensagem", is("Olá Elias"));
}
}
importação das
bibliotecas necessárias
Rest-Assured
http://rest-assured.io
DSL Java para testar e validar APIs REST.
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;
public class ExemploRestAssured {
@Test
public void boasVindas() {
given().
param("nome", "Elias").
when().
post("/cadastro").
then().
body("mensagem", is("Olá Elias"));
}
}
pré-condição para a
requisição
Rest-Assured
http://rest-assured.io
DSL Java para testar e validar APIs REST.
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;
public class ExemploRestAssured {
@Test
public void boasVindas() {
given().
param("nome", "Elias").
when().
post("/cadastro").
then().
body("mensagem", is("Olá Elias"));
}
}
ação (requisição)
Rest-Assured
http://rest-assured.io
DSL Java para testar e validar APIs REST.
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;
public class ExemploRestAssured {
@Test
public void boasVindas() {
given().
param("nome", "Elias").
when().
post("/cadastro").
then().
body("mensagem", is("Olá Elias"));
}
}
validação dos dados
de retorno
Gerar do Access-Token
public String getAccessToken() {
Configuration configuration = new Configuration();
String username = configuration.getAuthenticationUsername();
String password = configuration.getAuthenticationPassword();
baseURI = configuration.getAPIURL();
basePath = configuration.getAPIOauthContext();
return
given().
auth()
.preemptive().basic(username, password).
when().
get("/").
then().
extract().
path("Access-Token");
}
Gerar do Access-Token
public String getAccessToken() {
Configuration configuration = new Configuration();
String username = configuration.getAuthenticationUsername();
String password = configuration.getAuthenticationPassword();
baseURI = configuration.getAPIURL();
basePath = configuration.getAPIOauthContext();
return
given().
auth()
.preemptive().basic(username, password).
when().
get("/").
then().
extract().
path("Access-Token");
}
a autenticação é enviada
como pré-condição
Gerar do Access-Token
public String getAccessToken() {
Configuration configuration = new Configuration();
String username = configuration.getAuthenticationUsername();
String password = configuration.getAuthenticationPassword();
baseURI = configuration.getAPIURL();
basePath = configuration.getAPIOauthContext();
return
given().
auth()
.preemptive().basic(username, password).
when().
get("/").
then().
extract().
path("Access-Token");
}
access-token é
retornado como
String
Leitor de Configurações
public String getAccessToken() {
Configuration configuration = new Configuration();
String username = configuration.getAuthenticationUsername();
String password = configuration.getAuthenticationPassword();
baseURI = configuration.getAPIURL();
basePath = configuration.getAPIOauthContext();
return
given().
auth()
.preemptive().basic(username, password).
when().
get("/").
then().
extract().
path("Access-Token");
}
lê dados de
autenticação
Leitor de Configurações
public String getAccessToken() {
Configuration configuration = new Configuration();
String username = configuration.getAuthenticationUsername();
String password = configuration.getAuthenticationPassword();
baseURI = configuration.getAPIURL();
basePath = configuration.getAPIOauthContext();
return
given().
auth()
.preemptive().basic(username, password).
when().
get("/").
then().
extract().
path("Access-Token");
}
lê dados para
acesso ao token
BaseTest
public abstract class BaseTest {
protected static String accessToken;
@BeforeClass(alwaysRun = true)
public static void beforeClass() {
Configuration configuration = new Configuration();
accessToken = new GenerateAccessToken().
getAccessToken();
baseURI = configuration.getAPIURL();
basePath = configuration.getPublico();
}
}
Código executado antes de cada teste
BaseTest
public abstract class BaseTest {
protected static String accessToken;
@BeforeClass(alwaysRun = true)
public static void beforeClass() {
Configuration configuration = new Configuration();
accessToken = new GenerateAccessToken().
getAccessToken();
baseURI = configuration.getAPIURL();
basePath = configuration.getPublico();
}
}
Código executado antes de cada teste
accessToken que
será acessado pelas
classes de teste
BaseTest
public abstract class BaseTest {
protected static String accessToken;
@BeforeClass(alwaysRun = true)
public static void beforeClass() {
Configuration configuration = new Configuration();
accessToken = new GenerateAccessToken().
getAccessToken();
baseURI = configuration.getAPIURL();
basePath = configuration.getPublico();
}
}
Código executado antes de cada teste
gera o accessToken
apenas uma vez para
a execução de teste
BaseTest
public abstract class BaseTest {
protected static String accessToken;
@BeforeClass(alwaysRun = true)
public static void beforeClass() {
Configuration configuration = new Configuration();
accessToken = new GenerateAccessToken().
getAccessToken();
baseURI = configuration.getAPIURL();
basePath = configuration.getPublico();
}
}
Código executado antes de cada teste
chamada da classe
de geração do token
BaseTest
public abstract class BaseTest {
protected static String accessToken;
@BeforeClass(alwaysRun = true)
public static void beforeClass() {
Configuration configuration = new Configuration();
accessToken = new GenerateAccessToken().
getAccessToken();
baseURI = configuration.getAPIURL();
basePath = configuration.getPublico();
}
}
Código executado antes de cada teste
necessário informar
novamente o
apontamento da API
* porque já foi apontado na geração do access token
health-check
Garantir que o endpoint está
respondendo
heath-check
Apenas validamos se o statuscode é 200
public class EventoDetalheTest extends BaseTest {
@Test(groups = { "health" })
public void healthCheck() {
given().
auth().oauth2(accessToken).
when().
get("evento/{id}", id).
then().
statusCode(HttpStatus.SC_OK);
}
heath-check
Apenas validamos se o statuscode é 200
tag de grupo para
filtrar a execução
public class EventoDetalheTest extends BaseTest {
@Test(groups = { "health" })
public void healthCheck() {
given().
auth().oauth2(accessToken).
when().
get("evento/{id}", id).
then().
statusCode(HttpStatus.SC_OK);
}
heath-check
Apenas validamos se o statuscode é 200
public class EventoDetalheTest extends BaseTest {
@Test(groups = { "health" })
public void healthCheck() {
given().
auth().oauth2(accessToken).
when().
get("evento/{id}", id).
then().
statusCode(HttpStatus.SC_OK);
}
inserir sempre o access-token
como pré-condição da requisição
heath-check
Apenas validamos se o statuscode é 200
public class EventoDetalheTest extends BaseTest {
@Test(groups = { "health" })
public void healthCheck() {
given().
auth().oauth2(accessToken).
when().
get("evento/{id}", id).
then().
statusCode(HttpStatus.SC_OK);
}
validar se o status code,
e somente ele, é 200
contrato
Garantir que o endpoint não teve
seus atributos alterados
● É o nome dado ao pacto entre o produtor e consumidor
● Garante que mudanças na API não invalidem o consumo:
● path
● parâmetros
● dados de envio (request)
● dados de retorno (response body)
● json-schema é um contrato que define os dados
esperados, tipos e formatos de cada campo na resposta
contrato
{
"nome": "Elias",
"idade": 36
}
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"nome": {
"type": "string"
},
"idade": {
"type": "integer"
}
},
"required": [
"nome",
"idade"
],
"additionalProperties": false
}
json-schema
{
"nome": "Elias",
"idade": 36
}
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"nome": {
"type": "string"
},
"idade": {
"type": "integer"
}
},
"required": [
"nome",
"idade"
],
"additionalProperties": false
}
json-schema possui o nome
do atributo e o tipo de dados
json-schema
{
"nome": "Elias",
"idade": 36
}
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"nome": {
"type": "string"
},
"idade": {
"type": "integer"
}
},
"required": [
"nome",
"idade"
],
"additionalProperties": false
}
os dois atributos devem estar
presentes, obrigatoriamente
json-schema
{
"nome": "Elias",
"idade": 36
}
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"nome": {
"type": "string"
},
"idade": {
"type": "integer"
}
},
"required": [
"nome",
"idade"
],
"additionalProperties": false
}
json-schema
nenhum outro
atributo é permitido
teste funcional
na minha máquina funciona
¯_(ツ)_/¯
funcional
Validar cenários positivos e negativos (caminho feliz | fluxo exceção)
@Test(groups = {"funcional"})
public void validarEventoPeloID() {
given().
auth().oauth2(accessToken).
when().
get("evento/{id}", 110).
then().
statusCode(HttpStatus.SC_OK).
body("[0].id", is(110)).
body("[0].descricao", is("TDC 2019 Florianópolis")).
body("[0].chave", is("tdc-2019-florianopolis")).
body("[0].ativo", is(true)).
body("[0].dias", is(5)).
body("[0].dataInicio", is("2019-04-23 00:00:00")).
body("[0].dataTermino", is("2019-04-27 00:00:00"));
}
funcional
Validar cenários positivos e negativos (caminho feliz | fluxo exceção)
@Test(groups = {"funcional"})
public void validarEventoPeloID() {
given().
auth().oauth2(accessToken).
when().
get("evento/{id}", 110).
then().
statusCode(HttpStatus.SC_OK).
body("[0].id", is(110)).
body("[0].descricao", is("TDC 2019 Florianópolis")).
body("[0].chave", is("tdc-2019-florianopolis")).
body("[0].ativo", is(true)).
body("[0].dias", is(5)).
body("[0].dataInicio", is("2019-04-23 00:00:00")).
body("[0].dataTermino", is("2019-04-27 00:00:00"));
}
tag de grupo para
filtrar a execução
funcional
Validar cenários positivos e negativos (caminho feliz | fluxo exceção)
@Test(groups = {"funcional"})
public void validarEventoPeloID() {
given().
auth().oauth2(accessToken).
when().
get("evento/{id}", 110).
then().
statusCode(HttpStatus.SC_OK).
body("[0].id", is(110)).
body("[0].descricao", is("TDC 2019 Florianópolis")).
body("[0].chave", is("tdc-2019-florianopolis")).
body("[0].ativo", is(true)).
body("[0].dias", is(5)).
body("[0].dataInicio", is("2019-04-23 00:00:00")).
body("[0].dataTermino", is("2019-04-27 00:00:00"));
}
requisição para obter
o detalhe de um
determinado evento
funcional
Validar cenários positivos e negativos (caminho feliz | fluxo exceção)
@Test(groups = {"funcional"})
public void validarEventoPeloID() {
given().
auth().oauth2(accessToken).
when().
get("evento/{id}", 110).
then().
statusCode(HttpStatus.SC_OK).
body("[0].id", is(110)).
body("[0].descricao", is("TDC 2019 Florianópolis")).
body("[0].chave", is("tdc-2019-florianopolis")).
body("[0].ativo", is(true)).
body("[0].dias", is(5)).
body("[0].dataInicio", is("2019-04-23 00:00:00")).
body("[0].dataTermino", is("2019-04-27 00:00:00"));
}
validação dos dados
de retorno (body)
* [0] existe ali porque o retorno é um array de uma posição
* é um possível bug da implementação
aceitação
Garantir que um conjunto de endpoints
funcionam como na UI
Testar com a perspectiva do usuário
● Entrar no evento The Developers Conference Florianópolis
● Clicar na Trilha DevTest
● Visualizar os detalhes da palestra Automação e
Virtualização de serviços REST com RestAssured +
Wiremock + Docker
aceitação
@Test(groups = {"aceitacao"})
public void visualizaDetalhes_EncontrandoDados() throws ObjetoNotFoundException {
String tituloPalestra = "Automação e Virtualização de serviços REST ";
Evento evento = encontraEvento("TDC 2019 Florianópolis");
Modalidade trilha = encontraTrilha(evento, "Trilha DevTest");
Palestra palestra = encontraPalestra(evento, trilha, tituloPalestra);
given().
auth().
oauth2(accessToken).
pathParam("eventoID", evento.getId()).
pathParam("modalidadeID", trilha.getId()).
pathParam("palestraID", palestra.getId()).
when().
get("/evento/{eventoID}/modalidade/{modalidadeID}/palestra/{palestraID}/palestrantes").
then().
statusCode(200).
body("[0].member.nome", is("Elias Nogueira")).
body("[0].member.empresa", is("Sicredi"));
}
aceitação
@Test(groups = {"aceitacao"})
public void visualizaDetalhes_EncontrandoDados() throws ObjetoNotFoundException {
String tituloPalestra = "Automação e Virtualização de serviços REST ";
Evento evento = encontraEvento("TDC 2019 Florianópolis");
Modalidade trilha = encontraTrilha(evento, "Trilha DevTest");
Palestra palestra = encontraPalestra(evento, trilha, tituloPalestra);
given().
auth().
oauth2(accessToken).
pathParam("eventoID", evento.getId()).
pathParam("modalidadeID", trilha.getId()).
pathParam("palestraID", palestra.getId()).
when().
get("/evento/{eventoID}/modalidade/{modalidadeID}/palestra/{palestraID}/palestrantes").
then().
statusCode(200).
body("[0].member.nome", is("Elias Nogueira")).
body("[0].member.empresa", is("Sicredi"));
}
funções auxiliares para chamadas a
cada ação do usuário
aceitação
@Test(groups = {"aceitacao"})
public void visualizaDetalhes_EncontrandoDados() throws ObjetoNotFoundException {
String tituloPalestra = "Automação e Virtualização de serviços REST ";
Evento evento = encontraEvento("TDC 2019 Florianópolis");
Modalidade trilha = encontraTrilha(evento, "Trilha DevTest");
Palestra palestra = encontraPalestra(evento, trilha, tituloPalestra);
given().
auth().
oauth2(accessToken).
pathParam("eventoID", evento.getId()).
pathParam("modalidadeID", trilha.getId()).
pathParam("palestraID", palestra.getId()).
when().
get("/evento/{eventoID}/modalidade/{modalidadeID}/palestra/{palestraID}/palestrantes").
then().
statusCode(200).
body("[0].member.nome", is("Elias Nogueira")).
body("[0].member.empresa", is("Sicredi"));
}
uso dos dados obtidos
para a requisição
service virtualization
disponibilizar mocks de seviços
● Forma de simular comportamentos de componentes
baseados em API
● Habilita o uso de serviços virtuais ao invés de serviços de
produção mesmo que componentes chave não estejam
disponíveis
service virtualization
service virtualization
{
"id" : "f238845e-369c-4a34-aa69-04d9240d7fb5",
"name" : "evento_modalidade_palestra",
"request" : {
"urlPattern" : "/v1/publico/evento/110/modalidade/2685/palestra/10083",
"method" : "GET"
},
"response" : {
"status" : 200,
"bodyFileName" : "evento_modalidade_palestra_data.json",
"headers" : {
"Authorization": "*"
}
},
"persistent" : true,
"insertionIndex" : 1
}
service virtualization
{
"id" : "f238845e-369c-4a34-aa69-04d9240d7fb5",
"name" : "evento_modalidade_palestra",
"request" : {
"urlPattern" : "/v1/publico/evento/110/modalidade/2685/palestra/10083",
"method" : "GET"
},
"response" : {
"status" : 200,
"bodyFileName" : "evento_modalidade_palestra_data.json",
"headers" : {
"Authorization": "*"
}
},
"persistent" : true,
"insertionIndex" : 1
}
sempre que uma requisição for igual a esta
URL (inclusive com os dados)
service virtualization
{
"id" : "f238845e-369c-4a34-aa69-04d9240d7fb5",
"name" : "evento_modalidade_palestra",
"request" : {
"urlPattern" : "/v1/publico/evento/110/modalidade/2685/palestra/10083",
"method" : "GET"
},
"response" : {
"status" : 200,
"bodyFileName" : "evento_modalidade_palestra_data.json",
},
"persistent" : true,
"insertionIndex" : 1
}
a api responderá os dados abaixo...
service virtualization
{
"id": 10083,
"slot": 6,
"ordem": 1,
"titulo": "Automação e Virtualização de serviços REST...",
"descricao": ”Você sempre quis aprender a como testar...",
"tipo": 2,
"horario": "16:40"
}
dados de retorno
@eliasnogueira
github.com/eliasnogueira
Obrigado!

Mais conteúdo relacionado

Mais procurados

API Test Automation Using Karate (Anil Kumar Moka)
API Test Automation Using Karate (Anil Kumar Moka)API Test Automation Using Karate (Anil Kumar Moka)
API Test Automation Using Karate (Anil Kumar Moka)Peter Thomas
 
Py.test
Py.testPy.test
Py.testsoasme
 
Angular 2.0 forms
Angular 2.0 formsAngular 2.0 forms
Angular 2.0 formsEyal Vardi
 
JUnit & Mockito, first steps
JUnit & Mockito, first stepsJUnit & Mockito, first steps
JUnit & Mockito, first stepsRenato Primavera
 
Mockito a simple, intuitive mocking framework
Mockito   a simple, intuitive mocking frameworkMockito   a simple, intuitive mocking framework
Mockito a simple, intuitive mocking frameworkPhat VU
 
Writing automation tests with python selenium behave pageobjects
Writing automation tests with python selenium behave pageobjectsWriting automation tests with python selenium behave pageobjects
Writing automation tests with python selenium behave pageobjectsLeticia Rss
 
Spring Framework - Spring Security
Spring Framework - Spring SecuritySpring Framework - Spring Security
Spring Framework - Spring SecurityDzmitry Naskou
 
Mocking in Java with Mockito
Mocking in Java with MockitoMocking in Java with Mockito
Mocking in Java with MockitoRichard Paul
 
Karate - Web-Service API Testing Made Simple
Karate - Web-Service API Testing Made SimpleKarate - Web-Service API Testing Made Simple
Karate - Web-Service API Testing Made SimpleVodqaBLR
 
테스트자동화 성공전략
테스트자동화 성공전략테스트자동화 성공전략
테스트자동화 성공전략SangIn Choung
 
Unit Testing And Mocking
Unit Testing And MockingUnit Testing And Mocking
Unit Testing And MockingJoe Wilson
 
Testing RESTful Webservices using the REST-assured framework
Testing RESTful Webservices using the REST-assured frameworkTesting RESTful Webservices using the REST-assured framework
Testing RESTful Webservices using the REST-assured frameworkMicha Kops
 
Automação de Teste para REST, Web e Mobile
Automação de Teste para REST, Web e MobileAutomação de Teste para REST, Web e Mobile
Automação de Teste para REST, Web e MobileElias Nogueira
 

Mais procurados (20)

JUnit Presentation
JUnit PresentationJUnit Presentation
JUnit Presentation
 
Appium
AppiumAppium
Appium
 
API Test Automation Using Karate (Anil Kumar Moka)
API Test Automation Using Karate (Anil Kumar Moka)API Test Automation Using Karate (Anil Kumar Moka)
API Test Automation Using Karate (Anil Kumar Moka)
 
Py.test
Py.testPy.test
Py.test
 
Angular 2.0 forms
Angular 2.0 formsAngular 2.0 forms
Angular 2.0 forms
 
Using Mockito
Using MockitoUsing Mockito
Using Mockito
 
JUnit & Mockito, first steps
JUnit & Mockito, first stepsJUnit & Mockito, first steps
JUnit & Mockito, first steps
 
Mockito a simple, intuitive mocking framework
Mockito   a simple, intuitive mocking frameworkMockito   a simple, intuitive mocking framework
Mockito a simple, intuitive mocking framework
 
Cucumber BDD
Cucumber BDDCucumber BDD
Cucumber BDD
 
Writing automation tests with python selenium behave pageobjects
Writing automation tests with python selenium behave pageobjectsWriting automation tests with python selenium behave pageobjects
Writing automation tests with python selenium behave pageobjects
 
Spring Framework - Spring Security
Spring Framework - Spring SecuritySpring Framework - Spring Security
Spring Framework - Spring Security
 
Mocking in Java with Mockito
Mocking in Java with MockitoMocking in Java with Mockito
Mocking in Java with Mockito
 
Unit testing with JUnit
Unit testing with JUnitUnit testing with JUnit
Unit testing with JUnit
 
Karate - Web-Service API Testing Made Simple
Karate - Web-Service API Testing Made SimpleKarate - Web-Service API Testing Made Simple
Karate - Web-Service API Testing Made Simple
 
BDD with Cucumber
BDD with CucumberBDD with Cucumber
BDD with Cucumber
 
테스트자동화 성공전략
테스트자동화 성공전략테스트자동화 성공전략
테스트자동화 성공전략
 
Unit Testing And Mocking
Unit Testing And MockingUnit Testing And Mocking
Unit Testing And Mocking
 
Testing RESTful Webservices using the REST-assured framework
Testing RESTful Webservices using the REST-assured frameworkTesting RESTful Webservices using the REST-assured framework
Testing RESTful Webservices using the REST-assured framework
 
Automação de Teste para REST, Web e Mobile
Automação de Teste para REST, Web e MobileAutomação de Teste para REST, Web e Mobile
Automação de Teste para REST, Web e Mobile
 
Karate DSL
Karate DSLKarate DSL
Karate DSL
 

Semelhante a Automação e virtualização de serviços

TDD - Algumas lições aprendidas com o livro GOOS
TDD - Algumas lições aprendidas com o livro GOOSTDD - Algumas lições aprendidas com o livro GOOS
TDD - Algumas lições aprendidas com o livro GOOSFábio Miranda
 
Play Framework - FLISOL
Play Framework - FLISOLPlay Framework - FLISOL
Play Framework - FLISOLgrupoweblovers
 
Workshop Microservices - Construindo APIs RESTful com Spring Boot
Workshop Microservices - Construindo APIs RESTful com Spring BootWorkshop Microservices - Construindo APIs RESTful com Spring Boot
Workshop Microservices - Construindo APIs RESTful com Spring BootRodrigo Cândido da Silva
 
PDC - Engenharia - Plataforma Microsoft .NET
PDC - Engenharia - Plataforma Microsoft .NETPDC - Engenharia - Plataforma Microsoft .NET
PDC - Engenharia - Plataforma Microsoft .NETslides_teltools
 
Ecosistema spring a_plataforma_enterprise_jav
Ecosistema spring a_plataforma_enterprise_javEcosistema spring a_plataforma_enterprise_jav
Ecosistema spring a_plataforma_enterprise_javJulio Viegas
 
CDI Extensions e DeltaSpike
CDI Extensions e DeltaSpikeCDI Extensions e DeltaSpike
CDI Extensions e DeltaSpikeRafael Benevides
 
AspectJ — Programação orientada a aspectos em Java
AspectJ — Programação orientada a aspectos em JavaAspectJ — Programação orientada a aspectos em Java
AspectJ — Programação orientada a aspectos em Javaelliando dias
 
JavaOne LATAM 2016 - Combinando AngularJS com Java EE
JavaOne LATAM 2016 - Combinando AngularJS com Java EEJavaOne LATAM 2016 - Combinando AngularJS com Java EE
JavaOne LATAM 2016 - Combinando AngularJS com Java EERodrigo Cândido da Silva
 
Como conectar programas em linguagem java a bases de dados
Como conectar programas em linguagem java  a bases de dadosComo conectar programas em linguagem java  a bases de dados
Como conectar programas em linguagem java a bases de dadosHenrique Fernandes
 
Teste de Integracao com DbUnit e JStryker
Teste de Integracao com DbUnit e JStrykerTeste de Integracao com DbUnit e JStryker
Teste de Integracao com DbUnit e JStrykerWashington Botelho
 

Semelhante a Automação e virtualização de serviços (20)

TDD - Algumas lições aprendidas com o livro GOOS
TDD - Algumas lições aprendidas com o livro GOOSTDD - Algumas lições aprendidas com o livro GOOS
TDD - Algumas lições aprendidas com o livro GOOS
 
Play Framework - FLISOL
Play Framework - FLISOLPlay Framework - FLISOL
Play Framework - FLISOL
 
Vraptor
VraptorVraptor
Vraptor
 
Workshop Microservices - Construindo APIs RESTful com Spring Boot
Workshop Microservices - Construindo APIs RESTful com Spring BootWorkshop Microservices - Construindo APIs RESTful com Spring Boot
Workshop Microservices - Construindo APIs RESTful com Spring Boot
 
PDC - Engenharia - Plataforma Microsoft .NET
PDC - Engenharia - Plataforma Microsoft .NETPDC - Engenharia - Plataforma Microsoft .NET
PDC - Engenharia - Plataforma Microsoft .NET
 
Ecosistema spring a_plataforma_enterprise_jav
Ecosistema spring a_plataforma_enterprise_javEcosistema spring a_plataforma_enterprise_jav
Ecosistema spring a_plataforma_enterprise_jav
 
CDI Extensions e DeltaSpike
CDI Extensions e DeltaSpikeCDI Extensions e DeltaSpike
CDI Extensions e DeltaSpike
 
VRaptor4
VRaptor4VRaptor4
VRaptor4
 
Spring Capitulo 03
Spring Capitulo 03Spring Capitulo 03
Spring Capitulo 03
 
AspectJ — Programação orientada a aspectos em Java
AspectJ — Programação orientada a aspectos em JavaAspectJ — Programação orientada a aspectos em Java
AspectJ — Programação orientada a aspectos em Java
 
JavaOne LATAM 2016 - Combinando AngularJS com Java EE
JavaOne LATAM 2016 - Combinando AngularJS com Java EEJavaOne LATAM 2016 - Combinando AngularJS com Java EE
JavaOne LATAM 2016 - Combinando AngularJS com Java EE
 
Workshop05
Workshop05Workshop05
Workshop05
 
API Apontador
API ApontadorAPI Apontador
API Apontador
 
Design patterns
Design patternsDesign patterns
Design patterns
 
Como conectar programas em linguagem java a bases de dados
Como conectar programas em linguagem java  a bases de dadosComo conectar programas em linguagem java  a bases de dados
Como conectar programas em linguagem java a bases de dados
 
Wicket 2008
Wicket 2008Wicket 2008
Wicket 2008
 
Teste de Integracao com DbUnit e JStryker
Teste de Integracao com DbUnit e JStrykerTeste de Integracao com DbUnit e JStryker
Teste de Integracao com DbUnit e JStryker
 
ASP.NET Web API
ASP.NET Web APIASP.NET Web API
ASP.NET Web API
 
Spring MVC - QConSP
Spring MVC - QConSPSpring MVC - QConSP
Spring MVC - QConSP
 
Fundamentos de JDBC
Fundamentos de JDBCFundamentos de JDBC
Fundamentos de JDBC
 

Mais de Elias Nogueira

Coach por Imersão - Buscando a excelência técnica com o time
Coach por Imersão - Buscando a excelência técnica com o timeCoach por Imersão - Buscando a excelência técnica com o time
Coach por Imersão - Buscando a excelência técnica com o timeElias Nogueira
 
O Agile Coach pode (e muitas vezes deve) ser técnico
O Agile Coach pode (e muitas vezes deve) ser técnicoO Agile Coach pode (e muitas vezes deve) ser técnico
O Agile Coach pode (e muitas vezes deve) ser técnicoElias Nogueira
 
Create an architecture for web test automation
Create an architecture for web test automationCreate an architecture for web test automation
Create an architecture for web test automationElias Nogueira
 
Paralelize seus testes web e mobile para ter feedbacks mais rápidos
Paralelize seus testes web e mobile para ter feedbacks mais rápidosParalelize seus testes web e mobile para ter feedbacks mais rápidos
Paralelize seus testes web e mobile para ter feedbacks mais rápidosElias Nogueira
 
Como 4 Agile Coaches trabalham em uma Transformação Ágil
Como 4 Agile Coaches trabalham em uma Transformação Ágil Como 4 Agile Coaches trabalham em uma Transformação Ágil
Como 4 Agile Coaches trabalham em uma Transformação Ágil Elias Nogueira
 
BDD não é automação de teste - Scrum Gathering
BDD não é automação de teste - Scrum GatheringBDD não é automação de teste - Scrum Gathering
BDD não é automação de teste - Scrum GatheringElias Nogueira
 
Como criar e executar testes paralelos web usando Selenium e containers
Como criar e executar testes paralelos web usando Selenium e containersComo criar e executar testes paralelos web usando Selenium e containers
Como criar e executar testes paralelos web usando Selenium e containersElias Nogueira
 
Improve Yourself -- Learn the Skills, Join the Community - Tests
Improve Yourself -- Learn the Skills, Join the Community - TestsImprove Yourself -- Learn the Skills, Join the Community - Tests
Improve Yourself -- Learn the Skills, Join the Community - TestsElias Nogueira
 
BDD não é Automação de Testes
BDD não é Automação de TestesBDD não é Automação de Testes
BDD não é Automação de TestesElias Nogueira
 
Criando uma grid para execução de testes paralelo com Appium
Criando uma grid para execução de testes paralelo com AppiumCriando uma grid para execução de testes paralelo com Appium
Criando uma grid para execução de testes paralelo com AppiumElias Nogueira
 
Como ter sucesso ministrando uma palestra técnica
Como ter sucesso ministrando uma palestra técnicaComo ter sucesso ministrando uma palestra técnica
Como ter sucesso ministrando uma palestra técnicaElias Nogueira
 
Quais são os steps de que deve conter na sua pipeline?
Quais são os steps de que deve conter na sua pipeline?Quais são os steps de que deve conter na sua pipeline?
Quais são os steps de que deve conter na sua pipeline?Elias Nogueira
 
Testes em todos os niveis de planejamento
Testes em todos os niveis de planejamentoTestes em todos os niveis de planejamento
Testes em todos os niveis de planejamentoElias Nogueira
 
Coaching the Agile Coach
Coaching the Agile CoachCoaching the Agile Coach
Coaching the Agile CoachElias Nogueira
 
Java Test Automation for REST, Web and Mobile
Java Test Automation for REST, Web and MobileJava Test Automation for REST, Web and Mobile
Java Test Automation for REST, Web and MobileElias Nogueira
 
Trust Your Pipeline - Automatically Testing and End-to-End Java Application
Trust Your Pipeline - Automatically Testing and End-to-End Java ApplicationTrust Your Pipeline - Automatically Testing and End-to-End Java Application
Trust Your Pipeline - Automatically Testing and End-to-End Java ApplicationElias Nogueira
 
O que é um Agile Coach
O que é um Agile CoachO que é um Agile Coach
O que é um Agile CoachElias Nogueira
 
Criando uma grid para execução de teste automatizado funcional e e2e
Criando uma grid para execução de teste automatizado funcional e e2eCriando uma grid para execução de teste automatizado funcional e e2e
Criando uma grid para execução de teste automatizado funcional e e2eElias Nogueira
 
A importancia de testes em todos os aspectos
A importancia de testes em todos os aspectosA importancia de testes em todos os aspectos
A importancia de testes em todos os aspectosElias Nogueira
 

Mais de Elias Nogueira (20)

Coach por Imersão - Buscando a excelência técnica com o time
Coach por Imersão - Buscando a excelência técnica com o timeCoach por Imersão - Buscando a excelência técnica com o time
Coach por Imersão - Buscando a excelência técnica com o time
 
O Agile Coach pode (e muitas vezes deve) ser técnico
O Agile Coach pode (e muitas vezes deve) ser técnicoO Agile Coach pode (e muitas vezes deve) ser técnico
O Agile Coach pode (e muitas vezes deve) ser técnico
 
Create an architecture for web test automation
Create an architecture for web test automationCreate an architecture for web test automation
Create an architecture for web test automation
 
Paralelize seus testes web e mobile para ter feedbacks mais rápidos
Paralelize seus testes web e mobile para ter feedbacks mais rápidosParalelize seus testes web e mobile para ter feedbacks mais rápidos
Paralelize seus testes web e mobile para ter feedbacks mais rápidos
 
Como 4 Agile Coaches trabalham em uma Transformação Ágil
Como 4 Agile Coaches trabalham em uma Transformação Ágil Como 4 Agile Coaches trabalham em uma Transformação Ágil
Como 4 Agile Coaches trabalham em uma Transformação Ágil
 
BDD não é automação de teste - Scrum Gathering
BDD não é automação de teste - Scrum GatheringBDD não é automação de teste - Scrum Gathering
BDD não é automação de teste - Scrum Gathering
 
Como criar e executar testes paralelos web usando Selenium e containers
Como criar e executar testes paralelos web usando Selenium e containersComo criar e executar testes paralelos web usando Selenium e containers
Como criar e executar testes paralelos web usando Selenium e containers
 
Improve Yourself -- Learn the Skills, Join the Community - Tests
Improve Yourself -- Learn the Skills, Join the Community - TestsImprove Yourself -- Learn the Skills, Join the Community - Tests
Improve Yourself -- Learn the Skills, Join the Community - Tests
 
BDD não é Automação de Testes
BDD não é Automação de TestesBDD não é Automação de Testes
BDD não é Automação de Testes
 
Criando uma grid para execução de testes paralelo com Appium
Criando uma grid para execução de testes paralelo com AppiumCriando uma grid para execução de testes paralelo com Appium
Criando uma grid para execução de testes paralelo com Appium
 
Como ter sucesso ministrando uma palestra técnica
Como ter sucesso ministrando uma palestra técnicaComo ter sucesso ministrando uma palestra técnica
Como ter sucesso ministrando uma palestra técnica
 
Quais são os steps de que deve conter na sua pipeline?
Quais são os steps de que deve conter na sua pipeline?Quais são os steps de que deve conter na sua pipeline?
Quais são os steps de que deve conter na sua pipeline?
 
Tem que testar mesmo?
Tem que testar mesmo?Tem que testar mesmo?
Tem que testar mesmo?
 
Testes em todos os niveis de planejamento
Testes em todos os niveis de planejamentoTestes em todos os niveis de planejamento
Testes em todos os niveis de planejamento
 
Coaching the Agile Coach
Coaching the Agile CoachCoaching the Agile Coach
Coaching the Agile Coach
 
Java Test Automation for REST, Web and Mobile
Java Test Automation for REST, Web and MobileJava Test Automation for REST, Web and Mobile
Java Test Automation for REST, Web and Mobile
 
Trust Your Pipeline - Automatically Testing and End-to-End Java Application
Trust Your Pipeline - Automatically Testing and End-to-End Java ApplicationTrust Your Pipeline - Automatically Testing and End-to-End Java Application
Trust Your Pipeline - Automatically Testing and End-to-End Java Application
 
O que é um Agile Coach
O que é um Agile CoachO que é um Agile Coach
O que é um Agile Coach
 
Criando uma grid para execução de teste automatizado funcional e e2e
Criando uma grid para execução de teste automatizado funcional e e2eCriando uma grid para execução de teste automatizado funcional e e2e
Criando uma grid para execução de teste automatizado funcional e e2e
 
A importancia de testes em todos os aspectos
A importancia de testes em todos os aspectosA importancia de testes em todos os aspectos
A importancia de testes em todos os aspectos
 

Automação e virtualização de serviços

  • 1. Automação e Virtualização de serviços REST com RestAssured + Wiremock + Docker @eliasnogueira
  • 2. Passos... 1 Entender a documentação da API 2 Pensar nos testes com uma divisão de pipeline 3 Criar uma versão inicial da arquitetura 4 Criar os testes e definir as suítes de testes 5 Criar mocks para resolver problemas * massa de dados, dependências, indisponibilidades
  • 3. API do TDC https://www.globalcode.com.br/api Expõe a API de consulta a: § Eventos § Modalidades § Coordenadores § Palestrantes § Palestras Através de um ClientID e um Secret é gerado um Access-Token em OAuth2 Possui a documentação via OpenAPI para download na própria página de acesso
  • 5. Entender os controllers § operações § endpoints § parâmetros de entrada § saída § autenticação
  • 6. 2. Pensar nos testes com uma divisão de pipeline
  • 7. API Pipeline Health Check Contrato Funcional Aceitação Garantir que o endpoint está respondendo HTTP 200 Garantir que o endpoint não teve seus atributos alterados Garantir que o endpoint funciona ou apresenta os resultados de falha esperados Garantir que um conjunto de endpoints funcionam como na UI
  • 9. Arquitetura src test Geração do Access Token necessário para a execução dos testes Leitor de Configurações para ler, ao menos, os dados de autenticação beans e builders suportar melhor a escrita dos testes BaseTest para remover a duplicidade de pré-condição json schemas schemas dos recursos para o teste de contrato Suítes de Teste habilitará a rápida execução de testes
  • 10. 4. Criar testes e definir as suítes de teste
  • 11. Rest-Assured http://rest-assured.io DSL Java para testar e validar APIs REST. import static io.restassured.RestAssured.*; import static org.hamcrest.Matchers.*; public class ExemploRestAssured { @Test public void boasVindas() { given(). param("nome", "Elias"). when(). post("/cadastro"). then(). body("mensagem", is("Olá Elias")); } }
  • 12. Rest-Assured http://rest-assured.io DSL Java para testar e validar APIs REST. import static io.restassured.RestAssured.*; import static org.hamcrest.Matchers.*; public class ExemploRestAssured { @Test public void boasVindas() { given(). param("nome", "Elias"). when(). post("/cadastro"). then(). body("mensagem", is("Olá Elias")); } } importação das bibliotecas necessárias
  • 13. Rest-Assured http://rest-assured.io DSL Java para testar e validar APIs REST. import static io.restassured.RestAssured.*; import static org.hamcrest.Matchers.*; public class ExemploRestAssured { @Test public void boasVindas() { given(). param("nome", "Elias"). when(). post("/cadastro"). then(). body("mensagem", is("Olá Elias")); } } pré-condição para a requisição
  • 14. Rest-Assured http://rest-assured.io DSL Java para testar e validar APIs REST. import static io.restassured.RestAssured.*; import static org.hamcrest.Matchers.*; public class ExemploRestAssured { @Test public void boasVindas() { given(). param("nome", "Elias"). when(). post("/cadastro"). then(). body("mensagem", is("Olá Elias")); } } ação (requisição)
  • 15. Rest-Assured http://rest-assured.io DSL Java para testar e validar APIs REST. import static io.restassured.RestAssured.*; import static org.hamcrest.Matchers.*; public class ExemploRestAssured { @Test public void boasVindas() { given(). param("nome", "Elias"). when(). post("/cadastro"). then(). body("mensagem", is("Olá Elias")); } } validação dos dados de retorno
  • 16. Gerar do Access-Token public String getAccessToken() { Configuration configuration = new Configuration(); String username = configuration.getAuthenticationUsername(); String password = configuration.getAuthenticationPassword(); baseURI = configuration.getAPIURL(); basePath = configuration.getAPIOauthContext(); return given(). auth() .preemptive().basic(username, password). when(). get("/"). then(). extract(). path("Access-Token"); }
  • 17. Gerar do Access-Token public String getAccessToken() { Configuration configuration = new Configuration(); String username = configuration.getAuthenticationUsername(); String password = configuration.getAuthenticationPassword(); baseURI = configuration.getAPIURL(); basePath = configuration.getAPIOauthContext(); return given(). auth() .preemptive().basic(username, password). when(). get("/"). then(). extract(). path("Access-Token"); } a autenticação é enviada como pré-condição
  • 18. Gerar do Access-Token public String getAccessToken() { Configuration configuration = new Configuration(); String username = configuration.getAuthenticationUsername(); String password = configuration.getAuthenticationPassword(); baseURI = configuration.getAPIURL(); basePath = configuration.getAPIOauthContext(); return given(). auth() .preemptive().basic(username, password). when(). get("/"). then(). extract(). path("Access-Token"); } access-token é retornado como String
  • 19. Leitor de Configurações public String getAccessToken() { Configuration configuration = new Configuration(); String username = configuration.getAuthenticationUsername(); String password = configuration.getAuthenticationPassword(); baseURI = configuration.getAPIURL(); basePath = configuration.getAPIOauthContext(); return given(). auth() .preemptive().basic(username, password). when(). get("/"). then(). extract(). path("Access-Token"); } lê dados de autenticação
  • 20. Leitor de Configurações public String getAccessToken() { Configuration configuration = new Configuration(); String username = configuration.getAuthenticationUsername(); String password = configuration.getAuthenticationPassword(); baseURI = configuration.getAPIURL(); basePath = configuration.getAPIOauthContext(); return given(). auth() .preemptive().basic(username, password). when(). get("/"). then(). extract(). path("Access-Token"); } lê dados para acesso ao token
  • 21. BaseTest public abstract class BaseTest { protected static String accessToken; @BeforeClass(alwaysRun = true) public static void beforeClass() { Configuration configuration = new Configuration(); accessToken = new GenerateAccessToken(). getAccessToken(); baseURI = configuration.getAPIURL(); basePath = configuration.getPublico(); } } Código executado antes de cada teste
  • 22. BaseTest public abstract class BaseTest { protected static String accessToken; @BeforeClass(alwaysRun = true) public static void beforeClass() { Configuration configuration = new Configuration(); accessToken = new GenerateAccessToken(). getAccessToken(); baseURI = configuration.getAPIURL(); basePath = configuration.getPublico(); } } Código executado antes de cada teste accessToken que será acessado pelas classes de teste
  • 23. BaseTest public abstract class BaseTest { protected static String accessToken; @BeforeClass(alwaysRun = true) public static void beforeClass() { Configuration configuration = new Configuration(); accessToken = new GenerateAccessToken(). getAccessToken(); baseURI = configuration.getAPIURL(); basePath = configuration.getPublico(); } } Código executado antes de cada teste gera o accessToken apenas uma vez para a execução de teste
  • 24. BaseTest public abstract class BaseTest { protected static String accessToken; @BeforeClass(alwaysRun = true) public static void beforeClass() { Configuration configuration = new Configuration(); accessToken = new GenerateAccessToken(). getAccessToken(); baseURI = configuration.getAPIURL(); basePath = configuration.getPublico(); } } Código executado antes de cada teste chamada da classe de geração do token
  • 25. BaseTest public abstract class BaseTest { protected static String accessToken; @BeforeClass(alwaysRun = true) public static void beforeClass() { Configuration configuration = new Configuration(); accessToken = new GenerateAccessToken(). getAccessToken(); baseURI = configuration.getAPIURL(); basePath = configuration.getPublico(); } } Código executado antes de cada teste necessário informar novamente o apontamento da API * porque já foi apontado na geração do access token
  • 26. health-check Garantir que o endpoint está respondendo
  • 27. heath-check Apenas validamos se o statuscode é 200 public class EventoDetalheTest extends BaseTest { @Test(groups = { "health" }) public void healthCheck() { given(). auth().oauth2(accessToken). when(). get("evento/{id}", id). then(). statusCode(HttpStatus.SC_OK); }
  • 28. heath-check Apenas validamos se o statuscode é 200 tag de grupo para filtrar a execução public class EventoDetalheTest extends BaseTest { @Test(groups = { "health" }) public void healthCheck() { given(). auth().oauth2(accessToken). when(). get("evento/{id}", id). then(). statusCode(HttpStatus.SC_OK); }
  • 29. heath-check Apenas validamos se o statuscode é 200 public class EventoDetalheTest extends BaseTest { @Test(groups = { "health" }) public void healthCheck() { given(). auth().oauth2(accessToken). when(). get("evento/{id}", id). then(). statusCode(HttpStatus.SC_OK); } inserir sempre o access-token como pré-condição da requisição
  • 30. heath-check Apenas validamos se o statuscode é 200 public class EventoDetalheTest extends BaseTest { @Test(groups = { "health" }) public void healthCheck() { given(). auth().oauth2(accessToken). when(). get("evento/{id}", id). then(). statusCode(HttpStatus.SC_OK); } validar se o status code, e somente ele, é 200
  • 31. contrato Garantir que o endpoint não teve seus atributos alterados
  • 32. ● É o nome dado ao pacto entre o produtor e consumidor ● Garante que mudanças na API não invalidem o consumo: ● path ● parâmetros ● dados de envio (request) ● dados de retorno (response body) ● json-schema é um contrato que define os dados esperados, tipos e formatos de cada campo na resposta contrato
  • 33. { "nome": "Elias", "idade": 36 } { "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", "properties": { "nome": { "type": "string" }, "idade": { "type": "integer" } }, "required": [ "nome", "idade" ], "additionalProperties": false } json-schema
  • 34. { "nome": "Elias", "idade": 36 } { "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", "properties": { "nome": { "type": "string" }, "idade": { "type": "integer" } }, "required": [ "nome", "idade" ], "additionalProperties": false } json-schema possui o nome do atributo e o tipo de dados json-schema
  • 35. { "nome": "Elias", "idade": 36 } { "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", "properties": { "nome": { "type": "string" }, "idade": { "type": "integer" } }, "required": [ "nome", "idade" ], "additionalProperties": false } os dois atributos devem estar presentes, obrigatoriamente json-schema
  • 36. { "nome": "Elias", "idade": 36 } { "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", "properties": { "nome": { "type": "string" }, "idade": { "type": "integer" } }, "required": [ "nome", "idade" ], "additionalProperties": false } json-schema nenhum outro atributo é permitido
  • 37. teste funcional na minha máquina funciona ¯_(ツ)_/¯
  • 38. funcional Validar cenários positivos e negativos (caminho feliz | fluxo exceção) @Test(groups = {"funcional"}) public void validarEventoPeloID() { given(). auth().oauth2(accessToken). when(). get("evento/{id}", 110). then(). statusCode(HttpStatus.SC_OK). body("[0].id", is(110)). body("[0].descricao", is("TDC 2019 Florianópolis")). body("[0].chave", is("tdc-2019-florianopolis")). body("[0].ativo", is(true)). body("[0].dias", is(5)). body("[0].dataInicio", is("2019-04-23 00:00:00")). body("[0].dataTermino", is("2019-04-27 00:00:00")); }
  • 39. funcional Validar cenários positivos e negativos (caminho feliz | fluxo exceção) @Test(groups = {"funcional"}) public void validarEventoPeloID() { given(). auth().oauth2(accessToken). when(). get("evento/{id}", 110). then(). statusCode(HttpStatus.SC_OK). body("[0].id", is(110)). body("[0].descricao", is("TDC 2019 Florianópolis")). body("[0].chave", is("tdc-2019-florianopolis")). body("[0].ativo", is(true)). body("[0].dias", is(5)). body("[0].dataInicio", is("2019-04-23 00:00:00")). body("[0].dataTermino", is("2019-04-27 00:00:00")); } tag de grupo para filtrar a execução
  • 40. funcional Validar cenários positivos e negativos (caminho feliz | fluxo exceção) @Test(groups = {"funcional"}) public void validarEventoPeloID() { given(). auth().oauth2(accessToken). when(). get("evento/{id}", 110). then(). statusCode(HttpStatus.SC_OK). body("[0].id", is(110)). body("[0].descricao", is("TDC 2019 Florianópolis")). body("[0].chave", is("tdc-2019-florianopolis")). body("[0].ativo", is(true)). body("[0].dias", is(5)). body("[0].dataInicio", is("2019-04-23 00:00:00")). body("[0].dataTermino", is("2019-04-27 00:00:00")); } requisição para obter o detalhe de um determinado evento
  • 41. funcional Validar cenários positivos e negativos (caminho feliz | fluxo exceção) @Test(groups = {"funcional"}) public void validarEventoPeloID() { given(). auth().oauth2(accessToken). when(). get("evento/{id}", 110). then(). statusCode(HttpStatus.SC_OK). body("[0].id", is(110)). body("[0].descricao", is("TDC 2019 Florianópolis")). body("[0].chave", is("tdc-2019-florianopolis")). body("[0].ativo", is(true)). body("[0].dias", is(5)). body("[0].dataInicio", is("2019-04-23 00:00:00")). body("[0].dataTermino", is("2019-04-27 00:00:00")); } validação dos dados de retorno (body) * [0] existe ali porque o retorno é um array de uma posição * é um possível bug da implementação
  • 42. aceitação Garantir que um conjunto de endpoints funcionam como na UI
  • 43. Testar com a perspectiva do usuário ● Entrar no evento The Developers Conference Florianópolis ● Clicar na Trilha DevTest ● Visualizar os detalhes da palestra Automação e Virtualização de serviços REST com RestAssured + Wiremock + Docker
  • 44. aceitação @Test(groups = {"aceitacao"}) public void visualizaDetalhes_EncontrandoDados() throws ObjetoNotFoundException { String tituloPalestra = "Automação e Virtualização de serviços REST "; Evento evento = encontraEvento("TDC 2019 Florianópolis"); Modalidade trilha = encontraTrilha(evento, "Trilha DevTest"); Palestra palestra = encontraPalestra(evento, trilha, tituloPalestra); given(). auth(). oauth2(accessToken). pathParam("eventoID", evento.getId()). pathParam("modalidadeID", trilha.getId()). pathParam("palestraID", palestra.getId()). when(). get("/evento/{eventoID}/modalidade/{modalidadeID}/palestra/{palestraID}/palestrantes"). then(). statusCode(200). body("[0].member.nome", is("Elias Nogueira")). body("[0].member.empresa", is("Sicredi")); }
  • 45. aceitação @Test(groups = {"aceitacao"}) public void visualizaDetalhes_EncontrandoDados() throws ObjetoNotFoundException { String tituloPalestra = "Automação e Virtualização de serviços REST "; Evento evento = encontraEvento("TDC 2019 Florianópolis"); Modalidade trilha = encontraTrilha(evento, "Trilha DevTest"); Palestra palestra = encontraPalestra(evento, trilha, tituloPalestra); given(). auth(). oauth2(accessToken). pathParam("eventoID", evento.getId()). pathParam("modalidadeID", trilha.getId()). pathParam("palestraID", palestra.getId()). when(). get("/evento/{eventoID}/modalidade/{modalidadeID}/palestra/{palestraID}/palestrantes"). then(). statusCode(200). body("[0].member.nome", is("Elias Nogueira")). body("[0].member.empresa", is("Sicredi")); } funções auxiliares para chamadas a cada ação do usuário
  • 46. aceitação @Test(groups = {"aceitacao"}) public void visualizaDetalhes_EncontrandoDados() throws ObjetoNotFoundException { String tituloPalestra = "Automação e Virtualização de serviços REST "; Evento evento = encontraEvento("TDC 2019 Florianópolis"); Modalidade trilha = encontraTrilha(evento, "Trilha DevTest"); Palestra palestra = encontraPalestra(evento, trilha, tituloPalestra); given(). auth(). oauth2(accessToken). pathParam("eventoID", evento.getId()). pathParam("modalidadeID", trilha.getId()). pathParam("palestraID", palestra.getId()). when(). get("/evento/{eventoID}/modalidade/{modalidadeID}/palestra/{palestraID}/palestrantes"). then(). statusCode(200). body("[0].member.nome", is("Elias Nogueira")). body("[0].member.empresa", is("Sicredi")); } uso dos dados obtidos para a requisição
  • 48. ● Forma de simular comportamentos de componentes baseados em API ● Habilita o uso de serviços virtuais ao invés de serviços de produção mesmo que componentes chave não estejam disponíveis service virtualization
  • 49. service virtualization { "id" : "f238845e-369c-4a34-aa69-04d9240d7fb5", "name" : "evento_modalidade_palestra", "request" : { "urlPattern" : "/v1/publico/evento/110/modalidade/2685/palestra/10083", "method" : "GET" }, "response" : { "status" : 200, "bodyFileName" : "evento_modalidade_palestra_data.json", "headers" : { "Authorization": "*" } }, "persistent" : true, "insertionIndex" : 1 }
  • 50. service virtualization { "id" : "f238845e-369c-4a34-aa69-04d9240d7fb5", "name" : "evento_modalidade_palestra", "request" : { "urlPattern" : "/v1/publico/evento/110/modalidade/2685/palestra/10083", "method" : "GET" }, "response" : { "status" : 200, "bodyFileName" : "evento_modalidade_palestra_data.json", "headers" : { "Authorization": "*" } }, "persistent" : true, "insertionIndex" : 1 } sempre que uma requisição for igual a esta URL (inclusive com os dados)
  • 51. service virtualization { "id" : "f238845e-369c-4a34-aa69-04d9240d7fb5", "name" : "evento_modalidade_palestra", "request" : { "urlPattern" : "/v1/publico/evento/110/modalidade/2685/palestra/10083", "method" : "GET" }, "response" : { "status" : 200, "bodyFileName" : "evento_modalidade_palestra_data.json", }, "persistent" : true, "insertionIndex" : 1 } a api responderá os dados abaixo...
  • 52. service virtualization { "id": 10083, "slot": 6, "ordem": 1, "titulo": "Automação e Virtualização de serviços REST...", "descricao": ”Você sempre quis aprender a como testar...", "tipo": 2, "horario": "16:40" } dados de retorno