eletrotupi / tcc/ commit / a2ea135

thesis: consolidate the tests chapter

Replaces the duplicated chapter with a single version that states the
ethics limitation up front, trims the repeated restatements, and notes
the emerging frontend unit tests
Pedro Lucas Porcellis porcellis@eletrotupi.com · 9 days ago a2ea1352da034bd3377e2a3cbfa4c53a75eba523 Browse files
Parents c732afc
Changed files
1
Additions
+168
Deletions
-211
monografia/chapters/tests.tex
1 1
\chapter{Testes}\label{cap:testes}
2 2

3 -
Delineadas as tecnologias e a arquitetura nos capítulos anteriores, este
4 -
capítulo se debruça como o comportamento do sistema é verificado: quais tipos
5 -
de teste existem, onde são aplicados, o que cada um é capaz --- e incapaz ---
6 -
de detectar, e por que o esforço de verificação foi distribuído da forma como
7 -
foi. O objetivo não é prescrever uma estratégia ideal, mas registrar com
8 -
honestidade o estado da prática no projeto e as suas lacunas, apresentadas de
9 -
forma explícita na Seção~\ref{sec:test-gaps}.
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}.
10 8

11 -
Os dados quantitativos citados ao longo do capítulo, como o número de arquivos
12 -
de teste, referem-se ao estado do repositório em meados de outubro de 2026.
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}.
13 15

14 -
\section{Fundamentos de Teste de Software}\label{sec:tests-basic}
16 +
Os dados quantitativos citados ao longo do capítulo referem-se ao estado do
17 +
repositório em meados de outubro de 2026.
15 18

16 -
Teste de software é, em sua formulação clássica, a execução de um programa com
17 -
a intenção de revelar defeitos \cite{Myers:2012}. Uma consequência é que um
18 -
conjunto de testes que passa demonstra que os casos exercitados se comportam
19 -
como esperado, mas não necessariamente que o sistema esteja livre de defeitos.
20 -
Essa limitação é relevante para a leitura deste capítulo.
19 +
\section{Vocabulário}\label{sec:test-vocab}
21 20

22 -
A literatura costuma organizar a atividade de teste em níveis, que se
23 -
distinguem pelo tamanho da parte do sistema sob verificação: o teste de unidade
24 -
exercita a menor parte testável do programa de forma isolada; o teste de
25 -
integração verifica a interação entre partes já testadas; e o teste de sistema
26 -
avalia o sistema completo em condições próximas às de uso. Os nomes e as
27 -
fronteiras entre os níveis variam entre autores; por isso,
28 -
o Quadro~\ref{tab:tests-vocab} fixa o vocabulário usado neste trabalho
29 -
e o relaciona aos termos usuais.
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.
30 26

31 27
\begin{table}[H]
32 28
\centering
33 29
\caption{Vocabulário de testes adotado neste trabalho}
34 -
\label{tab:tests-vocab}
30 +
\label{tab:test-vocab}
35 31
\small
36 32
\begin{tabular}{|p{2.8cm}|p{6.6cm}|p{4.2cm}|}
37 33
\hline
38 34
\textbf{Termo} &
39 35
\textbf{O que exercita} &
70 66
\hline
71 67
\end{tabular}
72 68
\source{Elaborado pelo autor (2026)}
73 69
\end{table}
74 70

75 -
Outro conceito necessário é o de dublê de teste (\textit{test double}): termo
76 -
genérico para qualquer objeto que substitui uma dependência real durante
77 -
o teste. A taxonomia de \citet{Meszaros:2007} distingue, entre outros,
78 -
\textit{stubs}, \textit{spies}, \textit{mocks} e \textit{fakes}. Neste
79 -
trabalho, o termo \textit{mock} é empregado no sentido amplo adotado pelas
80 -
ferramentas de teste do ecossistema JavaScript --- a substituição de um módulo
81 -
por um substituto controlado ---, e não no sentido restrito da taxonomia.
71 +
\section{Estratégia de Verificação}\label{sec:test-strategy}
82 72

83 -
E então, uma heurística recorrente para distribuir o esforço entre os níveis
84 -
é a chamada pirâmide de testes: muitos testes rápidos e isolados na base, menos
85 -
testes de integração no meio e poucos testes de interface no topo
86 -
\cite{Vocke:2012}. A distribuição observada no Nexo se afasta desse formato:
87 -
alguns testes unitários, maioria de testes de integração e um topo fino,
88 -
predominantemente manual.
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.
89 84

90 -
\section{Estratégia de Verificação}\label{sec:tests-strategies}
91 -

92 -
O código-fonte do Nexo é mantido em um único repositório que abriga dois
93 -
projetos independentes: a API e o aplicativo móvel, ambos descritos nos
94 -
capítulos anteriores.
95 -

96 -
O esforço de teste entre os dois projetos é deliberadamente assimétrico. A API
97 -
possui uma suíte automatizada e é protegida por um portão de integração
98 -
contínua; o aplicativo móvel é verificado majoritariamente de forma manual, com
99 -
uma pequena suíte \textit{end-to-end} e testes unitários por cima. Essa
100 -
assimetria decorre das prioridades do projeto, e não de um descuido, e se
101 -
justifica por, ao menos, dois motivos. O primeiro é que, por limitações de
102 -
força de trabalho, manter uma suíte automatizada completa nas duas esferas
103 -
excederia a capacidade disponível, sendo preferível concentrar o esforço onde
104 -
o retorno é maior. O segundo é que a API é o componente que concentra
105 -
a validação, a autenticação, as regras de negócio e a persistência --- isto é,
106 -
a garantia sobre a integridade dos dados registrados pelo usuário.
107 -

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

111 88
\begin{table}[H]
112 89
\centering
113 90
\caption{Ferramentas de verificação}
114 91
\label{tab:test-tooling}
166 143
\source{Elaborado pelo autor (2026)}
167 144
\end{table}
168 145

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

171 -
A suíte automatizada do Nexo concentra-se na API e cobre três frentes
172 -
distintas: os testes unitários, os testes de integração das rotas HTTP e os
173 -
testes dos processadores de tarefas em segundo plano. No momento da redação
174 -
deste capítulo, o diretório \texttt{api/tests} reunia 48 arquivos, dos quais 17
175 -
são unitários, 26 exercitam as rotas e cinco cobrem os \textit{jobs}.
176 -
A execução e as asserções ficam a cargo do Vitest, enquanto as requisições HTTP
177 -
são realizadas pelo Supertest, que permite exercitar a aplicação Express
178 -
diretamente, sem abrir uma porta de rede, porém através de sua pilha HTTP real.
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.
179 155

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

182 -
A configuração do Vitest (\texttt{api/vitest.config.ts}) permite dividir
183 -
a suíte em dois ``projetos'', cada um com condições especiais. O projeto
184 -
\texttt{unit} seleciona os arquivos nomeados com o sufixo
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
185 160
\texttt{.unit.test.ts} e não carrega configuração global alguma, de modo que
186 -
esses testes dependem apenas das funções que exercitam. Já o projeto
187 -
\texttt{db} seleciona os demais arquivos --- os testes de integração e de
188 -
\textit{job} ---, aplica um arquivo de configuração global e fixa um limite de
189 -
tempo por teste, além de que os testes desse projeto truncam e repovoam o banco
190 -
de dados.
191 -

192 -
A cobertura de código é apenas mensurada, não imposta. O relatório, produzido
193 -
pela ferramenta de cobertura do Vitest por meio do comando \texttt{npm run
194 -
test:coverage}, não possui limiar mínimo nem bloqueia a integração contínua.
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.
195 165

196 -
Existe ainda uma verificação estática de tipos (\texttt{npm run typecheck})
197 -
executada no fluxo de CI em caráter consultivo: uma falha é registrada, mas não
198 -
interrompe o processo de \textit{deploy}.
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}.
199 171

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

202 -
Os testes que dependem do banco são executados contra uma instância real do
203 -
PostgreSQL --- e não contra um substituto em memória ---, em uma base dedicada
204 -
com o mesmo nome do projeto, adicionando o suffixo \texttt{\_test}, criada por
205 -
um pequeno script e materializada com \texttt{prisma db push}. O isolamento
206 -
entre os casos é obtido por truncamento: antes de cada teste, uma rotina
207 -
executa \texttt{TRUNCATE users CASCADE}, removendo a tabela de usuários e, por
208 -
meio das chaves estrangeiras em cascata, todas as tabelas dependentes. Não há
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á
209 180
\textit{rollback} transacional nem banco efêmero por execução.
210 181

211 -
O carregamento de dados é feito por funções auxiliares escritas à mão, e não
212 -
por uma biblioteca de fábricas. Para tal, um módulo compartilhado
213 -
(\texttt{api/tests/test-helper.ts}) oferece as primitivas centrais --- criação
214 -
do cliente Prisma, limpeza da base, criação de usuário de teste e geração de
215 -
token ---, enquanto cada arquivo define os \textit{seeders} específicos dos
216 -
registros de que necessita.
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.
217 187

218 -
A regra que orienta o uso de dublês na API pode ser resumida assim: simula-se
219 -
apenas o que deixa o processo; a aplicação e o banco de dados permanecem reais.
220 -
A camada de filas (BullMQ) é substituída, globalmente, por um substituto que
221 -
registra os \textit{jobs} enfileirados, permitindo que um teste afirme tanto
222 -
a resposta HTTP quanto o trabalho em segundo plano que deveria ter sido
223 -
agendado. De modo semelhante, o envio de arquivos e o cliente de armazenamento
224 -
de objetos são substituídos por implementações controladas, e o disparo de
225 -
e-mail e de notificações \textit{push} é simulado pontualmente, nos arquivos
226 -
que os exercitam.
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.
227 195

228 -
Duas fronteiras, porém, permanecem deliberadamente reais. O acesso ao banco de
229 -
dados, via Prisma, nunca é simulado; tampouco a autenticação. Os testes geram
230 -
tokens JWT válidos, assinados com o segredo de teste, e os enviam no cabeçalho
231 -
de autorização, de modo que o \textit{middleware} de autenticação real seja
232 -
executado. Essa escolha reduz o risco de que um teste passe contra um
233 -
substituto que se comporte de maneira distinta em produção.
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.
234 202

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

237 -
A suíte da API divide-se em três grupos, que retomam o vocabulário fixado no
238 -
Quadro~\ref{tab:tests-vocab}: os testes unitários, os testes de integração e os
239 -
testes de tarefas assíncronas. Cada grupo é apresentado a seguir com o que
240 -
exercita, o que é capaz de detectar e o que escapa ao seu alcance.
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.
241 209

242 210
\subsubsection{Testes unitários}
243 211

244 212
Os testes unitários exercitam uma única função ou módulo, sem HTTP e sem banco
245 -
de dados. Eles concentram-se na lógica pura do sistema, em grande parte
246 -
extraída deliberadamente de seus envoltórios de persistência para se tornar
247 -
testável: os agregadores dos indicadores, os construtores dos relatórios e
248 -
auxiliares compartilhados, como a paginação e a conversão de agendamento.
249 -
Também cobrem o gerador de código de ativação, a validade de tokens, os
250 -
serializadores e as regras de validação. Por serem rápidos e determinísticos,
251 -
constituem o instrumento natural para fixar casos-limite --- fronteiras de
252 -
janelas de tempo, margens de classificação e aritmética de paginação ---, e
253 -
servem como documentação executável dessas regras.
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.
254 222

255 -
A limitação desse nível é estrutural: ele só alcança a lógica que foi isolada
256 -
em uma costura testável. A maior parte do comportamento do sistema permanece
257 -
fora de seu alcance sem o banco e a camada HTTP, e o nível pouco contribui,
258 -
isoladamente, para a confiança geral na aplicação.
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.
259 227

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

262 230
Os testes de integração formam a maior parte da suíte. Cada um constrói a
263 -
aplicação real, conecta um cliente Prisma real e a exercita por meio do
264 -
Supertest, afirmando tanto a resposta HTTP quanto o estado persistido no banco.
265 -
Eles percorrem o caminho completo de uma requisição --- roteamento, validação,
266 -
autenticação, controladores, serviços e persistência --- e, por operarem sobre
267 -
um PostgreSQL real, não sofrem o descolamento que afeta os substitutos: um
268 -
teste não pode passar contra um falso que se comporte de modo diferente da
269 -
produção. Afirmar simultaneamente a resposta e as linhas persistidas verifica o
270 -
efeito da operação, e não apenas o seu valor de retorno.
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.
271 238

272 -
Em contrapartida, esses testes exigem infraestrutura em execução, são mais
273 -
lentos e, por compartilharem a mesma base, são forçados a rodar em série.
274 -
O isolamento por truncamento é suficiente, porém menos rigoroso do que um
275 -
\textit{rollback} transacional, pois um teste que falha no meio pode deixar
276 -
resíduos. Os dados de teste, ademais, são escritos à mão em cada arquivo, o que
277 -
gera duplicação e o risco de que os \textit{seeders} divirjam entre si ao longo
278 -
do tempo.
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.
279 243

280 -
\subsubsection{Testes de \textit{tarefas assíncronas}}
244 +
\subsubsection{Testes de tarefas assíncronas}
281 245

282 -
Os testes de tarefas assíncronas, ou de \textit{jobs}, importam um processador
283 -
do BullMQ e o chamam diretamente, com uma carga fabricada, contra o banco real.
284 -
Eles cobrem o código que executa fora do ciclo requisição--resposta --- os
285 -
\textit{workers} que geram exportações, enviam mensagens e recalculam
286 -
indicadores ---, chegando, no caso da exportação, a descompactar o anexo
287 -
produzido e inspecionar seu conteúdo.
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.
288 251

289 252
Como o processador é invocado diretamente, a maquinaria da fila em si ---
290 -
agendamento, repetição, tentativas e ordenação --- permanece fora do alcance
291 -
desses testes. A carga também é fabricada à mão e, por isso, pode divergir
292 -
daquela que o enfileirador realmente envia, sem que nada verifique uma contra
293 -
a outra.
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.
294 256

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

297 -
Diferentemente da API, o aplicativo móvel não possui uma estrutura automatizada
298 -
de testes em nível de unidade ou de componente. A verificação cotidiana do
299 -
aplicativo é manual, em um dispositivo físico, contra a pilha local em
300 -
execução. Essa escolha é contextual: o aplicativo roda como um \textit{build}
301 -
de desenvolvimento do Expo, ou seja, carrega dependências de código nativo do
302 -
Android.
303 -

304 -
A verificação manual captura o que os testes automatizados raramente alcançam
305 -
--- problemas visuais, de leiaute e de desempenho no dispositivo ---, mas não
306 -
é repetível, não protege contra regressões e permanece invisível à integração
307 -
contínua: uma tela quebrada pode ser incorporada ao código sem que nada falhe.
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.
308 268

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

311 271
Sobre a verificação manual há uma suíte \textit{end-to-end} opcional, baseada
312 -
no Maestro, uma ferramenta declarativa de automação de interface para
313 -
dispositivos móveis. A suíte cobre uma única jornada central --- login,
314 -
registro de humor e saída --- por meio de três fluxos descritos em YAML,
315 -
marcados como \texttt{smoke} e executados por um pequeno \textit{harness}
316 -
(\texttt{frontend/scripts/e2e.sh}), exposto como \texttt{npm run test:e2e}. Os
317 -
fluxos são dirigidos por identificadores de teste (\texttt{testID}) inseridos
318 -
no código do aplicativo, e não pelo texto visível, o que os torna mais robustos
319 -
a mudanças de interface.
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.
320 279

321 280
A execução depende de um dispositivo Android físico conectado por \texttt{adb},
322 281
de um \textit{build} de desenvolvimento, da API em funcionamento com um usuário
323 -
de teste previamente semeado e do Metro servindo o aplicativo; não há caminho
324 -
sem cabeça nem integração ao CI, de modo que a suíte é executada manualmente e,
325 -
por consequência, com pouca frequência. Cada fluxo limpa o estado do aplicativo
326 -
e recarrega o \textit{bundle}, o que torna a execução lenta, e a cobertura
327 -
permanece fina: um único caminho feliz, sem casos de erro. A suíte não está,
328 -
ademais, integralmente verde no momento da redação: os fluxos de login e de
329 -
saída passam, mas o fluxo de registro de humor falha ao adicionar um componente
330 -
de humor, porque a tela correspondente é abandonada pelo aplicativo pouco
331 -
depois de ser aberta --- causa ainda não identificada.
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.
332 291

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

335 -
A integração contínua do Nexo, entendida como a prática de integrar e verificar
336 -
automaticamente as mudanças de código \cite{Humble_Farley_2011}, é executada
337 -
exclusivamente no GitHub Actions e testa somente a API, em linha com
338 -
a estratégia assimétrica já descrita. O fluxo de implantação
339 -
(\texttt{.github/workflows/deploy.yml}) só é executado quando algo acontecem
340 -
mudanças no código da \texttt{api}: sua etapa de teste sobe um serviço efêmero
341 -
de PostgreSQL, instala as dependências, prepara a base de teste, executa
342 -
a verificação de tipos em caráter consultivo e roda a suíte com o Vitest.
343 -
A construção da imagem e a implantação em produção são condicionadas ao sucesso
344 -
dessa etapa, de modo que uma suíte reprovada impede a publicação de uma nova
345 -
versão da API, como demonstrado no Capítulo~\ref{sec:deploy-and-ci}.
346 -

347 -
O aplicativo móvel, por sua vez, permanece inteiramente fora da integração
348 -
contínua: embora disponha de comandos de \textit{lint} (\texttt{expo lint})
349 -
e de verificação de tipos (\texttt{tsc --noEmit}), ambos são executados apenas
350 -
manualmente, e a suíte \textit{end-to-end} não é disparada por nenhum fluxo.
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.
351 305

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

354 -
Em síntese, a verificação automatizada do Nexo cobre a superfície HTTP
355 -
e a persistência da API, a sua lógica pura e os seus trabalhadores em segundo
356 -
plano; a verificação do aplicativo móvel restringe-se a uma jornada manual de
357 -
fumaça, limitada à plataforma para a qual o produto é de fato distribuído.
358 -
Ficam fora de qualquer cobertura automatizada a lógica do \textit{frontend}
359 -
abaixo do nível \textit{end-to-end}, a maquinaria da fila em si (agendamento,
360 -
repetições e ordenação) e os caminhos de erro do aplicativo.
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.
361 315

362 -
A cobertura de código é medida, mas não imposta: o relatório orienta o trabalho
363 -
sem jamais reprovar uma \textit{build} ou \textit{deploy}. Persistem, ainda,
364 -
dois riscos de descolamento conhecidos --- os dados de teste escritos à mão em
365 -
cada arquivo e a cópia espelhada dos tipos da API mantida no \textit{frontend}
366 -
podem divergir da fonte de verdade sem que nenhum teste acuse. Essas lacunas
367 -
são assumidas de forma explícita e refletem uma escolha de priorização, e não
368 -
uma garantia de ausência de defeitos. Como a própria definição de teste
369 -
antecipava, uma suíte ``verde'' demonstra apenas que os casos exercitados se
370 -
comportam como esperado.
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.