Identificação
- Duração: 2 horas
- Tipo: oficina integradora
- Entrega: painel Angular testado, compilado, documentado e apresentável
- Laboratório:
../exemplos/aula-4.10/index.html
Introdução
O que é um teste automatizado?
Teste automatizado é código que executa uma situação, observa o resultado e compara esse resultado com uma expectativa.
preparar cenário → executar comportamento → verificar resultado
Se a expectativa não for atendida, o teste falha e informa onde o comportamento divergiu. Ele pode ser repetido por uma pessoa, pelo editor ou por um servidor de integração contínua.
Teste prova que não existem bugs?
Não. Um teste comprova somente o comportamento e os cenários que ele verificou. Uma suíte ajuda a detectar regressões e aumenta a confiança, mas não substitui análise, acessibilidade, segurança, validação real nem observação em produção.
Testar é o mesmo que depurar?
Não. Testar detecta que o resultado não corresponde ao esperado. Depurar é investigar por que isso aconteceu. Um teste pequeno e com nome claro facilita essa investigação.
O que é uma suíte de testes?
É um conjunto organizado de casos relacionados. Podemos agrupar testes por serviço, componente ou comportamento.
describe("TaskStore", () => {
it("counts only open tasks", () => { /* ... */ });
it("keeps a valid selection after removal", () => { /* ... */ });
});
O que é Vitest?
Vitest é o executor de testes usado por padrão nos projetos Angular CLI atuais. Ele
oferece funções como describe, it, expect e vi.fn. O Angular continua
fornecendo TestBed, fixtures e utilitários para criar o ambiente da aplicação.
Projetos antigos podem usar Karma e Jasmine. Não reescreva testes apenas pelo nome da ferramenta; planeje uma migração consciente.
O que é compilação?
Compilação é o processo de transformar o código-fonte da aplicação em arquivos que um navegador ou servidor poderá entregar.
TypeScript + templates + CSS + assets
↓ ng build
HTML + JavaScript + CSS otimizados
A compilação verifica compilação e produz artefatos. Ele não publica automaticamente, não cria banco MySQL e não garante que a API esteja disponível.
Compilação é igual a publicação?
Não. ng build cria a pasta de saída. Publicar significa enviar essa saída a um
servidor, CDN ou plataforma e configurar domínio, HTTPS, cache e fallback de rotas.
Se compilou, funciona?
Não necessariamente. Uma aplicação pode compilar e ainda possuir link quebrado, contraste ruim, API incorreta, erro de autorização ou rota que falha ao atualizar a página. Testes e auditoria complementam a compilação.
Desenvolvimento e produção são iguais?
Não. ng serve prioriza desenvolvimento, mensagens detalhadas e recarga rápida. A
configuração de produção aplica otimização, AOT, minificação, eliminação de código
inutilizado e outras transformações.
O que será entregue nesta aula?
Concluiremos o painel Angular da Knowledge AI com evidências reproduzíveis:
código → testes → compilação → auditoria → documentação → apresentação
Objetivos
Ao final da aula, o aluno deverá conseguir:
- explicar teste automatizado, suíte, caso e expectativa;
- distinguir testes unitários, de componente, integração e ponta a ponta;
- aplicar Arrange, Act e Assert;
- testar funções puras e stores com signals;
- criar componentes com
TestBedeComponentFixture; - verificar conteúdo e interação no DOM;
- substituir dependências de modo controlado;
- testar HTTP sem rede real;
- verificar interceptors isoladamente;
- interpretar cobertura sem transformá-la em objetivo vazio;
- executar
ng testlocalmente e em CI; - explicar e produzir uma compilação de produção;
- auditar budgets, source maps, segredos e rotas SPA;
- documentar, demonstrar e defender o projeto do módulo.
Pré-requisitos
- Aulas 4.1 a 4.9 concluídas;
- componentes, templates, serviços, Router, formulários, HTTP e signals;
- noções de funções e testes do Módulo 3;
- terminal e scripts npm;
- HTML semântico e acessibilidade.
Pergunta orientadora
Que evidências demonstram que o painel está pronto para ser entregue e mantido?
Roteiro sugerido
| Etapa | Duração |
|---|---|
| Estratégia e anatomia dos testes | 20 min |
| Serviços, stores e componentes | 30 min |
| HTTP, interceptors e acessibilidade | 25 min |
| Compilação, segurança e hospedagem | 25 min |
| Auditoria e apresentação | 15 min |
| Encerramento | 5 min |
1. Pirâmide de testes
poucos testes E2E
testes de integração/componente
muitos testes unitários rápidos
Testes unitários isolam regras pequenas. Testes de componente combinam classe e template. Integrações verificam fronteiras controladas. E2E percorre o sistema como usuário. A proporção depende do risco, não de uma fórmula rígida.
2. O que testar primeiro
Priorize:
- regras de negócio;
- fluxos críticos;
- validação e autorização visual;
- transformação de dados externos;
- estados de erro e vazio;
- regressões já encontradas;
- acessibilidade essencial de interações.
Não comece testando getters triviais enquanto um envio crítico não possui cobertura.
3. Arrange, Act, Assert
it("marks a task as done", () => {
// Arrange
const store = createStoreWith([{ id: 1, done: false }]);
// Act
store.toggle(1);
// Assert
expect(store.tasks()[0].done).toBe(true);
});
Separar as fases deixa intenção e falha mais claras.
4. Um teste deve contar uma história
Prefira:
should keep the selected task when it still exists
Evite:
test 1
works
O nome deve indicar condição, ação e resultado relevante.
5. Teste funções puras sem Angular
describe("filterTasks", () => {
it("returns only unfinished tasks for the open filter", () => {
const result = filterTasks(TASKS, "open");
expect(result.every((task) => !task.done)).toBe(true);
});
});
Se uma regra não depende de DI, template ou framework, um teste direto é menor e mais rápido.
6. Testando um serviço com TestBed
describe("TaskStore", () => {
beforeEach(() => {
TestBed.configureTestingModule({ providers: [TaskStore] });
});
it("derives the open count", () => {
const store = TestBed.inject(TaskStore);
expect(store.openCount()).toBe(2);
});
});
TestBed cria um ambiente isolado de injeção. Reinicialize o estado entre casos para
que a ordem de execução não altere resultados.
7. Testando signals
Leia a API pública e execute comandos reais:
const before = store.openCount();
store.toggle(1);
expect(store.openCount()).toBe(before - 1);
Evite testar detalhes internos do grafo. O contrato relevante é o valor observado.
8. Mock, stub, fake e spy
| Dublê | Finalidade |
|---|---|
| stub | devolve respostas controladas |
| fake | implementação simplificada funcional |
| spy | registra chamadas e argumentos |
| mock | termo amplo; muitas ferramentas combinam stub e spy |
Use o menor dublê necessário. Dublês demais fazem o teste conhecer a implementação em vez do comportamento.
9. Substituindo uma dependência
const apiStub = {
list: vi.fn().mockReturnValue(of(TASKS)),
};
TestBed.configureTestingModule({
providers: [
TaskStore,
{ provide: TaskApi, useValue: apiStub },
],
});
O teste controla a fronteira sem chamar servidor real.
10. O que é ComponentFixture?
Fixture conecta instância, template renderizado e ciclo de detecção de mudanças.
const fixture = TestBed.createComponent(TaskCard);
fixture.componentRef.setInput("task", TASK);
await fixture.whenStable();
Use fixture.nativeElement para observar o DOM que o usuário receberia.
11. Teste de componente standalone
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [TaskCard],
}).compileComponents();
});
Componentes standalone entram em imports, não em declarations.
12. Verificando o DOM
it("renders the task title", async () => {
const fixture = TestBed.createComponent(TaskCard);
fixture.componentRef.setInput("task", TASK);
await fixture.whenStable();
const title = fixture.nativeElement.querySelector("h3");
expect(title.textContent).toContain(TASK.title);
});
Teste resultado visível. Evite acoplar a seletores decorativos que mudam com o CSS.
13. Interação do usuário
it("emits the task id when the button is clicked", async () => {
const fixture = TestBed.createComponent(TaskCard);
fixture.componentRef.setInput("task", TASK);
const emitted = vi.fn();
fixture.componentInstance.completed.subscribe(emitted);
await fixture.whenStable();
fixture.nativeElement.querySelector("button").click();
expect(emitted).toHaveBeenCalledWith(TASK.id);
});
O teste percorre template, evento DOM e output.
14. Não teste apenas “deve criar”
expect(fixture.componentInstance).toBeTruthy();
Esse smoke test encontra falhas básicas de criação, mas não comprova comportamento. Adicione casos que representem decisões reais.
15. Estado assíncrono
Teste loading, success, empty e error separadamente. Controle o tempo com ferramentas
do runner ou Observables determinísticos; não dependa de setTimeout real e rede.
16. Testando HTTP sem rede
TestBed.configureTestingModule({
providers: [
TaskApi,
provideHttpClientTesting(),
],
});
const api = TestBed.inject(TaskApi);
const http = TestBed.inject(HttpTestingController);
const result = firstValueFrom(api.list());
const request = http.expectOne("/api/tasks");
expect(request.request.method).toBe("GET");
request.flush(TASKS);
expect(await result).toEqual(TASKS);
O backend de teste captura a requisição e devolve uma resposta controlada.
17. Verifique requisições pendentes
afterEach(() => {
TestBed.inject(HttpTestingController).verify();
});
Isso detecta chamadas inesperadas ou esquecidas.
18. Testando interceptors
Quando o teste configurar recursos do cliente, registre primeiro provideHttpClient
e depois provideHttpClientTesting:
providers: [
provideHttpClient(withInterceptors([correlationInterceptor])),
provideHttpClientTesting(),
]
Teste um interceptor por vez quando possível.
19. Erro HTTP controlado
request.flush(
{ code: "INTERNAL_ERROR" },
{ status: 500, statusText: "Internal Server Error" },
);
await expect(result).rejects.toMatchObject({ status: 500 });
Nenhum servidor real precisa falhar para testar a interface de erro.
20. Testando acessibilidade essencial
Automatize verificações simples e mantenha revisão humana:
- botão nativo com nome acessível;
- label associado ao campo;
- erro ligado por
aria-describedby; role="status"ourole="alert"correto;- foco no resumo quando planejado;
- navegação completa por teclado;
- contraste e zoom em auditoria visual.
Automação não consegue avaliar toda a experiência de tecnologia assistiva.
21. Testes frágeis
Sinais comuns:
- dependem da ordem;
- usam tempos reais arbitrários;
- verificam métodos privados;
- quebram ao renomear uma classe CSS;
- reproduzem a implementação dentro da expectativa;
- compartilham estado mutável;
- usam rede ou data atual sem controle.
22. Executando os testes
ng test
No desenvolvimento, o modo observação repete os testes após alterações. Para uma execução única explícita:
ng test --no-watch --no-progress
Em CI, o ambiente normalmente ativa o comportamento não interativo.
23. Cobertura de código
ng test --coverage
Cobertura informa quais linhas, funções e ramos foram executados. Cem por cento não garante boas expectativas; baixa cobertura em fluxo crítico revela risco, mas a meta deve apoiar qualidade, não gerar testes vazios.
24. O que é CI?
Integração contínua é um processo automatizado que valida mudanças em cada push ou pull request.
instalar → formatar/verificar → testar → compilar → publicar artefato
O fluxo deve falhar quando uma etapa obrigatória falhar.
25. Compilação de produção
ng build
Por padrão, o CLI atual utiliza a configuração de produção, salvo customização do
espaço de trabalho. Verifique o resultado no diretório configurado em outputPath.
26. O que a produção otimiza?
- compilação AOT de templates;
- bundling;
- minificação;
- tree shaking e eliminação de código morto;
- CSS e assets;
- remoção de recursos de desenvolvimento;
- hashing e cache conforme configuração.
O artefato deve ser testado no modo em que será hospedado.
27. Budget de bundle
Budgets geram aviso ou erro quando o tamanho ultrapassa limites:
{
"type": "initial",
"maximumWarning": "500kB",
"maximumError": "1MB"
}
Escolha limites baseados no produto e acompanhe regressões. Não aumente o teto sem investigar o crescimento.
28. Source maps
Source maps ajudam a relacionar código otimizado ao fonte. Maps ocultos ainda podem vazar se o servidor os publicar. Defina uma política de geração, armazenamento e acesso para observabilidade.
29. Variáveis de ambiente não são cofres
Qualquer valor incorporado ao bundle do front-end pode ser encontrado no navegador. URL pública e feature flag podem estar na configuração; senha MySQL, chave privada e segredo de API não podem.
Angular → apenas configuração pública
NestJS → segredos do servidor
MySQL → credenciais acessadas pelo back-end
30. Rotas na hospedagem
Uma SPA com Router precisa que o servidor devolva index.html para deep links:
/tasks/42 → servidor entrega index.html → Angular resolve /tasks/42
Sem fallback, atualizar uma rota válida pode produzir 404 do servidor.
31. base href
Se a aplicação for publicada em subdiretório, confirme o caminho base e os assets. Uma configuração incorreta pode carregar o HTML e falhar em scripts, estilos e rotas.
32. Cache e hashing
Arquivos com hash permitem cache longo porque um conteúdo novo recebe outro nome. O HTML principal costuma exigir política mais curta para apontar aos bundles atuais.
33. Lista de verificação de segurança do bundle
- nenhum token real;
- nenhuma senha ou conexão MySQL;
- nenhum
.envsecreto copiado; - nenhum source map público por acidente;
- nenhuma mensagem com stack trace ao usuário;
- URLs de API corretas;
- dependências e licenças revisadas;
- CSP e headers decididos na hospedagem.
34. README reproduzível
O README final deve explicar:
- objetivo e público;
- funcionalidades;
- stack e arquitetura;
- requisitos;
- instalação;
- execução local;
- testes;
- compilação;
- configuração pública;
- decisões e limitações;
- acessibilidade;
- demonstração e licença.
35. Projeto final do módulo
O painel da Knowledge AI deve conter:
- shell e navegação por rotas;
- dashboard;
- lista, filtro e detalhes de tarefas;
- cadastro e edição validados;
- componentes reutilizáveis;
- serviço/store com signals;
- integração HTTP tipada;
- loading, empty, success e error;
- interceptors e mensagens acessíveis;
- testes essenciais;
- compilação de produção;
- documentação reproduzível.
36. Arquitetura final
Angular
├── páginas e layouts
├── componentes de apresentação
├── formulários e estado visual
├── stores e serviços
├── Router
├── HttpClient + interceptors
└── testes
│ HTTP
▼
NestJS → Prisma → MySQL
O módulo entrega o front-end e contratos simulados. O back-end real será construído nos próximos módulos.
37. Roteiro de apresentação
Em cinco minutos:
- problema e usuário;
- fluxo principal;
- arquitetura e decisões;
- demonstração de sucesso;
- demonstração de erro e acessibilidade;
- testes e compilação;
- limitações e próximo passo.
Não percorra arquivos sem contexto; conte a história do produto e mostre evidências.
38. Laboratório guiado
Abra a auditoria final do painel.
Etapa 1 — Selecione o perfil da entrega
Compare uma entrega incompleta com o painel preparado.
Etapa 2 — Execute a suíte simulada
Observe testes de regra, store, componente, HTTP, interceptor e acessibilidade.
Etapa 3 — Execute a compilação simulado
Acompanhe typecheck, AOT, otimização, budget e geração do artefato.
Etapa 4 — Audite documentação e segurança
Marque critérios e veja como eles alteram a prontidão.
Etapa 5 — Corrija falhas
Use “Preparar entrega completa” e compare o novo resultado.
Etapa 6 — Gere o parecer
Leia bloqueios, evidências e recomendação de apresentação.
39. Sobre o laboratório estático
O laboratório ensina o fluxo de qualidade sem depender de um espaço de trabalho Angular
instalado dentro do curso. Os testes e a compilação são simulações determinísticas; a
pasta src/app contém exemplos Angular/Vitest equivalentes.
40. Erros comuns
Testar só caminho feliz
Falhas de rede, validação, vazio e permissão ficam sem evidência.
Confundir cobertura com qualidade
Linhas executadas podem não possuir expectativas úteis.
Mockar tudo
O teste deixa de verificar integrações importantes.
Usar produção real no teste
Resultados ficam lentos, perigosos e instáveis.
Publicar ng serve
Servidor de desenvolvimento não é a entrega otimizada de produção.
Colocar segredo em environment
O valor entra no bundle e fica público.
Esquecer fallback SPA
Rotas funcionam por clique, mas falham ao atualizar.
Não registrar comandos
Outra pessoa não consegue reproduzir teste e compilação.
41. Desafio individual
Produza um pacote de evidências com:
- pelo menos oito testes relevantes;
- teste de sucesso e erro HTTP;
- teste isolado de interceptor;
- teste de interação e semântica acessível;
- relatório de cobertura interpretado;
- compilação dentro do budget;
- auditoria de segredos;
- teste de deep link;
- README reproduzível;
- vídeo ou apresentação de cinco minutos.
42. Lista de verificação de conclusão
- Distingo teste, compilação e publicação.
- Escrevo testes com Arrange, Act e Assert.
- Testo comportamento, não detalhes privados.
- Sei usar
TestBede fixture. - Testo HTTP sem rede real.
- Verifico estados de erro e acessibilidade.
- Entendo cobertura e seus limites.
- Gero uma compilação para produção.
- Audito segredos, budget e source maps.
- Documento e apresento o projeto.
43. Rubrica do projeto
| Critério | Pontos |
|---|---|
| Componentes, templates e composição | 15 |
| Rotas e formulários | 15 |
| Serviços, signals e estado | 15 |
| HTTP, interceptors e erros | 15 |
| Acessibilidade | 10 |
| Testes automatizados | 15 |
| Compilação, segurança e desempenho | 10 |
| Documentação e apresentação | 5 |
| Total | 100 |
Para concluir, obtenha pelo menos 70 pontos e não possua bloqueio crítico de segurança, compilação ou acessibilidade.
44. Resumo
- testes automatizados produzem evidências repetíveis;
- Vitest é o runner padrão dos projetos Angular CLI atuais;
TestBedcria ambientes isolados para DI e componentes;- o backend HTTP de teste evita rede real;
- cobertura mede execução, não qualidade da expectativa;
- compilação transforma fonte em artefato otimizado;
- publicação exige servidor, rotas, cache e segurança;
- o projeto final precisa ser reproduzível e defendido tecnicamente.
45. Fontes oficiais
- Angular: visão geral de testes
- Angular: testes de componentes
- Angular: testes de serviços
- Angular: testes HTTP
- Angular CLI:
ng build - Angular: implantação e fallback de rotas
- Angular: configuração do espaço de trabalho
Próximo módulo
No Módulo 5, criaremos o back-end com Node.js e NestJS: ambiente de execução, módulos, controllers, providers, DTOs, validação e os primeiros endpoints reais da Knowledge AI.