Reports
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 de arquivo estruturado com o resultado da análise, que é o que chamamos de report.
A configuração de report do teste unitário esta 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 detalhas 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
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 tinhamos antes em packages.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 esta 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 pra 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 pra 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 package.json vamos adicioanar 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 locamente 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 faça isso. Por isso passamos --format gitlab anteriormente.
Várias ferramentas 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 as vezes fica mais complicado de debugar onde aconteceu o problema.