Controle de Qualidade
Esta seção tem por objetivo detalhar as convenções de commit, os padrões de codificação, as diretrizes de code review e a metodologia empregada nos testes unitários do projeto.
📚 Padrões de commit
O projeto adota o padrão Conventional Commits, que define uma convenção para a escrita de mensagens de commit, com o objetivo de padronizar o histórico de alterações, tornando-o mais legível, organizado e automatizável.
Tipos de commit do padrão especificado
-
feat: Uma nova funcionalidade (
feature
) -
fix: Uma correção de bug (
bug fix
) - chore: Tarefas de manutenção que não alteram o código-fonte visível ao usuário (ex: ajustes de build, configuração de CI/CD, gerenciamento de dependências)
-
docs: Alterações na documentação (ex:
README.md
,CONTRIBUTING.md
) - style: Alterações que não afetam o significado do código (espaços em branco, formatação, ponto e vírgula, etc.). Geralmente relacionado ao Prettier/ESLint
- refactor: Uma alteração no código que não corrige um bug nem adiciona uma funcionalidade (ex: renomear uma variável, melhorar a performance de um algoritmo)
- test: Adicionando ou corrigindo testes
-
ci: Alterações em arquivos de configuração de Integração Contínua (ex:
.gitlab-ci.yml
)
Exemplo de commit válido:
feat/date-modal
Nomeação de branches
Cada nova funcionalidade, correção ou tarefa deve ser desenvolvida em uma branch própria, criada a partir da versão mais atual da branch developer. Para manter a organização e o rastreamento claros, o nome da branch deve possuir as seguintes informações:
-
tipo:
indica a categoria da- feat: novas funcionalidades
- fix: correção de bugs
- chore: tarefas de manutenção ou configurações que não impactam diretamente o código-fonte
- docs: alteração na documentação
-
US<id>
: identificador da User Story (ou tarefa) no sistema de gerenciamento -
nome-descritivo
: breve descrição em inglês do objetivo da branch, utilizando palavras minúsculas separadas por hífens
Sendo assim um o modelo de padrão a ser seguindo seria:
tipo/US<id>-nome-descritivo
Exemplos de nomeação de branch válidos:
feat/US101-auth-module
fix/US125-producer-validation-error
chore/US130-update-dockerfile
docs/US132-update-readme-contribution-guide
🔍 Revisão de código
Todo código desenvolvido deve ser submetido a code review. Para que o merge request seja aprovado, ele precisa passar por uma análise, garantindo qualidade, consistência e conformidade com as diretrizes do projeto.
📏 Padrões de código
O projeto utiliza a ferramenta ESLint (https://eslint.org/) para identificar rapidamente erros, padrões inconsistentes ou más práticas no código. Seu principal objetivo é garantir a padronização do código, promovendo legibilidade, manutenibilidade e qualidade técnica em equipes de desenvolvimento.
Além disso, o projeto emprega o Prettier (https://prettier.io/) para padronizar o estilo visual do código, independentemente de quem o escreveu. O Prettier foca na formatação consistente, aumentando a legibilidade, a uniformidade e a agilidade no desenvolvimento.
A equipe adotou a convenção de usar nomes em inglês para variáveis, funções e classes, sempre em camelCase, garantindo clareza, consistência e facilidade de manutenção do código.
🧪 Testes unitários
Back-end
O projeto utiliza o Jest, um framework de testes completo para JavaScript/TypeScript amplamente adotado no ecossistema NestJS. O Jest atua como o executor e verificador dos testes. Ele oferece um ambiente integrado que combina:
-
Test Runner (Executor de Testes): : O Jest é o programa que ativamente procura por arquivos de teste em nosso projeto (os arquivos
.spec.ts
) e os executa um por um -
Assertion Library (Biblioteca de Asserção): permite escrever vO Jest nos dá a ferramenta principal da investigação: a função
expect()
. Com ela, fazemos "asserções" (afirmações) sobre o nosso código. Por exemplo:expect(soma(2, 2))toBe(4);
se traduz para: "Eu afirmo que o resultado desoma(2, 2)
deve ser4
" -
Mocking Library (Biblioteca de Simulação): Em um caso complexo, o detetive precisa isolar a cena do crime. O Jest nos permite "mocar" (do inglês mock, que significa simular ou imitar) as dependências. Se o
AreasService
depende doAreasRepository
para falar com o banco de dados, podemos dizer ao Jest: "Para este teste, finja que oAreasRepository
existe e, quando o métodofindById
for chamado, retorne este objeto falso aqui". Isso isola o teste apenas para a lógica doAreasService
-
Relatórios (Reporting): Após a investigação, o Jest apresenta um relatório claro no terminal, dizendo quais afirmações (
expect
) foram confirmadas (PASS
) e quais foram refutadas (FAIL
)
Nomenclatura
A forma como nomeamos nossos arquivos de teste não é aleatória. É uma convenção, um acordo que fazemos para que o Jest encontre os testes sem precisarmos configurar nada.
Dissecando o nome do arquivo de teste areas.service.spec.ts
temos:
-
areas.service
: esta é a unidade sob teste. O nome indica claramente que este arquivo de teste é responsável por verificar o comportamento do arquivoareas.service.ts
-
.spec
: esta é a parte mais importante. Significa "Specification" (Especificação). Este arquivo não é apenas um "teste", ele é um documento executável que especifica como oareas.service.ts
deve se comportar. É o conjunto de regras e requisitos daquela unidade. Outra convenção comum é.test
, que tem o mesmo significado. Em nosso projeto, adotamos.spec
-
.ts
: indica que o arquivo é escrito em TypeScript -
.e2e
: significa End-to-End (Ponta-a-Ponta). Este sufixo especial nos diz que o escopo do teste é diferente. Ele não vai testar uma unidade isolada, mas sim um fluxo completo da aplicação, geralmente disparado por uma requisição HTTP
Estrutura de teste
Os testes em Jest seguem uma estrutura organizada em blocos e verificações:
-
describe(nome, função)
Agrupa testes relacionados em uma suíte de testes.
Analogia: é como o capítulo de um livro, com todos os testes desse bloco focados em uma funcionalidade específica. -
it(descricao, função)
outest(descricao, função)
Representa um caso de teste individual.
Analogia: é como um parágrafo dentro do capítulo, testando uma única coisa. A descrição deve explicar claramente o que está sendo testado. -
expect(valor)
Faz uma asserção, verificando se o valor obtido corresponde ao valor esperado. -
Matchers (
.toBe()
,.toEqual()
,.toThrow()
, etc.)
Métodos que completam a asserção, permitindo comparar valores ou verificar erros.
Exemplos:expect(resultado).toBe(5); // espera que seja exatamente 5 expect(objeto).toEqual({ id: 1 }); // espera que o objeto seja igual em valor expect(() => func()).toThrow(); // espera que a função lance um erro
Fluxo no projeto
-
Criação:
Quando você cria uma nova funcionalidade, por exemplo, noproducers.service.ts
, você também cria um arquivoproducers.service.spec.ts
na pasta de test. -
Isolamento (Testes Unitários):
Dentro do.spec.ts
, usamos o@nestjs/testing
para criar um "módulo de teste". Isso nos permite injetar "mocks" (versões falsas) das dependências. Não queremos testar o banco de dados aqui, apenas a lógica de negócio doProducersService
. -
Fluxo Completo (Testes E2E):
Para os testes na pasta/test
(.e2e-spec.ts
), nós não usamos mocks. Nós subimos uma instância completa e real da nossa aplicação em memória. Então, usamos a biblioteca supertest para fazer chamadas HTTP de verdade (GET /producers
,POST /producers
) e usamosexpect
para verificar a resposta HTTP (status code, corpo da resposta, etc). -
Execução:
Quando você roda o comando:npm test