Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/lucasrmagalhaes/cypresstest-angular
Utilizando o Cypress E2E para testar um blog em Angular.
https://github.com/lucasrmagalhaes/cypresstest-angular
angular cypress dio
Last synced: 2 days ago
JSON representation
Utilizando o Cypress E2E para testar um blog em Angular.
- Host: GitHub
- URL: https://github.com/lucasrmagalhaes/cypresstest-angular
- Owner: lucasrmagalhaes
- Created: 2020-12-29T00:53:04.000Z (almost 4 years ago)
- Default Branch: main
- Last Pushed: 2023-01-07T22:49:38.000Z (almost 2 years ago)
- Last Synced: 2023-03-03T22:32:57.609Z (over 1 year ago)
- Topics: angular, cypress, dio
- Language: JavaScript
- Homepage:
- Size: 4.35 MB
- Stars: 10
- Watchers: 1
- Forks: 6
- Open Issues: 16
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
Testes E2E com CypressProgramação
- Motivação
- Cypress?
- Trade-offs
- Pré-Requisitos
- O que vamos testar
- Instalação
- Removendo o Protactor
- Cypress Test Runner
- Primeiro Teste
- Como Rodar
- Configuração
- Roteiro de Testes
- Support Commands
- Fixture
- Relatórios e Integrações
- Plugins
- Incluir Outra Spec
- Falso Negativo
- DevOps
- Paralelismo
- Analytics Dashboard
Motivação
Agilidade (- tempo)
Qualidade (- bugs)
Economia de horas (- custo)
Por que não somente Testes Unitários?
O teste E2E simula a navegação pelo usuário, validando não só a interface frontend como integração com o backend.
Teste unitário valida a qualidade do Código. E2E valida a aplicação.
Cypress?
JavaScritpt: Baixa curva de aprendizado, custo com treinamento reduzido.
Performance: Paralelismo, Stress Test, Load Test.
Recorder: Cypress Recorder (Chrome), Katalon Recorder.
Produtividade: Auto-reload, Spies, Stubs e Mocks.
Licença: OpenSource (Mit).
End-to-end tests, Integration tests, Unit tests.
Diferente do Selenium ou Appium, que injetam comandos exernos, o Cypress roda no mesmo contexto JS do App, com acesso instantâneo a todas as interações e eventos.
Trade-offs
Cypress não é uma ferramenta de automação geral.
Os comandos do Cypress sempre são executados dentro de um navegador.
Nunca haverá suporte para várias guias do navegador.
Você não pode usar o Cypress para controlar dois navegadores no mesmo teste.
Pré-Requisitos
Git
Node
O que vamos testar
Projeto para teste: Angular Real World Example App
git clone https://github.com/gothinkster/angular-realworld-example-app
cd angular-realworld-example-app
npm install
npm run start
http://localhost:4200/
Aqui temos um aplicativo Angular contendo exemplos "reais" (CRUD, autenticação, etc) de acordo com a especificação para exemplos RealWord.
Vamos adicionar o Cypress!
Instalação
Abra outro terminal. Na pasta/angular-realworld-example-app/ execute:
npm install cypress --save-dev
npx cypress -v
Caso tenha problemas com Proxy ou Firewall, baixe o binário e configure a variável de ambiente antes de instalar:
set CYPRESS_INSTALL_BINARY=C:\cypress.zip
npm install cypress --save-dev --verbose
Removendo o Protactor
Remova o pacote:
npm uninstall protactor --save-dev
Exclua a pasta /e2e/
Do package.json, remova a linha: "e2e": "ng e2e"
Cypress Test Runner
npx cypress open
O comando "cypress open", além de abrir o Cypress Test Runner, cria a pasta inicial /cypress/ e o arquivo de configuração /cypress.json
E já vem com /examples/ dos principais comandos Cypress.
Primeiro Teste
cypress/integrations/exemplo.spec.js
```js
describe('Primeiro Teste', () => {
it('Exemplos Cypress', () => {
cy.visit('https://example.cypress.io')
expect(true).to.equal(true)
})
})
```
describe and it come from Mocha
expect comes from Chai
Como Rodar
Para executar todos os testes da pasta /cypress/integration/:
npx cypress run
Para executar somente um roteiro:
npx cypress run --spec "cypress/integration/examples/example.spec.js"
Para abrir a interface do Cypress Test Runner:
npx cypress open
Configuração
cypress.json
{
"baseUrl": "http://localhost:4200",
"pageLoadTimeout": 30000,
"defaultCommandTimeOut": 30000,
"viewportHeight": 800,
"viewportWidth": 500,
"retries": 3
}
Roteiro de Testes
- Cadastro
- Login
- Perfil
- Feeds
- Paginação
- Post
- Tags
- Comentários
- Seguir
- Logout
Cypress Recorder
Extensão para o Chrome capaz de gravar um roteiro base.
Recomendado para capturar os seletores no DOM.
```js
describe('Conduit Cadastro', () => {
const usuario = 'usuario' + (new Date()).getTime()
const senha = 'senha' + (new Date()).getTime()
it('Novo Usuário', () => {
cy.visit('/register')
cy.get('[formcontrolname=username]').type(usuario)
cy.get('[formcontrolname=email]').type(usuario+'@email.com')
cy.get('[formcontrolname=password]').type(senha)
cy.get('.btn').click()
cy.contains('.nav-item:nth-child(4) > .nav-link', usuario)
.should('be.visible')
})
})
```
npx cypress run --spec "cypress/integration/register.spec.js"
Support Comands
cypress/support/index.js
```js
Cypress.Commands.add('login', (username, password) => {
cy.visit('/login')
cy.url().should('include', '/login')
cy.get('[formcontrolname=email]').type(username)
cy.get('[formcontrolname=password]').type(password)
cy.get('.btn').click()
})
```
Login
cypress/integration/login.spec.js
```js
describe('Conduit Login', () => {
it('Login sucesso', () => {
cy.login('[email protected]', 'testecypress')
cy.get('.nav-item:nth-child(4) > nav-link').click()
cy.get('.btn:nth-child(5)').click()
cy.url().should('contain', '/settings')
})
it('Dados Inválidos', () => {
cy.login('[email protected]', 'senhaerrada')
cy.get('.error-messages > li')
.should('contain', 'email or password is invalid')
})
})
```
Perfil
cypress/integration/perfil.spec.js
```js
describe('Profile', () => {
it('Editar Perfil', () => {
cy.login('[email protected]', 'testecypress')
cy.contains('testecypress').click()
cy.contains('Edit Profile Settings').click()
cy.get('[formcontrolname="image"]').clear()
cy.get('[formcontrolname="image"]')
.type('https://thispersondoesnotexist.com/image')
cy.get('[formcontrolname="password"]').type('testecypress')
cy.contains('Update Settings').click()
})
})
```
Feeds
cypress/integration/feed.spec.js
```js
describe('Conduit Feed', () => {
it('Ver Feeds', () => {
cy.login('[email protected]', 'testecypress')
cy.get('.nav-pills > .nav-item:nth-child(1) > .nav-link').click();
cy.get('.nav-pills > .nav-item:nth-child(2) > .nav-link').click()
cy.get('app-article-preview:nth-child(1) .btn').click()
})
})
```
Pagination
cypress/integration/pagination.spec.js
```js
describe('Paginação', () => {
it('Paginar', () => {
cy.visit('/')
cy.get('.page-item.active > a').contains('1')
cy.get('.page-item:nth-child(2) > .page-link').click()
cy.get('.page-item.active > a').contains('2')
cy.get('.page-item:nth-child(3) > .page-link').click()
cy.get('.page-item.active > a').contains('3')
})
})
```
Post
cypress/integration/post.spec.js
```js
describe('Post', () => {
beforeEach(() => {
cy.login('[email protected]', 'testecypress')
})
it('Novo', () => {
const tit = 'Cypress E2E'
cy.contains('New Article').click()
cy.location('pathname').should('equal', '/editor')
cy.get('[formcontrolname=title]').type(tit)
cy.get('[formcontrolname=description]').type('Ponta a Ponta')
cy.get('[formcontrolname=body]').type('Agilidade, Qualidade')
cy.contains('Publish Article').click()
cy.get('h1').contains(tit)
})
it('Editar', () => {
cy.contains('testecypress').click()
cy.location('pathname').should('contains', '/profile')
cy.get('.article-preview').get('h1').first().click()
cy.contains('Edit Article').click()
cy.get('[formcontrolname=body]').clear()
cy.get('[formcontrolname=body]').type('Economia')
cy.contains('Publish Article').click()
cy.contains('Economia')
})
})
```
Tags
cypress/integration/tags.spec.js
```js
describe('Tags', () => {
it('Adicionar', () => {
cy.login('[email protected]', 'testecypress')
cy.contains('testecypress').click()
cy.location('pathname').should('contains', '/profile')
cy.get('.article-preview').get('h1').first().click()
cy.contains('Edit Article').click()
cy.get('[placeholder="Enter tags"]').type('dungeons{enter}');
cy.get('[placeholder="Enter tags"]').type('dragons{enter}');
cy.contains('Publish Article').click();
cy.get('.tag-list').contains('dragons');
})
})
```
Comentários
cypress/integration/comentarios.spec.js
```js
describe('Comentarios', () => {
it('Escrever', () => {
cy.login('[email protected]', 'testecypress')
cy.contains('Global Feed').click()
cy.get('.preview-link').first().click()
cy.get('.form-control').type('Sensacional!')
cy.get('.btn-primary').click()
cy.contains('Sensacional!')
})
})
```
Seguir
cypress/integration/seguir.spec.js
```js
describe('Seguir', () => {
it('Seguir Usuário', () => {
const usuario = 'usuario'+(new Date()).getTime();
const senha = 'senha'+(new Date()).getTime();
cy.visit('/register', { timeout: 10000 })
cy.get('[formcontrolname=username]').type(usuario)
cy.get('[formcontrolname=email]').type(usuario+'@email.com')
cy.get('[formcontrolname=password]').type(senha)
cy.get('.btn').click()
cy.wait(10000)
cy.visit('/profile/testecypress')
cy.contains('Folow').click()
})
})
```
Logout
cypress/integration/logout.spec.js
```js
describe('Logout', () => {
it('Logout via Perfil', () => {
cy.login('[email protected]', 'testecypress')
cy.contains('Settings').click()
cy.url().should('include', '/settings')
cy.get('.btn-outline-danger').click()
})
})
```
Fixture: Data-Driven Tests
cypress/support/index.js
```js
Cypress.Commands.add('loadUsers', () => {
cy.fixture('users')
.as('users')
})
```
cypress/integration/test.spec.js
```js
// this.users.default.username
// this.users.default.pass
// this.users.client.username
// this.users.client.pass
```
cypress/fixtures/users.json
```js
{
"default":{
"user": "basic-user",
"pass": "testpass"
},
"client":{
"user": "premium-user",
"pass": "testpass"
}
}
```
Funcionalidades extendidas
Relatórios e Integrações
Reports json, html e xml
- mocha
- mochawesome
- mochawesome-merge
- mochawesome-report-generator
- cypress-multi-reporters
- cypress-slack-reporter
- cypress-sonarqube-reporter
Falso Negativo
Rede, microserviços e dependências podem falhar
Um teste E2E pode falhar por conta de outros recursos além do controle da sua aplicação:
- Uma API pode falhar
- Insdisponibilidade de Rede ou Firewall
- Indisponibilidade de recursos como CPU e memória
- Deploys paralelos
Como Identificar?
Verifique se os as apis e serviços estão rodando:
```js
it('Backend Health Checks', () => {
cy.request('https://login/healthcheck').then((response) => {
expect(response.status).to.eq(200)
})
cy.request('https://database/healtcheck')
.then((response) => {
expect(response.status).to.eq(200)
})
})
```
DevOps
Environments:
- CYPRESS_BASE_URL
- CYPRESS_VIDEO_COMPRESSION
- CYPRSS_REPORTER
- CYPRESS_INSTALL_BINARY
- CYPRESS_RECORD_KEY
# cypress/Dockerfile# Imagem base
FROM cypress/base:14.0.0# Copia os arquivos para a imagem
COPY ./# Opcional - Pega o binário local
#ENV CYPRESS_INSTALL_BINARY=/cypress.zipRUN npm install --verbose
RUN $(npm bin)/cypress verify# Inicialização do container
CMD $(npm bin)/cypress run
# prompt / terminaldocker build -t cypress:0.0.1
docker run cypress:0.0.1
Paralelismo
cypress run --parallel --record
Cypress Dashboard
cypress run --record --key=abc123
+ exemplos
1 - Cypress Kitchen Sink
git clone
https://github.com/cypress-io/cypress-example-kitchensink.gitcd cypress-example-kitchensink
npm install
npm start
npm run cy:open
2 - Cypress Real Word App
git clone
https://github.com/cypress-io/cypress-realworld-app.gitcd cypress-realworld-app
npm install
npm dev
npm run cypress:open