Automatizando testes, em APIs REST, com Cypress e NodeJS

Automatização de testes já é uma realidade vivenciada por vários projetos de software. Isso se dá para tentar garantir, cada vez mais, a qualidade do que está sendo produzido pelos desenvolvedores e ter uma maior segurança, quando algo for alterado via código, de que nada na aplicação foi alterado/danificado, seja as iterações com o usuário, regras de negócios e comportamentos de APIs.

Neste cenário, irei abordar os testes na camada de Serviço, onde falarei sobre os testes de contrato de API. Mas antes de iniciar, vou explicar alguns conceitos básicos:

  • Significa “Application Programming Interface”, é uma forma de integração entre sistemas. São um tipo de “ponte” que conecta aplicações.
  • Estão entre a camada de UI e de Testes Unitários
  • Garante que a estrutura do JSON de retorno esteja correta
  • Podem ser automatizados
  • Traduzindo significa requisição, o qual é um pedido de algum cliente ao servidor. Tal pedido contém uma série de dados que são utilizados para descrever exatamente o que o cliente precisa.
  • Traduzindo significa resposta, o qual é a resposta que o servidor retorna para o cliente, podendo ser de sucesso ou de erro.

Com alguns conceitos alinhados, vamos ver o que terá no cenário:

O Cypress irá realizar os testes nos end-points da API. Porém, antes de qualquer iteração, tem-se o NodeJS como recurso para preparar e tornar mais seguro e controlado o nosso ambiente, ao manipular o banco de dados.

Desenvolvimento

Antes de tudo, vamos utilizar as seguintes ferramentas:

Com essas ferramentas já instaladas na máquina/computador, vamos abrir o VS Code, apontar para alguma pasta vazia (opção [Open Folder]), abrir o terminal e criar o projeto com o seguinte comando:

npm init -y

Após execução do comando, será criado um arquivo [package.json], o qual é uma espécie de manifesto do projeto. Feito isso, instala-se os seguintes pacotes com seus respectivos comandos:

npm i cypress -D

npm i mongodb -D

O primeiro irá instalar o Cypress e o segundo irá instalar o driver do MongoDB para NodeJS, ambos como dependência de desenvolvimento.

O próximo passo será criar pastas chamada [src/api-test]. Vale ressaltar que a nossa aplicação de teste pode conter vários projetos de atuação pelo Cypress. No caso teremos apenas um único projeto.

mkdir src/api-test

No arquivo [package.json], altera-se a seção scripts para que fique conforme o código abaixo:

Feito isso, basta executar o seguinte comando, no terminal, para abrir o playground do Cypress e, logo em seguida, toda a estrutura do projeto será criada na devida pasta.

npm run cy:api

A estrutura ficará assim:

E este é o playground do Cypress, contendo alguns testes, já implementados, de exemplo:

Nas estrutura, vamos focar apenas nas partes [integration],[plugins] e no arquivo [cypress.json], pelos seguintes motivos:

  • integration: é onde se escreve os testes, efetivamente
  • plugins: é onde ficará os códigos em NodeJS, que farão alguma ação no banco de dados
  • cypress.json: arquivo o qual você consegue deixar algumas configurações para os testes

Agora, vamos para o desenvolvimento em NodeJS. Primeiro, faz-se a conexão com o banco de dados da API para poder manipulá-lo de acordo com a necessidade. Isso se dá criando dois novos arquivos dentro de [plugins], um chamado [userRepository.js] e outro [config.json].

  • userRepository.js: ficará o código que irá manipular uma collection do banco de dados
  • config.json: qualquer configuração que será necessária para o repositório

Alimenta-se o arquivo [config.json] com as configurações que serão necessárias para conexão com o MongoDB:

Neste arquivo, temos a string de conexão e o nome da base de dados que iremos utilizar.

Com isso, vamos para o desenvolvimento do repositório. Primeiro, precisa-se importar as configurações de conexão do mongo, localizada no arquivo [config.json], e algumas variáveis do pacote mongodb que foi instalado anteriormente, conforme mostrado abaixo:

Cria-se uma classe chamada UserRepository e, logo após, vamos exportá-la para que ela possa ser utilizada em outros locais no projeto, ficando assim:

Nesta classe irá conter os métodos de inserir um novo usuário, deletar todos os usuários e recuperar o id de todos os usuários, além de ter o método que irá realizar a conexão e recuperar a collections com a qual iremos trabalhar.

Primeiro, vamos fazer o método que fará a conexão com o banco e que recuperará a collection [user]. Construiremos um método a parte e o mesmo será chamado via construtor:

Agora, podemos focar apenas nos métodos que irão operar no banco de dados, ficando assim:

O código completo segue abaixo:

Feito isso, vamos modificar o arquivo [index.js] que está dentro de [plugins] para que ele possa consumir nosso repositório e, ao mesmo tempo, disponibilizá-los para os nossos testes, desta maneira:

Através do plugin [task] podemos executar códigos em NodeJS.

Terminado isto, vamos para os testes efetivamente. Dentro de [integration] vamos criar uma nova pasta chamada [user-test] e, dentro desta pasta, um novo arquivo chamado [user.spec.js]. É dentro deste arquivo que ficará todos os testes da API voltada para os end-points que trabalham com o usuário.

Alimenta-se o arquivo [cypress.json] com a url base da API e, também, com um objeto default para podermos utilizar, conforme mostrado abaixo:

Vamos importar essas configurações no nosso arquivo que ficará o código de teste, dessa forma:

Agora vamos codificar os nossos testes, começando do cenário de recuperar usuários. Especificamente, iremos testar o end-point de verbo GET da nossa API, o qual recupera todos os usuários cadastrados. Para isso, vamos criar uma suíte que irá agrupar todas as nossas iterações de teste, desta maneira:

Após isso, vamos utilizar dois hooks dentro do [describe], um para poder deletar todos os usuários da base e inserir apenas um (antes de todas as iterações) e outro para fazer a requisição na API (antes de cada iteração):

Um ponto de atenção ao utilizar o comando [I] para fazer a requisição, onde coloca-se um “alias” [getUser] para poder facilitar o uso dessa chamada. E para exemplificar a utilização detes request, segue abaixo o retorno do mesmo:

Agora podemos criar as iterações de teste. Iremos criar duas, uma que irá validar o content-type do cabeçalho e outra que irá validar o código do status de retorno, ficando assim:

Com isso terminamos nosso primeiro cenário de testes. O próximo iremos abordar a criação de um usuário, onde testaremos o verbo POST, o qual realiza o cadastro de um novo usuário pela API. E o primeiro passo é igual ao anterior, vamos criar nossa suite de testes, assim:

E iremos utilizar, desta vez, apenas um hook, o qual irá fazer a requisição na API a cada iteração de teste:

Para exemplificar, segue abaixo um retorno da requisição mostrada acima:

E agora vamos criar as devidas iterações. Neste caso terá três iterações:

  • a primeira que irá validar o content-type do cabeçalho
  • a segunda que irá validar o código do status de retorno
  • a terceira que irá validar o corpo do JSON retornado, contendo:
    - se existe a propriedade [id]
    - se a propriedade [id] é uma string
    - se no corpo as pripriedades [name] e [cpf] são as mesmas que foram enviadas via request

Ficando desta maneira:

E, por fim, teremos o cenário que irá abordar a exclusão de usuário, realizando o teste em um end-point de verbo DELETE. Vamos, então, criar mais uma nova suite de testes:

E, dentro dela, iremos utiliar um hook que será executado, apenas, antes de qualquer iteração. Tal hook irá deletar todos os usuários da base, irá inserir um novo, irá recuperar o primeiro id de um usuário existente e fará a request:

Por fim, teremos apenas uma iteração de teste, a qual irá validar o código do status de retorno:

Com isso finalizamos nosso desenvolvimento. O código completo se encontra abaixo:

E abaixo segue o resultado da execução dos mesmos, com o passo a passo de uma das iterações para exemplificar:

O código da aplicação se encontra no GitHub.

Conclusão

Através de uma ferramenta simples e leve conseguimos criar, em poucos passos, nossos testes e, por meio de recursos da propria ferramenta, conseguimos utilizar códigos em NodeJS para poder manipular conteudos externos, garantindo assim uma maior confiabilidade e segurança nos testes a serem desenvolvidos.

Bachelor in Computer Science, MBA in Software Architecture and .NET Developer.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store