Sobre o Projeto
Preparação do Ambiente
Cenário de Teste
Primeiros Passos no Postman
ㅤPre-request Script
ㅤRealizando Requisições do tipo GET
ㅤPassando os Requisitos para o Código
ㅤCriando Massa de Dados (Objetos)
ㅤPassando a Massa de Dados para o Body
Body
Tests
ㅤDeclaração de Variáveis
ㅤFunção para criação da Base dos Testes
ㅤCriando os Testes
Contribuições
Notas Finais da Autora
- Criação de massa de dados na aba pre-request script do postman para atingir a expectativa do teste.
- Enviar dados de forma dinâmica para o corpo da requisição na aba body.
- Validar a saída das requisições na aba tests.
- Criar uma conta no Postman.
- Instalar Postman.
- Baixar a collection desse repositório.
- Importar a collection no Postman.
O trecho abaixo fará uma requisição para obter a lista de usuários cadastrados no servidor. Dessa lista, será salvo em existingEmails apenas o e-mail desses usuários. Isso auxiliará em um teste futuro como base para checar se o email do usuário é duplicado.
pm.sendRequest({
url: 'https://andreina-qa-test.onrender.com/api/users',
method: 'GET',
header: {
'Authorization': `${pm.collectionVariables.get("token")}`
}
}, function (err, response) {
if(err){
console.error('Erro ao tentar acessar lista de usuários', err)
}
pm.variables.set('existingEmails', response.json().map(item => (item.email)))
})
O Processo de vida do código quando acontece uma requisição é de executar as demais linhas do código sem aguardar o resulltado da requisição. Portanto, será necessário adicionar um timer (também pode ser um assync await) fazendo com que as demais linhas do código sejam executadas apenas após receber os dados da requisição anterior.
setTimeout(function () {
}, 2000)
Dentro do setTimeout será criado a variável validation onde conterá as regras de negócios definidas em #1, além disso, contará com uma lista de e-mails inválidos para validações futuras
var validation = {
minNome: 3,
maxNome: 80,
minSenha: 6,
lenTelefone: 11,
validCargo: ['QA', 'DEV', 'PO'],
emailDuplicated: pm.variables.get('existingEmails')
}; pm.variables.set('validation', validation)
var ListOfInvalidEmails = [
"invalid_email", // Does not have '@'
"invalid@.com", // Dot after '@'
"invalid@domain", // Without extension (.com, .org, etc.)
"@invalid.com", // Begins with '@'
"invalid.email.com", // Colon in a domain
"invalid@domain@.com", // More than one '@'
"invalid email@domain.com", // Space in an email
"invalid.email@domain_com", // Domain underscore
"invalid.email@domain..com", // Dot duplicate in domain
"invalid@domain.-com", // Hyphen after dot in domain
"invalid.email@domain.com." // Dot at end of email
// Add more invalid emails if needed
]
Logo após o código acima, ainda dentro do setTimeout, será criado o objeto validData que contem os campos Nome, Senha, Email, Telefone e Cargo com dados válidos.
var validData = { // Dados Válidos
nome: pm.variables.replaceIn('{{$randomFirstName}}'), // Nome Válido
senha: 'abc123', // Senha Válida
email: pm.variables.replaceIn('{{$randomEmail}}'), // Email Válido
telefone: _.random(10000000000, 99999999999), // Telefone Válido
cargo: _.sample(validation.validCargo) // Cargo Válido
}
Com base no objeto validData, será criado uma cópia dele para os objetos abaixo.
- emptyName
- minName
- maxName
- emptyPassword
- minPassword
- emptyEmail
- duplicatedEmail
- invalidEmail
- invalidTelefone
- lenTelefone
- emptyCargo
- invalidCargo
E em seguida o objeto será modificado para conter a falha desejada. Segue exemplo de como isso ocorre:
var minName = _.cloneDeep(validData); minName ={ // Mínimo Nome
...minName, nome: 'a'.repeat(validation.minNome - 1)
}
var emptyPassword = _.cloneDeep(validData); emptyPassword ={ // Senha Vazia
..emptyPassword, senha: null
}
var duplicatedEmail = _.cloneDeep(validData); duplicatedEmail ={ // Email Duplicado
...duplicatedEmail, email: _.sample(validation.emailDuplicated)
}
var invalidEmail = _.cloneDeep(validData); invalidEmail ={ // Email Duplicad.
...invalidEmail, email: _.sample(ListOfInvalidEmails)
}
Inclusive é possível agrupar falhas dependendo de como o back-end funciona. Por exemplo, no caso de deixar todos os dados vazios e o servidor retornar mensagem de dados vazios para cada campo, é possível criar apenas um objeto contendo todos os campos recebendo null.
Ao final da massa de testes, dentro do setTimeout está sendo declarado testData que é a variável que receberá a massa de dados dos testes. Tendo recebido esses dados, será percorrido cada um deles e criado uma variávevl visível no contexto da requisição (ou seja, para todas as abas). Isso servirá para enviar esses dados para o corpo da requisição (body).
setTimeout(function () {
const testData = TESTE_AQUI
for (const key in testData) {
pm.variables.set(`qa_${key}`, testData[key] === null
? null
: `"${testData[key]}"`)
}
}, 2000)
No body será inserido a variável correspondente ao campo, conforme criado no pre-request. Dessa forma será possível enviar de forma automática os dados da requisição, sem a necessidade de escrever manualmente.
{
"nome": {{qa_nome}},
"senha": {{qa_senha}},
"email": {{qa_email}},
"telefone": {{qa_telefone}},
"cargo": {{qa_cargo}}
}
Logo no topo da aba testes haverá as variáveis abaixo sendo message responsável pela mensagem retornada ao enviar a requisição, req o copo da requisição enviada e validation o objeto previamente criado no pre-request. Ainda declarando as variáveis que ajudaram na validação, foi declarado o emailRegex com objetivo de validar e-mails.
const message = pm.response.text()
const req = JSON.parse(pm.request.body)
const validation = pm.variables.get("validation")
const emailRegex = /^[\w\.-]+@[\w\.-]+\.\w+$/
Abaixo temos a base que dará luz aos testes que serão realizados. A função recebe:
- testName: O nome do teste. Ex.: "Bloqueio de telefone diferente de 11 dígitos"
- condition: A condição para que o teste seja executado. Ex.: O teste só será executado se o resultado a seguir for verdadeiro
req.telefone?.length !== 11
- expectedResult: O resultado esperado quando a condição for atingida. Ex.: Dado que condition é verdadeiro então o resultado do código a seguir também deve ser verdadeiro
pm.response.code === 400 && message.includes(`Campo telefone deve ter 11 dígitos`)
Podemos concluir que condition e expectedResult recebem booleanos por parâmentro.
function test(testName, condition, expectedResult) {
if (condition) {
pm.test(testName, function () {
pm.expect(expectedResult).to.be.true
})
return true
}
return false
}
Muitos testes foram criados e todos os testes estão no arquivo Hands On.postman_collection para documentação não ficar extensa, estarei dando apenas alguns exemplos. Mas existe uma gama de exemplos no arquivo, alguns com técnicas diferentes para deixar o código mais clean.
Nos exemplos abaixo, temos a variável isTelephoneInvalidLength sendo declarada como false o que significa: "O tamanho de telefone é inválido? MENTIRA". Logo abaixo a variável chama a função anterior referente a base de teste, nela, passando por parâmetro o nome do teste, a condição para que o teste ocorra e o resultado esperado para o caso de o teste ocorrer. O teste ocorrendo retorna true no caso de o telefone ser inválido ou false no caso de válido.
Abaixo, a função teste é chamada com o objetivo de validar se os dados passados no body são válidos, a condição é que todos os testes realizados incluindo o teste anterior, isTelephoneInvalidLength, retorne false que, como explicado anteriormente, significa que não é inválido, sendo true uma afirmação de inválido. Atingindo a condição, o resultado do teste precisa atingir o código e mensagem de confirmação.
let isTelephoneInvalidLength = false
isTelephoneInvalidLength = test(
`Bloqueio de telefone diferente de 11 dígitos | telefone tem ${req.telefone?.length} dígitos`,
req.telefone !== null && req.telefone?.length !== 11,
pm.response.code === 400 && message.includes(`Campo telefone deve ter 11 dígitos`)
)
test(
`Dados Válidos
| nome: ${req.nome};
senha: ${req.senha};
email: ${req.email};
telefone: ${req.telefone};
cargo: ${req.cargo}`,
!isRequiredFieldsEmpty
&& !isFieldsOutOfLimit
&& !isTelephoneInvalid
&& !isTelephoneInvalidLength
&& !isEmailDuplicated
&& !isEmailInvalid
&& !isCargoInvalid,
pm.response.code == 201 && message.includes("Usuário registrado com sucesso")
)
![]() Erik Felipe |
Gostaria de agradecer ao Erik Felipe pelo backend que ele criou para a nossa API no projeto. A habilidade dele é fora de série e fez toda a diferença. Valeu demais, Erik, você arrebenta! 👏 |
![]() Andreina Oliveira |
O conhecimento em validação de REST API Test é essencial para cobertura de testes no backend. Hoje temos várias formas de garantir esse teste. O conteúdo apresentado nesse repositório apresenta como realizar essas validações utilizando a ferramenta Postman, mas considere que nem sempre essa ferramenta será a mais indicada para o seu contexto. A técnicas apresentada pode ser adaptada e inclusive tranformada em um único teste que valida todo os cenários, visto que a forma em que hoje o código foi implemantado a validação é feita por requisição. Sinta-se livre para usar o código como base para seus testes. Em caso de dúvidas e sugestões estou disponível para contato. |