Pular para o conteúdo principal

Relatórios

Vamos trabalhar com o reports e gerar os relatórios do jeito correto.

A maioria das ferramentas que fazem algum tipo de análise podem mostrar o resultado no console (terminal), mas também podem gerar um arquivo estruturado com o resultado da análise, que é o que chamamos de report.

A configuração de report do teste unitário está no arquivo vite.config.js

export default defineConfig({
plugins: [react()],
build: {
outDir: 'build'
},
test: {
environment: 'jsdom',
setupFiles: './tests/setup.js',
exclude: [
'**/node_modules/**',
'**/dist/**',
'**/e2e/**'
],
reporters: ['verbose', 'junit', 'html'], // <<<<< esta gerando dos dois modos
outputFile: {
junit: './reports/junit.xml', // <<<< para formato junit
html: './reports/html/index.html' // <<<< para formato html
}
}
})

Ou seja, o report irá sair neste arquivo ./reports/junit.xml, apesar de ser mostrado alguma coisa via console. Esse arquivo conterá informações detalhadas sobre os testes.

No nosso job de teste unitário vamos gerar o artefato para esse report do modo correto. Vamos usar always para garantir que sempre dará o report, ou falha ou não.

unit-test:
stage: test
image: node:22-slim
script:
- npm ci
- npm test
artifacts:
when: always
expire_in: "1 week"
reports:
junit: reports/junit.xml

Vamos subir o código com a modificação somente neste job.

❯ git checkout -b pipe/reports
❯ git add .gitlab-ci.yml
❯ git commit -m "add reports to unity tests"
❯ git push origin pipe/reports

alt text

alt text

alt text

O fato de usarmos a tag junit (artifacts.reports.junit) avisa para o GitLab que este é um arquivo no formato junit e automaticamente o GitLab faz um "parser" para fazer a mostragem correta na interface.

Assim podemos navegar entre o relatório de maneira simples e igual para vários relatórios.

Nada impede que publicamos o arquivo em reports e paths ao mesmo tempo para que possamos fazer o download caso necessário.

Como fazemos a mesma coisa agora para o linter? Primeiro vamos voltar o que tínhamos antes em package.json

{
"scripts": {
"lint": "eslint -f json -o gl-codequality.json .",
},
}

Ao invés de plugarmos em junit vamos plugar isso em codequality. Esse tipo de teste é do tipo codequality que iremos analisar mais adiante.

lint-test:
stage: test
image: node:22-slim
script:
- npm ci
- npm run lint # Isso irá chamar o comando origial
artifacts:
when: always
expire_in: "3 months"
reports:
codequality: gl-codequality.json # publicaremos aqui.
❯ git add .gitlab-ci.yml
❯ git add packages.json
❯ git commit -m "add reports to linter"
❯ git push origin pipe/reports

A visão já está no próprio push ou merge que gerou o code quality e não na mesma aba que estão os testes unitários.

Se declararmos uma varíavel qualquer que nunca foi utilizada irá quebrar o pipeline no linter, então podemos testar.

describe('App', () => {
it('renders the App component', () => {
render(<App />)
const textElement = screen.getByText(/Learn GitLab/i);
let myNewVar; // adicionado
expect(textElement).toBeInTheDocument();

//screen.debug(); // prints out the jsx in the App component unto the command line
})

Neste caso, o GitLab salva os artifacts de cada pipeline (como o gl-codequality.json).

Na hora de abrir um Merge Request, ele tenta comparar o report atual com o da branch base (ex: main) do último pipeline válido que ainda tem artifact.

Se o artifact expirou, não tem mais o que comparar ele assume que "não mudou nada" ou ignora a análise. Por isso é bom que guardemos os reports por um tempo maior.

E quanto ao job vulnerability-test, o que podemos fazer com o reports?

vulnerability-test:
stage: test # mesmo stage
image: node:22-slim
script:
- npm ci
- npm audit --audit-level=high --json > vulnerability-report.json
artifacts:
when: on_failure
expire_in: "1 hour"
paths:
- vulnerability-report.json

Antes de fazer isso vamos estudar um pouco de reports.

Reports​

Para ajudar, um pouco de documentação oficial do reports.

Primeiro vamos conhecer os tipos de reports que existem no momento.

  • accessibility: Análise automática para detectar problemas de usabilidade e inclusão digital em interfaces web. Teste coisas como: uso correto de alt em imagens , contraste entre texto e fundo, navegabilidade com teclado, presença de labels em inputs, estrutura semântica (headings, landmarks, etc)

  • annotations:

  • api_fuzzing: Testar APIs mandando dados aleatórios, inesperados ou maliciosos pra tentar quebrar, travar ou explorar a aplicação.

  • browser_performance: Relatório automático de desempenho de uma página web, focado na experiência do usuário (UX). Testa coisas como: tempo até o primeiro conteúdo visível (First Contentful Paint), tempo até a página ficar interativa (Time to Interactive), frames por segundo, uso de CPU/memória, carregamento de scripts/pesos de recursos. GitLab usa o Sitespeed.io, que roda testes com o Chrome em background via Puppeteer. Esse teste só faz sentido após o deploy, por exemplo no ambiente de staging ou develop.

  • coverage_report: porcentagem de linhas/funções/blocos testados no seu código. Vamos implementar.

  • codequality

  • container_scanning

  • coverage_fuzzing

  • cyclonedx: Um formato padronizado para descrever tudo que seu app usa (libs, pacotes, versões, etc), com foco em segurança e compliance.

  • dast

  • dependency_scanning

  • dotenv

  • junit

  • load_performance

  • metrics

  • requirements

  • sast

  • secret_detection

  • terraform

O GitLab entende vários tipos de reports para exibir resultados visuais bonitos nas MRs, pipelines e Security Dashboards.

Cada tipo tem seu formato JSON específico.

coverage_report​

Para implementar o teste de cobertura no projeto vamos alterar o seguinte o arquivo vite.config.js e adicionar o bloco abaixo.


environment: "jsdom",
setupFiles: "./tests/setup.js",
exclude: ["**/node_modules/**", "**/dist/**", "**/e2e/**"],
reporters: ["verbose", "junit", "html"],
coverage: { ## O bloco coverage
provider: "istanbul",
reporter: ["text", "json", "html", "cobertura"],
},
outputFile: {
junit: "./reports/junit.xml",
html: "./reports/html/index.html",
}

E em package.json vamos adicionar em scripts

  "scripts": {
"dev": "vite",
"build": "vite build",
"test": "vitest",
"e2e": "npx playwright test",
"lint": "eslint --format gitlab .",
"preview": "vite preview",
"coverage": "vitest run --coverage" //Esta linha
},

Adicione no .gitignore a pasta coverage senão irá subir a pasta de local.

echo "coverage" >> .gitignore

Para fazer o teste localmente execute.

❯ npm test -- --coverage  

# Removido parte para facilitar a leitura

Test Files 1 passed (1)
Tests 3 passed (3)
Start at 07:18:28
Duration 8.09s (transform 83ms, setup 168ms, collect 83ms, tests 27ms, environment 405ms, prepare 48ms)

% Coverage report from istanbul
--------------------------------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
--------------------------------------|---------|----------|---------|---------|-------------------
All files | 0 | 0 | 0.02 | 2.22 |
learn-gitlab-app | 0 | 0 | 100 | 0 |
playwright.config.cjs | 0 | 0 | 100 | 0 | 2-13
learn-gitlab-app/build/assets | 0 | 0 | 0 | 0 |
index-BcKvuBhg.js | 0 | 0 | 0 | 0 | 1-40
learn-gitlab-app/reports/html/assets | 0 | 0 | 0 | 0 |
index-Cv3XDLXs.js | 0 | 0 | 0 | 0 | 1-52
learn-gitlab-app/src | 50 | 100 | 100 | 50 |
App.jsx | 100 | 100 | 100 | 100 |
main.jsx | 0 | 100 | 100 | 0 | 6
--------------------------------------|---------|----------|---------|---------|-------------------

Ao executarmos esse teste, tudo estará dentro da pasta coverage e o arquivo que nos interessa é o cobertura-coverage.xml que é um formato que o GitLab entende.

Agora queremos que isso esteja no report então vamos adicionar mais um job no stage teste dentro de .gitlab-ci.yml.

coverage-test:
stage: test
image: node:22-slim
script:
- npm ci
- npm test -- --coverage
artifacts:
when: always
expire_in: "1 hour"
reports:
coverage_report:
coverage_format: cobertura
path: coverage/cobertura-coverage.xml

Durante o aprendizado vamos conferindo mais testes, não se importe agora com isso, o importante é conhecer as coisas e saber o que podemos fazer.

Code Quality Report (codequality)​

O Code Quality Report no GitLab exibe diretamente na Merge Request todos os problemas encontrados no código, como:

Por isso não conseguirmos ver o que fizemos no linter, pois não estávamos em um merge request. Faremos isso mais pra frente.

  • Código duplicado
  • Más práticas
  • Violação de estilo
  • Bugs potenciais (tipo await perdido)

Ele ajuda a automatizar revisão de código e forçar qualidade mínima no pipeline CI/CD.

O GitLab espera um arquivo JSON específico, com cada problema descrito em uma estrutura padronizada.

Não é qualquer JSON: tem que seguir o GitLab CodeQuality Schema certinho! Não vamos parar para ver esse schema, deixe que as ferramentas e quem as desenvolve farão isso. Por isso passamos --format gitlab anteriormente.

Várias ferramentas fazem isso, o que precisamos é saber como criar arquivo json no formato correto.

  • Lint / Code Quality: ESLint, Stylelint, Pylint, Flake8, GolangCI-Lint, Rubocop, PHP_CodeSniffer, SwiftLint, ktlint, TFLint, Dockerfilelint, Hadolint, ShellCheck, markdownlint

Segurança (SAST / Static Analysis): Bandit, Brakeman, Semgrep, ESLint-plugin-security, Gosec, NodeJsScan, Safety, Trivy

Análise Profunda / Code Smells: SonarQube, SonarCloud, CodeClimate, DeepSource, Codacy

IaC / Cloud / Containers: KubeLinter, Checkov, TFSec, CFN-Nag, Conftest

Licenciamento / Vulnerabilidades de Dependências: npm audit, yarn audit, Snyk, OWASP Dependency-Check

artifacts:
reports:
codequality: path/to/report.json

SAST Report (sast)​

Static Application Security Testing (vulnerabilidades de código).

Usado no Security Dashboard.

Exemplo: Trivy, GitLab SAST scanners (Node.js, Python, etc).

artifacts:
reports:
sast: path/to/sast-report.json

Dependency Scanning (dependency_scanning)​

Scaneia dependências (package.json, pom.xml...) por CVEs.

É tipo npm audit, mas compatível com GitLab Security.

artifacts:
reports:
dependency_scanning: path/to/report.json

Container Scanning (container_scanning)​

Procura vulnerabilidades em imagens Docker.

Usa scanners tipo Trivy, Grype, Clair.

Artifacts:

artifacts:
reports:
container_scanning: path/to/report.json

DAST Report (dast)​

Dynamic Application Security Testing.

Escaneia o app rodando (não o código).

Exemplo: OWASP ZAP.

artifacts:
reports:
dast: path/to/report.json

Terraform Reports (terraform)​

Mostra mudanças de infraestrutura detectadas no Terraform.

Infraestrutura como código visível nas MRs.

artifacts:
reports:
terraform: path/to/terraform-report.json

Dica​

Se observou bem todos os testes aqui foram executados em paralelo se um falhar irá quebrar o stage test. Fizemos isso para ganhar velocidade. Não existe uma ordem de execução. Cuidado com jobs que rodam em paralelo que às vezes fica mais complicado de debugar onde aconteceu o problema.