eletrotupi / tcc/ monografia/chapters/tests.texe11faebd227a1ab47246f3cf6d02d42cc42a6c8c
15.1 KB | 327 lines Raw
1
\chapter{Testes}\label{cap:testes}
2

3
Este capítulo registra como o comportamento do Nexo é verificado. Como nos
4
capítulos anteriores, o compromisso é com a honestidade: não se prescreve uma
5
estratégia ideal, mas se descreve o estado da prática, o que cada tipo de teste
6
é capaz --- e incapaz --- de detectar, e as lacunas assumidas explicitamente na
7
Seção~\ref{sec:test-gaps}.
8

9
O foco recai sobre a verificação automatizada. A validação com usuários reais
10
não foi realizada neste trabalho: o envolvimento de participantes em uma
11
aplicação de saúde mental exigiria aprovação prévia de comitê de ética em
12
pesquisa, levantamento de pessoas com transtorno de forma a aplicar com elas,
13
cujo todo o trâmite não coube no cronograma do projeto. Essa ausência de
14
avaliação externa é retomada como limitação na Seção~\ref{sec:test-gaps}.
15

16
Os dados quantitativos citados ao longo do capítulo referem-se ao estado do
17
repositório em meados de outubro de 2026.
18

19
\section{Vocabulário}\label{sec:test-vocab}
20

21
Quatro termos delimitam o alcance dos testes descritos adiante: unitário,
22
integração, \textit{job} e \textit{end-to-end} (E2E). Como os nomes e as
23
fronteiras entre esses níveis variam entre autores, o Quadro~\ref{tab:test-vocab}
24
fixa o sentido adotado neste trabalho e o relaciona aos níveis usuais da
25
literatura.
26

27
\begin{table}[H]
28
\centering
29
\caption{Vocabulário de testes adotado neste trabalho}
30
\label{tab:test-vocab}
31
\small
32
\begin{tabular}{|p{2.8cm}|p{6.6cm}|p{4.2cm}|}
33
\hline
34
\textbf{Termo} &
35
\textbf{O que exercita} &
36
\textbf{Nível usual na literatura} \\
37

38
\hline
39

40
Teste unitário &
41
Uma única função ou módulo, sem HTTP e sem banco de dados. &
42
Teste de unidade. \\
43

44
\hline
45

46
Teste de integração &
47
A aplicação HTTP real (rotas, validação, autenticação, controladores
48
e serviços) sobre um banco de dados real; apenas o que sai do processo
49
é simulado &
50
Teste de integração, em nível de API. \\
51

52
\hline
53

54
Teste de \textit{job} &
55
Um processador de tarefa em segundo plano, chamado diretamente com uma carga
56
fabricada, sobre o banco real. &
57
Teste de integração de componente assíncrono \\
58

59
\hline
60

61
Teste \textit{end-to-end} (E2E) &
62
O aplicativo empacotado, em um dispositivo, ao longo de uma jornada real de
63
usuário. &
64
Teste de sistema. \\
65

66
\hline
67
\end{tabular}
68
\source{Elaborado pelo autor (2026)}
69
\end{table}
70

71
\section{Estratégia de Verificação}\label{sec:test-strategy}
72

73
O código-fonte do Nexo vive em um único repositório com dois projetos
74
independentes: a API e o aplicativo móvel. O esforço de teste entre eles é
75
deliberadamente assimétrico. A API possui uma suíte automatizada e é protegida
76
por um portão de integração contínua; o aplicativo móvel é verificado
77
majoritariamente de forma manual, com uma suíte \textit{end-to-end} fina por
78
cima. Essa assimetria não é um descuido, e se justifica por duas prioridades.
79
A primeira é a capacidade de trabalho limitada: manter uma suíte automatizada
80
completa nas duas esferas excederia o disponível, e concentra-se o esforço onde
81
o retorno é maior. A segunda é que a API concentra a validação, a autenticação,
82
as regras de negócio e a persistência --- isto é, a garantia sobre a integridade
83
dos dados registrados pelo usuário.
84

85
A Tabela~\ref{tab:test-tooling} resume as ferramentas envolvidas e o ponto em que
86
cada uma atua.
87

88
\begin{table}[H]
89
\centering
90
\caption{Ferramentas de verificação}
91
\label{tab:test-tooling}
92
\small
93
\begin{tabular}{|p{4.4cm}|p{4.0cm}|p{5.0cm}|}
94
\hline
95
\textbf{Finalidade} &
96
\textbf{Ferramenta} &
97
\textbf{Onde atua} \\
98

99
\hline
100

101
Execução de testes e asserções da API &
102
Vitest &
103
API \\
104

105
\hline
106

107
Requisições HTTP nos testes &
108
Supertest &
109
Dentro dos arquivos do Vitest \\
110

111
\hline
112

113
Cobertura de código da API &
114
Vitest (\textit{coverage}) &
115
API, sem limiar mínimo \\
116

117
\hline
118

119
Banco de dados de teste &
120
PostgreSQL &
121
\textit{Container} local durante desenvolvimento; serviço efêmero no CI \\
122

123
\hline
124

125
Testes \textit{end-to-end} móveis &
126
Maestro &
127
Dispositivo Android físico, via \textit{adb} \\
128

129
\hline
130

131
\textit{Lint} do aplicativo &
132
ESLint (\texttt{expo lint}) &
133
Manual, fora do CI \\
134

135
\hline
136

137
Integração contínua &
138
GitHub Actions &
139
API \\
140

141
\hline
142
\end{tabular}
143
\source{Elaborado pelo autor (2026)}
144
\end{table}
145

146
\section{Suíte de Testes da API}\label{sec:test-api}
147

148
A suíte automatizada concentra-se na API e cobre três frentes: os testes
149
unitários, os testes de integração das rotas HTTP e os testes dos processadores
150
de tarefas em segundo plano. No momento da redação, o diretório
151
\texttt{api/tests} reunia 48 arquivos --- 17 unitários, 26 de rotas e cinco de
152
\textit{jobs}. A execução e as asserções ficam a cargo do Vitest; as requisições
153
HTTP são feitas pelo Supertest, que exercita a aplicação Express diretamente,
154
sem abrir uma porta de rede, porém através de sua pilha HTTP real.
155

156
\subsection{Organização e ferramentas}\label{sec:test-api-org}
157

158
A configuração do Vitest (\texttt{api/vitest.config.ts}) divide a suíte em dois
159
``projetos''. O projeto \texttt{unit} seleciona os arquivos com o sufixo
160
\texttt{.unit.test.ts} e não carrega configuração global alguma, de modo que
161
esses testes dependem apenas das funções que exercitam. O projeto \texttt{db}
162
seleciona os demais arquivos --- integração e \textit{job} ---, aplica um arquivo
163
de configuração global, fixa um limite de tempo por teste e faz com que esses
164
testes trunquem e repovoem o banco.
165

166
A cobertura de código é apenas mensurada, não imposta: o relatório
167
(\texttt{npm run test:coverage}) não possui limiar mínimo nem bloqueia a
168
integração contínua. A verificação estática de tipos (\texttt{npm run typecheck})
169
também roda em caráter consultivo no CI --- uma falha é registrada, mas não
170
interrompe o \textit{deploy}.
171

172
\subsection{Execução e banco de dados de teste}\label{sec:test-api-db}
173

174
Os testes que dependem do banco rodam contra uma instância real do PostgreSQL
175
--- e não contra um substituto em memória ---, em uma base dedicada de nome
176
sufixado com \texttt{\_test}, criada por um pequeno script e materializada com
177
\texttt{prisma db push}. O isolamento entre os casos é obtido por truncamento:
178
antes de cada teste, uma rotina executa \texttt{TRUNCATE users CASCADE},
179
removendo a tabela de usuários e, por cascata, todas as dependentes. Não há
180
\textit{rollback} transacional nem banco efêmero por execução.
181

182
O carregamento de dados é feito por funções auxiliares escritas à mão, e não por
183
uma biblioteca de fábricas: um módulo compartilhado
184
(\texttt{api/tests/test-helper.ts}) oferece as primitivas centrais --- cliente
185
Prisma, limpeza da base, criação de usuário e geração de token ---, e cada
186
arquivo define os \textit{seeders} de que necessita.
187

188
A regra para o uso de dublês na API é: simula-se apenas o que deixa o processo;
189
a aplicação e o banco permanecem reais. A camada de filas (BullMQ) é substituída
190
globalmente por um substituto que registra os \textit{jobs} enfileirados,
191
permitindo afirmar tanto a resposta HTTP quanto o trabalho em segundo plano
192
agendado. O envio de arquivos e o cliente de armazenamento são substituídos por
193
implementações controladas, e o disparo de e-mail e de notificações
194
\textit{push} é simulado pontualmente, nos arquivos que os exercitam.
195

196
Duas fronteiras permanecem deliberadamente reais: o acesso ao banco, via
197
Prisma, nunca é simulado; tampouco a autenticação. Os testes geram tokens JWT
198
válidos, assinados com o segredo de teste, e os enviam no cabeçalho de
199
autorização, de modo que o \textit{middleware} de autenticação real seja
200
executado. Essa escolha reduz o risco de um teste passar porém se comportar de
201
maneira distinta em produção.
202

203
\subsection{Tipos de testes}\label{sec:test-api-tipos}
204

205
A suíte da API divide-se em três grupos, retomando o vocabulário do
206
Quadro~\ref{tab:test-vocab}: unitários, integração e tarefas assíncronas. Cada
207
grupo é descrito a seguir com o que exercita, o que detecta e o que escapa ao
208
seu alcance.
209

210
\subsubsection{Testes unitários}
211

212
Os testes unitários exercitam uma única função ou módulo, sem HTTP e sem banco
213
de dados. Concentram-se na lógica pura do sistema, em grande parte extraída
214
deliberadamente de seus envoltórios de persistência para se tornar testável: os
215
agregadores dos indicadores, os construtores dos relatórios e auxiliares
216
compartilhados, como paginação e conversão de agendamento. Também cobrem o
217
gerador de código de ativação, a validade de tokens, os serializadores e as
218
regras de validação. Por serem rápidos e determinísticos, são o instrumento
219
natural para fixar casos-limite --- fronteiras de janelas de tempo, margens de
220
classificação e aritmética de paginação --- e servem como documentação
221
executável dessas regras.
222

223
A limitação desse nível é estrutural: ele só alcança a lógica isolada em uma
224
costura testável. Sem o banco e a camada HTTP, a maior parte do comportamento
225
permanece fora de alcance, e o nível pouco contribui, isoladamente, para a
226
confiança geral na aplicação.
227

228
\subsubsection{Testes de integração}
229

230
Os testes de integração formam a maior parte da suíte. Cada um constrói a
231
aplicação real, conecta um cliente Prisma real e a exercita via Supertest,
232
afirmando tanto a resposta HTTP quanto o estado persistido. Eles percorrem o
233
caminho completo de uma requisição --- roteamento, validação, autenticação,
234
controladores, serviços e persistência --- e, por operarem sobre um PostgreSQL
235
real, não sofrem o descolamento que afeta os substitutos. Afirmar a resposta e
236
as linhas persistidas simultaneamente verifica o efeito da operação, e não
237
apenas o valor de retorno.
238

239
Em contrapartida, exigem infraestrutura em execução, são mais lentos e, por
240
compartilharem a mesma base, rodam em série. O isolamento por truncamento é
241
suficiente, porém menos rigoroso do que um \textit{rollback} transacional, pois
242
um teste que falha no meio pode deixar resíduos.
243

244
\subsubsection{Testes de tarefas assíncronas}
245

246
Os testes de \textit{jobs} importam um processador do BullMQ e o chamam
247
diretamente, com uma carga fabricada, contra o banco real. Cobrem o código que
248
executa fora do ciclo requisição--resposta --- os \textit{workers} que geram
249
exportações, enviam mensagens e recalculam indicadores ---, chegando, no caso
250
da exportação, a descompactar o anexo produzido e inspecionar seu conteúdo.
251

252
Como o processador é invocado diretamente, a maquinaria da fila em si ---
253
agendamento, repetição, tentativas e ordenação --- permanece fora do alcance. A
254
carga é fabricada à mão e, por isso, pode divergir daquela que o enfileirador
255
realmente envia, sem que nada verifique uma contra a outra.
256

257
\section{Verificação do Aplicativo Móvel}\label{sec:test-mobile}
258

259
Em linha com a assimetria descrita na Seção~\ref{sec:test-strategy}, o
260
aplicativo móvel passou a contar com testes unitários em estágio inicial, ainda
261
em andamento e sem a cobertura da suíte da API. A verificação cotidiana
262
permanece predominantemente manual, em um dispositivo físico, contra a pilha
263
local em execução --- o aplicativo roda como \textit{build} de desenvolvimento
264
do Expo, com dependências nativas do Android. Essa verificação captura o que os
265
testes automatizados raramente alcançam --- problemas visuais, de leiaute e de
266
desempenho no dispositivo ---, mas não é repetível, não protege contra
267
regressões e permanece invisível à integração contínua.
268

269
\subsection{Suíte \textit{end-to-end} (Maestro)}\label{sec:test-mobile-e2e}
270

271
Sobre a verificação manual há uma suíte \textit{end-to-end} opcional, baseada
272
no Maestro, ferramenta declarativa de automação de interface para dispositivos
273
móveis. A suíte cobre uma única jornada central --- login, registro de humor e
274
saída --- por três fluxos em YAML, marcados como \texttt{smoke} e executados
275
por um pequeno \textit{harness} (\texttt{frontend/scripts/e2e.sh}), exposto
276
como \texttt{npm run test:e2e}. Os fluxos são dirigidos por identificadores de
277
teste (\texttt{testID}) inseridos no código, e não pelo texto visível, o que os
278
torna mais robustos a mudanças de interface.
279

280
A execução depende de um dispositivo Android físico conectado por \texttt{adb},
281
de um \textit{build} de desenvolvimento, da API em funcionamento com um usuário
282
de teste semeado e do Metro servindo o aplicativo; não há caminho sem cabeça
283
nem integração ao CI, de modo que a suíte é executada manualmente e com pouca
284
frequência. Cada fluxo limpa o estado do aplicativo e recarrega o
285
\textit{bundle}, tornando a execução lenta, e a cobertura permanece fina: um
286
único caminho feliz, sem casos de erro. A suíte não está integralmente verde no
287
momento da redação: os fluxos de login e de saída passam, mas o de registro de
288
humor falha ao adicionar um componente de humor, porque a tela correspondente é
289
abandonada pelo aplicativo pouco depois de ser aberta --- causa ainda não
290
identificada.
291

292
\section{Integração Contínua}\label{sec:test-ci}
293

294
A integração contínua do Nexo \cite{Humble_Farley_2011} é executada no GitHub
295
Actions e testa somente a API, coerente com a estratégia assimétrica. O fluxo
296
de implantação (\texttt{.github/workflows/deploy.yml}) dispara apenas quando há
297
mudanças em \texttt{api}: sobe um PostgreSQL efêmero, instala as dependências,
298
prepara a base de teste, executa a verificação de tipos em caráter consultivo e
299
roda a suíte com o Vitest. A construção da imagem e a implantação em produção
300
são condicionadas ao sucesso dessa etapa, de modo que uma suíte reprovada
301
impede a publicação, conforme o Capítulo~\ref{sec:deploy-and-ci}. O aplicativo
302
móvel permanece fora da integração contínua: \textit{lint} (\texttt{expo lint})
303
e verificação de tipos (\texttt{tsc --noEmit}) são executados apenas
304
manualmente, e a suíte \textit{end-to-end} não é disparada por fluxo algum.
305

306
\section{Cobertura e Lacunas}\label{sec:test-gaps}
307

308
Em síntese, a verificação automatizada cobre a superfície HTTP e a persistência
309
da API, a sua lógica pura e os seus trabalhadores em segundo plano; a
310
verificação do aplicativo móvel restringe-se, por ora, a uma jornada manual de
311
fumaça e a testes unitários ainda em consolidação. Permanecem pouco cobertas a
312
lógica do \textit{frontend} entre o nível de unidade e o \textit{end-to-end}, a
313
maquinaria da fila em si (agendamento, repetições e ordenação) e os caminhos de
314
erro do aplicativo.
315

316
Persistem, ainda, três limitações que merecem registro. A primeira é a ausência
317
de validação com usuários reais, motivada pelo trâmite de comitê de ética em
318
pesquisa descrito na abertura deste capítulo: as especificações automatizadas
319
atestam o comportamento programado, mas não a adequação do sistema às
320
expectativas do público-alvo. A segunda é a cobertura de código medida, mas não
321
imposta, o que orienta o trabalho sem jamais reprovar uma \textit{build} ou
322
\textit{deploy}. A terceira são os riscos de descolamento já mencionados: os
323
dados de teste escritos à mão em cada arquivo e a cópia espelhada dos tipos da
324
API mantida no \textit{frontend} podem divergir da fonte de verdade sem que
325
nenhum teste acuse. Essas lacunas são assumidas de forma explícita e refletem
326
uma escolha de priorização, não uma garantia de ausência de defeitos, e que
327
podem ser corrigidas em incrementos no futuro.