Dojo Session
Coding Dojo é uma prática de treino de programação onde programadores se reunem em um local físico (em tempos normais), escolhe um desafio/problema e começa a desenvolver juntos a solução para este problema, seguindo algumas regras que farão com que seja possível que todos participem no desenvolvimento da solução.
No Coding Dojo:
- Não importa se você é iniciante ou experiente.
- O objetivo é você aprender algo ou compartilhar algo que tem experiência.
- A idéia não é finalizar um projeto completo, e sim trocar experiências.
- Desenvolver a solução em baby steps:
- Vamos desenvolver usando TDD, desevolvendo testes simples primeiro e depois incrementando o código.
- Daremos sempre preferência para a implementação mais básica, e depois vamos refatorando o código para deixá-lo mais robusto.
Por que usar o Cypress?
O Cypress é um framework de testes automatizados amigável e fácil de usar. Para começar a escrever seus testes automatizados nenhuma configuração é necessária. Todas as ferramentas de teste de unidade com as quais você já está familiarizado estão incluídas.
Com o Cypress você pode:
- testes de e2e;
- testes de unidades;
- testes de componentes;
- testes de API;
- testes de testes de regressão visual;
- e até mesmo pode combinar todos eles.
Nosso Alvo
Utilizaremos como alvo dos nossos testes a API Serverest, desenvolvida pela comunidade opensource, que nos permite testar os métodos HTTP mais utilizados.
Objetivos
- Acessar o endereço da API Serverest.
- Usar o método GET para retornar informações.
- Interagir com o objeto retornado.
- Verificar o conteúdo do body do response.
Passo 1: Criar um projeto Cypress
Primeiro, vamos iniciar um projeto node digitando o comando:
npm init
Depois vamos instalar o Cypress no projeto:
npm i cypress -D
Agora vamos adicionar as seguinte linhas no arquivo package.json
:
"scripts": {
"cypress:open": "./node_modules/.bin/cypress open",
"cypress:run": "./node_modules/.bin/cypress run --spec **/*.spec.js"
Esses comando servirão para executarmos os nossos testes.
Para iniciar o projeto Cypress execute o comando:
npm run cypress:open
Após executar esse comando, uma estrutura de projeto será criada.
Vamos então limpar o conteúdo do diretório integration
. Depois vamos criar um diretório dentro em integration
chamado Produtos
.
Passo 2: Criando o primeiro teste
Dentro de Produtos
vamos criar um arquivo chamado GETprodutos.spec.js
, e vamos começar a escrever os nossos testes:
O Mocha nos oferece a seguinte estrutura de organização dos testes:
describe('Mocha’s interface - BDD', () => {
context('it provides a way to keep tests easier to read and organized.', () => {
it('This is your test case', () => {
expect(true).to.eq(true)
});
});
});
Isso irá facilitar a leitura dos testes quando forem executados.
/// <reference types="cypress" />
describe('Products api', () => {
context('GET /produtos', () => {
it('should return an array with all products', () => {
cy.request({
method: 'GET',
url: 'https://serverest.dev/produtos'
})
.should((response) => {
console.log(response.body)
expect(response.status).to.eq(200)
expect(response.body.quantidade).to.eq(2)
});
});
});
});
Usar .should()
permite que você use o response em uma função de callback e deve ser usado quando você precisa
manipular alguns valores ou fazer algumas asserções.
Se quisermos adicionar um novo teste a este contexto, basta criar um novo bloco de context
e it
:
/// <reference types="cypress" />
describe('Products api', () => {
context('GET /produtos', () => {
it('should return an array with all products', () => {
cy.request({
method: 'GET',
url: 'https://serverest.dev/produtos'
})
.should((response) => {
cy.log(response.body)
expect(response.status).to.eq(200)
expect(response.body.quantidade).to.eq(2)
})
});
});
context('GET /produtos + query string', () => {
it('should return an array with only the filtered product', () => {
cy.request({
method: 'GET',
url: 'https://serverest.dev/produtos',
qs: {
_id: 'BeeJh5lz3k6kSIzA'
}
})
.should((response) => {
expect(response.body.produtos).to.be.an('array')
expect(response.body.produtos[0])
.to.contains({
nome: "Logitech MX Vertical",
preco: 470,
descricao: "Mouse",
quantidade: 382,
_id: "BeeJh5lz3k6kSIzA"
})
})
});
});
});
Note que foi necessário duplicar o método GET com as mesmas informações. Como melhorar podemos esse código?
Vamos encapsular o request GET em um arquivo separado, para que possamos reutilizá-lo sempre que necessário. Nossa estrutura de Projeto ficará assim:
Diretório Produtos
Séra o diretório responsável por armazenar todas as requisições relacionadas a Produtos. Detro dele teremos os diretórios:
requests
tests
Dretório request
Será o diretório responsável por armazenar nossas requisições HTTP, exemplo:
GETprodutos.request.js
POSTprodutos.request.js
PUTprodutos.request.js
DELETEprodutos.request.js
Diretório tests
Será o diretório responsável por armazenar nossos testes, exemplo:
GETprodutos.spec.js
POSTprodutos.spec.js
PUTprodutos.spec.js
DELETEprodutos.spec.js
Vamos adicionar a baseUrl
no arquivo cypress.json
:
{
"baseUrl": "https://serverest.dev",
"video": false
}
Depois criaremos o arquivo GETprodutos.request.js
dentro do diretório requests
. Nesse arquivo iremos criar uma
função que será responsável por fazer o GET no endpoint /produtos
:
/// <reference types="cypress" />
function allProducts() {
return cy.request({
method: 'GET',
url: '/produtos',
failOnStatusCode: false
});
};
export { allProducts };
Não se esqueça de exportar a função criada.
No arquivo GETprodutos.spec.js
importe a função criada:
import * as GETprodutos from '../requests/GETprodutos.request';
Substitua o request pela função criada anteriormente:
/// <reference types="cypress" />
import * as GETprodutos from '../requests/GETprodutos.request';
describe('Products api', () => {
context('GET /produtos', () => {
it('should return an array with all products', () => {
GETprodutos.allProducts()
.should((response) => {
cy.log(response.body)
expect(response.status).to.eq(200)
expect(response.body.quantidade).to.eq(2)
});
});
});
context('GET /produtos + query string', () => {
it('should return an array with only the filtered product', () => {
GETprodutos.allProducts()
.should((response) => {
expect(response.body.produtos).to.be.an('array')
expect(response.body.produtos[0])
.to.contains({
nome: "Logitech MX Vertical",
preco: 470,
descricao: "Mouse",
quantidade: 382,
_id: "BeeJh5lz3k6kSIzA"
});
});
});
});
});
Passo 3: CI - Executando testes no Github Actions
Para criar um pipeline de execução dos nossos testes usando o Github Actions, crie um diretório na raíz do projeto com
o nome .github
e dentro dela outro diretório chamado workflows
. Dentro de workflows crie um arquivo chamado actions.yml
com o seguinte conteúdo:
name: Cypress CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x]
steps:
- uses: actions/checkout@v2
- name: Cypress tests using Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm i
- run: npm run cypress:run
Pronto, a cada commit no nosso código, todas as specs serão executadas no pipeline do Github.