Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tests e2e utilizando playwright com relatório #1716

Draft
wants to merge 26 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
405aaf5
feat(test e2e): added dependency playwright and your config file
nobregao May 4, 2024
14171b5
test(test e2e): added tests for anonymous and default user
nobregao May 4, 2024
a1f428a
test(test e2e): added .env test
nobregao May 4, 2024
9cc7706
chore(test e2e): move tests e2e `tests/integration/e2e` to `tests/e2e`
nobregao May 4, 2024
d88f2d7
feat(test e2e): update `.gitignore` and `.prettierignore`
nobregao May 22, 2024
3fc4cff
refactor(test e2e): rename where using `post` for `content`
nobregao May 22, 2024
a8fb197
feat(test e2e): update `vitest.config` define `include` attribute
nobregao May 26, 2024
1447b25
ci(test e2e): including e2e job
nobregao May 4, 2024
97e9853
test(test e2e): joined tests same context
nobregao May 30, 2024
62d950e
test(test e2e): create test file for Home, Register, Content Publish …
nobregao Jun 1, 2024
15ce405
test(test e2e): increment test for validate email e log in
nobregao Jun 1, 2024
d25ed7d
feat(test e2e): update `README`
nobregao Jun 4, 2024
f6466ed
Merge branch 'main' into tests-e2e-playwright-with-report
nobregao Jun 5, 2024
15f818a
feat(test e2e): improve HomePage tests
nobregao Jun 15, 2024
02a5982
refactor(test e2e): change `BeforeEach` and removed `describes`
nobregao Jun 15, 2024
830fee8
refactor(test e2e): improve `LoginPage`
nobregao Jun 15, 2024
bed31b5
test(test e2e): change `vitest.config`, remove `include` and added `e…
nobregao Jun 15, 2024
0953fde
refactor(test e2e): improve `RegisterPage`
nobregao Jun 15, 2024
ad90251
chore(test e2e): update version `playwright` to `1.44.1`
nobregao Jun 15, 2024
40ebc59
chore(test e2e): update playwright version `1.44.1`
nobregao Jun 24, 2024
b698e9a
feat(test e2e): updated script to executing tests
nobregao Jun 24, 2024
c859f38
ci(test e2e): reorganized tests jobs
nobregao Jun 24, 2024
04885b3
chore(test e2e): remove .env.test
nobregao Aug 12, 2024
da6a586
chore(test e2e): remove `data-test-id` and unused functions
nobregao Aug 13, 2024
891511a
refactor(test e2e): remove page object and test files
nobregao Aug 13, 2024
4074010
refactor(test e2e): remove attribute `data-test-id`
nobregao Aug 13, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.test
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
NODE_ENV=test
nobregao marked this conversation as resolved.
Show resolved Hide resolved
43 changes: 41 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ concurrency:
cancel-in-progress: true

jobs:
tests:
name: Tests
unit-tests:
name: Unit Tests
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Estes não são apenas testes de unidade, são de integração também. Não sei como poderíamos nomear este grupo que é "todos os testes com exceção dos e2e".

Faz sentido colocar os testes e2e no mesmo job?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Como precisamos que testes sejam executados em todo e qualquer PR aberto, acredito que faz sentido colocar em um job só. Com essa ideia podemos dividir em etapas de execução, algo pensei abaixo:

  tests:
    name: Tests
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2

      - name: Start containers
        run: npm run services:up

      - uses: actions/cache@v2
        with:
          path: ${{ github.workspace }}/.next/cache
          key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**.[jt]s', '**.[jt]sx') }}
          restore-keys: |
            ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-

      - uses: actions/setup-node@v2
        with:
          node-version: '18'
          cache: 'npm'

      - name: Install all dependencies
        run: npm ci
      - run: npx playwright install --with-deps

      - name: Run unit and integrations tests
        run: npm run dev & npx vitest run

      - name: Run e2e tests
        run: npm run dev & npx playwright test

      - uses: actions/upload-artifact@v4
        if: ${{ !cancelled() }}
        with:
          name: playwright-report
          path: playwright-report/
          retention-days: 30
          
      - name: Stop containers
        if: always()
        run: npm run services:down

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eu não tenho certeza se faz sentido juntar no mesmo teste pelo tempo que demoraria para executar. Pensei nisso pelo tempo de demora do setup, mas na verdade demora menos de 40 segundos. Pode deixar separado como está, a não ser que alguém traga uma informação nova que pareça fazer sentido deixar todos juntos.

Precisa apenas mudar o nome unit tests mesmo.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Talvez os scripts test e test:watch possam continuar realizando todos os testes, incluindo agora os com Playwright, mas também deverão existir scripts separados para cada caso.

A separação não precisa ser necessariamente em unit, integration e e2e. Acredito que faça sentido separar por ferramentas de teste, e se dependem ou não de subir o servidor Next.js, banco de dados, etc.

Só um exemplo sem pensar muito:

  • test - realiza todos os testes (npm run test:unit && npm run test:services && npm run test:browsers).
  • test:unit - testes de unidade (filtro /unit).
  • test:services - testes que dependam de subir todos os serviços (a maioria dos testes atuais, mas adiciona os filtros /integration e /e2e).
  • test:browsers - testes que simulam a interação pelo browser (nova possibilidade com o Playwright, e o filtro está em playwright.config.js).

Com scripts separados, temos liberdade para decidir entre executar tudo no mesmo job ou em jobs separados, de acordo com o custo benefício. Rodando separadamente, ganhamos velocidade no CI, mas isso implica em maior uso da cota do GitHub Actions, então é algo que tem que ser fácil de mudar conforme a necessidade.

E já que toquei no assunto da cota, esse é um dos motivos para cuidarmos em só colocar nos testes e2e o que for realmente necessário, pois é tempo valioso dos desenvolvedores aguardando a execução dos testes, mas também pode implicar em custos no GitHub.

runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
Expand Down Expand Up @@ -54,3 +54,42 @@ jobs:
with:
fetch-depth: 0
- uses: wagoid/commitlint-github-action@v4

e2e-tests:
name: E2E Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

- name: Start containers
run: npm run services:up

- uses: actions/cache@v2
with:
path: ${{ github.workspace }}/.next/cache
key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**.[jt]s', '**.[jt]sx') }}
restore-keys: |
${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-

- uses: actions/setup-node@v2
with:
node-version: '18'
cache: 'npm'
- run: npm ci

- name: Install Playwright Dependencies
run: npx playwright install --with-deps

- name: Run e2e tests
run: npm run dev & npx playwright test

- uses: actions/upload-artifact@v4
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Por que fazer esse upload?

if: ${{ !cancelled() }}
with:
name: playwright-report
path: playwright-report/
retention-days: 30

- name: Stop containers
if: always()
run: npm run services:down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,7 @@ terraform.rc

yarn.*
.tool-versions

# Playwright test results
test-results/
playwright-report/
2 changes: 2 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ node_modules
pages/pocs
.husky
public/museu
test-results/
playwright-report/
46 changes: 43 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,15 @@ Por padrão, ao rodar o comando `npm run dev` será injetado dois usuários ativ

## Rodar os testes

Há várias formas de rodar os testes dependendo do que você deseja fazer, mas o primeiro passo antes de fazer qualquer alteração no projeto é rodar os testes de forma geral para se certificar que tudo está passando como esperado. O comando abaixo irá rodar todos os serviços necessários, rodar os testes e em seguida derrubar todos os serviços.
### Testes unitários
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Como dito acima, estes não são apenas testes de unidade, são de integração também. Acredito que não precise criar esse tópico, mas o tópico para testes e2e pode continuar.

Copy link
Author

@nobregao nobregao Jun 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

entendi. sendo assim, faz sentido o subtítulo dessa seção ser algo como abaixo?

Testes unitários e Testes de integração

se sim, irei remover também a menção única a testes unitários dessa seção e deixar mais abrangente.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acho que fica melhor 👍

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Se os scripts atuais test, test:watch e test:watch:services forem executar também os testes com Playwright, então nem precisará de um tópico separado, sendo necessário apenas algum ajuste para citar isso.

Se acharem melhor manter um tópico próprio, "Testes de Integração" pode ser um sub-tópico de "Rodar os testes". Nesse caso, falta arrumar algo na documentação, ou nos scripts, para realmente conseguir executar os testes apenas seguindo o documentado aqui. Falta a instalação das dependências do Playwright, mas deve ser melhor colocar isso no script do que na documentação.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Falta a instalação das dependências do Playwright, mas deve ser melhor colocar isso no script do que na documentação.

Eu tenho usado o Fedora para programar o TabNews, e o Fedora não é suportado pelo Playwright. Apesar disso, consegui rodar os testes headless usando Docker. Acham que vale a menção disso na documentação? Usei esta referência com uma pequena adaptação para compartilhar o repositório do projeto entre o host e o container:

docker run -it --rm \
  -v /home/rafael/Documents/Repositorios/tabnews.com.br:/tabnews.com.br --net=host \
  --ipc=host mcr.microsoft.com/playwright:v1.44.1-jammy /bin/bash 

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

o Fedora não é suportado pelo Playwright.

Interessante, então podemos deixar um docker-compose.yml pronto pra esses casos. Acho mais simples de documentar que é possível usar outro script em sistemas não compatíveis com o Playwright. Por exemplo:

"script:alternativo": "docker compose -f infra/docker-compose.test.yml up"
services:
  playwright:
    container_name: playwright
    image: mcr.microsoft.com/playwright:v1.44.1-jammy
    volumes:
      - ..:/playwright
    network_mode: "host"
    ipc: "host"
    working_dir: /playwright
    command: >
      /bin/bash -c '
      npx playwright install --with-deps
      && npm run test:e2e
      '

Outra coisa que falta na documentação, ou no script test:e2e, é que é preciso subir os serviços antes de rodar o teste e2e. Melhor adicionar ao script.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Olha que interessante!

No Codespaces o Playwright parece funcionar muito mais estável dentro do contêiner docker do que rodando o teste direto pelo terminal. No docker não vi falhar nenhuma vez. Quando executando direto no terminal, muitas vezes acaba passando dos 30s de timeout.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nobregao você consegue criar o exemplo que o @aprendendofelipe sugeriu e executar os testes?


Há várias formas de rodar os testes dependendo do que você deseja fazer, mas o primeiro passo antes de fazer qualquer alteração no projeto é rodar os testes unitários de forma geral para se certificar que tudo está passando como esperado. O comando abaixo irá rodar todos os serviços necessários, rodar os testes unitários e em seguida derrubar todos os serviços.

```bash
npm test
```

Caso queira manter os serviços e testes rodando enquanto desenvolve (e rodando novamente a cada alteração salva), use o modo `watch` com o comando abaixo:
Caso queira manter os serviços e testes unitários rodando enquanto desenvolve (e rodando novamente a cada alteração salva), use o modo `watch` com o comando abaixo:

```bash
npm run test:watch:services
Expand All @@ -104,7 +106,7 @@ npm run dev
npm run test:watch
```

Caso não queira executar (ou dar `watch`) em todos os testes e queira isolar arquivos específicos de teste, você pode filtrar pelo caminho. Não é necessário digitar o caminho inteiro para o arquivo e você também pode fornecer mais de um caminho, veja alguns exemplos abaixo:
Caso não queira executar (ou dar `watch`) em todos os testes unitários e queira isolar arquivos específicos de teste, você pode filtrar pelo caminho. Não é necessário digitar o caminho inteiro para o arquivo e você também pode fornecer mais de um caminho, veja alguns exemplos abaixo:

```bash
# Rodar todos os testes de "users" e "status" da api "v1"
Expand All @@ -125,6 +127,44 @@ Observações:
- A forma como é tratado o caminho dos arquivos pode mudar dependendo do seu sistema operacional.
- A forma como o seu terminal interpreta caracteres especiais como `/` ou `[` pode mudar.

### Testes E2E

Além dos testes unitários o projeto também inclui testes de ponta a ponta (E2E) que simulam o comportamento dos usuários. Esses testes são executados usando o Playwright.

Para executar os testes em um navegador em segundo plano, em que você não verá a interface do usuário, execute o comando:

```bash
npm run test:e2e
```

Uma alternativa para execução desses testes, que te permite visualizar exatamente o que está acontecendo na interface do usuário do navegador, rode o seguinte comando:

```bash
npm run test:e2e:headed
```

Agora, se você preferir executar os testes visualizando seus resultados numa timeline em que você consegue acompanhar na interface o momento da execução do script, rode:

```bash
npm run test:e2e:ui
```

Com esse último comando é possível escolher qual teste executar diretamente de uma UI amigável, mas se quiser fazer isso via terminal...

```bash
# Rodar teste por arquivo
npx playwright test login.spec.js

# Rodar teste de um arquivo específico (procure pelo título do teste)
npx playwright test -g "should be able to login"
```

Depois da execução é possível consultar um relatório acessando com o comando abaixo:

```bash
npx playwright show-report
```

## Formas de contribuir

Você pode contribuir com o projeto de várias formas diferentes:
Expand Down
106 changes: 100 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"@commitlint/cli": "18.6.1",
"@commitlint/config-conventional": "18.6.2",
"@faker-js/faker": "8.4.1",
"@playwright/test": "1.43.1",
nobregao marked this conversation as resolved.
Show resolved Hide resolved
"@testing-library/react": "15.0.0",
"@vitejs/plugin-react": "4.2.1",
"autoprefixer": "10.4.17",
Expand Down Expand Up @@ -95,6 +96,9 @@
"test": "npm run concurrently -- --hide next -- run",
"test:watch": "vitest watch",
"test:watch:services": "npm run concurrently -- -- watch",
"test:e2e": "playwright test",
"test:e2e:ui": "playwright test --ui",
"test:e2e:headed": "playwright test --headed",
"lint": "npm run lint:next && npm run lint:prettier",
"lint:next": "next lint --max-warnings=0 --dir .",
"lint:prettier": "prettier --check .",
Expand Down
6 changes: 5 additions & 1 deletion pages/cadastro/index.public.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,11 @@ function SignUpForm() {
/>

<FormControl>
<Checkbox checked={isTermsAccepted} onChange={() => setIsTermsAccepted(!isTermsAccepted)} />
<Checkbox
checked={isTermsAccepted}
onChange={() => setIsTermsAccepted(!isTermsAccepted)}
data-test-id="terms-accepted"
/>
<FormControl.Label>
Li e estou de acordo com os
<Link href="/termos-de-uso"> Termos de Uso.</Link>
Expand Down
19 changes: 14 additions & 5 deletions pages/interface/components/Header/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,11 @@ export default function HeaderComponent() {
<SearchBoxOverlay />
<Box as="nav" sx={{ display: 'flex', flex: 1, margin: 0, padding: 0 }}>
<PrimerHeader.Item sx={{ mr: 0 }}>
<HeaderLink href="/" aria-label="Página inicial Relevantes" aria-current={asPath === '/' ? 'page' : false}>
<HeaderLink
href="/"
aria-label="Página inicial Relevantes"
aria-current={asPath === '/' ? 'page' : false}
data-test-id="relevants">
<CgTab size={32} />

<Box sx={{ ml: 2, display: ['none', 'block'] }}>TabNews</Box>
Expand All @@ -67,7 +71,8 @@ export default function HeaderComponent() {
<HeaderLink
href="/recentes/pagina/1"
aria-current={asPath === '/recentes/pagina/1' ? 'page' : false}
sx={asPath.startsWith('/recentes') ? activeLinkStyle : { ml: 3 }}>
sx={asPath.startsWith('/recentes') ? activeLinkStyle : { ml: 3 }}
data-test-id="recents">
Recentes
</HeaderLink>
</PrimerHeader.Item>
Expand All @@ -89,10 +94,14 @@ export default function HeaderComponent() {
{!isScreenSmall && (
<>
<PrimerHeader.Item sx={{ ml: 2 }}>
<HeaderLink href={loginUrl}>Login</HeaderLink>
<HeaderLink href={loginUrl} data-test-id="login">
Login
</HeaderLink>
</PrimerHeader.Item>
<PrimerHeader.Item sx={{ mr: 1 }}>
<HeaderLink href="/cadastro">Cadastrar</HeaderLink>
<HeaderLink href="/cadastro" data-test-id="register">
Cadastrar
</HeaderLink>
</PrimerHeader.Item>
</>
)}
Expand All @@ -110,7 +119,7 @@ export default function HeaderComponent() {
{!isScreenSmall && (
<PrimerHeader.Item sx={{ m: 2 }}>
<Tooltip aria-label="Publicar novo conteúdo" direction="s" noDelay={true} wrap={true}>
<HeaderLink href="/publicar">
<HeaderLink href="/publicar" data-test-id="publish">
<PlusIcon />
</HeaderLink>
</Tooltip>
Expand Down
6 changes: 5 additions & 1 deletion pages/login/index.public.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,11 @@ function LoginForm() {
<>
<form style={{ width: '100%' }} onSubmit={handleSubmit}>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
{globalErrorMessage && <Flash variant="danger">{globalErrorMessage}</Flash>}
{globalErrorMessage && (
<Flash variant="danger" data-test-id="global-error-message">
{globalErrorMessage}
</Flash>
)}

<Heading as="h1" sx={{ mb: 3 }}>
Login
Expand Down
Loading