9

TDD na prática: quem realmente pratica no dia a dia?

Toda pesquisa de "melhores práticas" de engenharia de software inclui TDD. Todo dev experiente diz que TDD é importante. E, na prática, a maioria não pratica.

Quero entender por quê, e se isso é problema.

O argumento a favor do TDD

Força você a pensar na interface antes da implementação. Isso melhora o design. Testes escritos depois tendem a testar implementação, não comportamento.

Feedback imediato. Você sabe na hora se quebrou algo.

Documentação executável. Testes bem escritos descrevem o que o sistema faz melhor do que qualquer README.

Por que não pratico consistentemente

Velocidade inicial. Na fase exploratória de uma feature, eu não sei ainda qual é a interface certa. Escrever teste antes de saber o que está testando gera retrabalho.

Tipos de código. TDD funciona bem para lógica de negócio. Para componentes visuais, integrações com APIs externas, scripts de migração: a aplicação mecânica de TDD gera testes frágeis.

Custo de manutenção. Testes mal escritos são piores do que não ter teste. E TDD praticado mal gera muitos testes mal escritos.

O que eu pratico de verdade

Testo depois, com cobertura nos caminhos críticos. Não é TDD, mas é o que realmente acontece.

Alguém aqui pratica TDD de forma consistente? Em que contexto funciona para vocês?

Carregando publicação patrocinada...
5

Toda pesquisa de "melhores práticas" de engenharia de software inclui TDD

Por isso o primeiro vídeo do meu canal vai se chamar "A péssima prática de seguir boas práticas".

Todo dev experiente diz que TDD é importante

Nem todo. Inclusive quem cria linguagem de programação não costuma usar TDD, por que será? É o software que mais se beneficiaria disso.

Força você a pensar na interface antes da implementação. Isso melhora o design. Testes escritos depois tendem a testar implementação, não comportamento.

Se o programador é ruim o TDD não vai salvá-lo. Se ele é bom o TDD pode não ajudar muito.

Feedback imediato. Você sabe na hora se quebrou algo.

Só se souber fazer bem, o que é raro.

Documentação executável. Testes bem escritos descrevem o que o sistema faz melhor do que qualquer README.

Isso nunca foi verdade e todos os projetos documentam de outras formas porque TDD não foi feito para ensinar um humano como usar aquilo.

Velocidade inicial. Na fase exploratória de uma feature, eu não sei ainda qual é a interface certa. Escrever teste antes de saber o que está testando gera retrabalho.

Isso.

Tipos de código. TDD funciona bem para lógica de negócio. Para componentes visuais, integrações com APIs externas, scripts de migração: a aplicação mecânica de TDD gera testes frágeis.

Verdade.

Custo de manutenção. Testes mal escritos são piores do que não ter teste. E TDD praticado mal gera muitos testes mal escritos.

Exatamente.

Alguém aqui pratica TDD de forma consistente? Em que contexto funciona para vocês?

Pra você ver como é fácil fazer o TDD errado: o que uma resposta dada por uma pessoa aleatória na internet vai ajudar alguém programar melhor? Quando não há entendimento exato do que vai fazer, TDD não pode ser feito. Quando não se sabe o que pode ser respondido ou não, não adianta perguntar.

De maneira alguma estou dizendo que TDD não presta e nunca deva ser usado.

Pesquise sobre SDD. Eu ainda estou avaliando a utilidade. Eu não glorifico nada, eu não jogo nada no lixo até ter informações reais sobre algi. Não posso adotar ou afastar algo porque outras pessoas disseram que é bom ou ruim.

Falei muito sobre: https://www.google.com/search?q=maniero+tdd

S2


Farei algo que muitos pedem para aprender a programar corretamente, gratuitamente (não vendo nada, é retribuição na minha aposentadoria) (links aqui).

2

O ponto sobre criadores de linguagem é forte, difícil argumentar contra. Acho que o problema com TDD é exatamente o que você descreveu: vira ritual sem entendimento. A maioria aprende o como sem nunca entender o quando e o por que. Vou pesquisar SDD, o nome não me era familiar. Qual você diria ser a diferença fundamental entre os dois?

3

Não sei ainda :D

SDD é uma abstração de maior nível, você documenta sem codificar, não é intenção dele fazer o que as pessoas acham que o TDD faz, mas ele não faz.

Não sei se é uma boa solução e sei que ele não elimina a necessidade de TDD se o projeto tem como requisito interno fazer os testes, mas pode ajudar na decisão de não fazer TDD.

Eu demoro para tomar uma decisão, porque ao contrário da maioria, eu só adoto algo depois de ter certeza que vai ajudar.

1

Faz sentido SDD ser uma camada acima: se a especificação já deixa claro o comportamento esperado, parte da necessidade do TDD como ferramenta de design de interface some. O problema é que a maioria dos projetos não tem especificação boa o suficiente pra isso funcionar de verdade.

O que me interessa no seu ponto é justamente essa distinção entre TDD como ferramenta de design versus TDD como ferramenta de verificação. O primeiro exige mudança de mindset real. O segundo é mais fácil de justificar, mas entrega menos valor.

Você já viu algum projeto em produção onde SDD eliminou de fato a necessidade de testes unitários, ou ainda é teoria a ser validada?

4

Meus 2 cents,

Sobre TDD o @LucasMontano publicou um video hoje (seg, 20/abr) comentando um tweet do "Uncle Bob" sobre o assunto:

Uma coisa tenho de reconhecer: se vamos delegar mais codigo para a IA (com seus volumes insanos), estruturas como PRD, SDD e TDD acabam sendo urgentes.

E talvez esse seja um elemento que nao gostamos de admitir: ainda vemos estes tipo de estrutura (como TDD) basicamente do ponto de vista humano e isto esta em transformacao, e nao importa que a IA/LLM ainda gere codigo lixo - em algum momento do tempo isso vai reflexionar, independente se daqui 2 meses, 6 meses ou 1 ano - e precisamos estar preparados para lidar com isso.

Talvez em breve acabemos criando outros tipo de estruturas, afinal tudo que temos foi criado/desenvolvido pensando em volume e velocidade humanos - para esta nova era de codificacao assistida por IA eh necessario repensar este ponto (e rapido).

Post devidamente favoritado via extensão TABNEWS FAVORITOS

Saude e Sucesso !

2

Vou assistir o vídeo. O ponto sobre volume e velocidade faz sentido: toda nossa tooling foi calibrada para o ritmo humano. Com IA gerando código mais rápido, os pontos de controle precisam mudar. TDD com IA pode ser mais sobre revisar assertions do que escrever testes do zero. Você sente que no seu trabalho atual já está mudando a forma como validam o código que a IA gera?

3

Meus 2 cents extendidos,

Você sente que no seu trabalho atual já está mudando a forma como validam o código que a IA gera?

Sem sombra de duvida.

A cerca de 1 ano, se alguem me falasse que eu iria estar criando app sem digitar codigo so acreditando no que a IA gera, ia achar graca e que nao fazia sentido - afinal programar nao eh so digitar codigo, mas tambem entender todo contexto que gira no seu entorno (usuarios, infra, etc).

Fato: a extensao TABNEWS FAVORITOS foi criada em 2 a 3 horas, e sem codificacao por IA ela nao ia existir (nao tinha tempo disponivel para fazer na mao).

So que testes basicos nao servem: eh necessario de fato verificar os contratos E as regras de negocios (que nem sempre eh uma questao apenas de checar se o dado X sai da funcao Y quando a informacao Z entra).

O que achei legal no video do @LucasMontano eh justamente ele trazer de forma sistematizada o que venho fazendo no dia-a-dia (e que nao tinha notado): escrever testes (no sentido de planejar, uma vez que ate a codificacao dos testes eh a IA que faz) virou essencial - sem eles, "quando" (e nao "se") a IA alucinar e eu precisar refazer o contexto do zero, preciso ter seguranca que a alucinacao nao detonou algo que eu nao percebi.

Usar IA mudou muita coisa - antes, eu sabia que um humano teria o "felling" necessario para nao fazer merda em um codigo, mesmo sem testes. A IA nao tem "felling", nao eh deterministica: entao acaba sendo primordial se proteger.

Saude e Sucesso.

1

O ponto do 'feeling' é o que mais faz sentido pra mim. Humano erra mas tem contexto do erro, sabe quando algo parece errado. A IA executa com confiança mesmo quando está completamente errada.

Tenho usado Claude Code bastante no BloodLink e o padrão que funcionou: escrever o contrato da função antes, depois deixar a IA implementar. Quando ela alucina, os testes pegam antes de eu perceber pelo comportamento. Isso me forçou a pensar melhor nas interfaces antes de qualquer linha de código, que é exatamente o que o TDD tradicional propõe. Só que cheguei lá por outro caminho.

A extensão de favoritos ficou boa, usei bastante. Qual ferramenta você usa pra deixar a IA escrever os testes? Prompt direto no chat ou alguma integração com o editor?

3

Meus 2 cents extendidos,

Tenho usado o VSCode (+copilot) e Antigravity (+gemini) e agora ClawCode (+OmniRoute e o LLM free de ocasiao).

Nesta estrutura, peco o desenvolvimento direto pelo prompt, quando faco a especificacao (PRD - macro, checklist - por tarefa e SDD - descricao da funcionalidade), ali ja tem a ordem para criar a funcionalidade E o teste necessario.

Saude e Sucesso

1

Essa abordagem de embutir o teste na própria spec é inteligente. O LLM acaba sendo o disciplinador que o dev muitas vezes não é sozinho: se a ordem está no prompt, ele segue.

No meu caso com Claude Code, percebo que quando especifico bem o comportamento esperado antes, o código gerado é mais coerente. Mas ainda cai no mesmo problema do TDD manual: quando a spec é vaga, o teste gerado testa implementação, não comportamento.

A diferença é que com LLM você consegue regenerar teste e código juntos rapidamente. Isso muda um pouco o custo-benefício do ciclo red-green-refactor.

Você define os critérios de aceite no SDD antes de gerar, ou vai refinando junto com o código?

3

Meus 2 cents extendidos,

Você define os critérios de aceite no SDD antes de gerar, ou vai refinando junto com o código?

Depende.

Todo DEV depois de um tempo tem sua biblioteca de funcoes - isso migrou para SPECs prontas para diversos casos.

As aplicacoes de um modo geral repetem uma serie de comportamentos (dai a origem dos frameworks, boilerplates, etc) e com o SDD nao eh diferente: quanto mais voce usa, maior a biblioteca que voce ja tem pronta de funcionalidades que precisa.

Grosso modo, antes (kkk, 1 ano atras) voce tinha boilerplates de inicializacao de um app, pre-configurado e pronto para uso: agora sao boilerplates de SPECs, SKILLs, AGENTS.md, devContainers, sandbox.

Mudou tudo, para ficar no mesmo lugar.

Enfim - com este "boilerplate" de IA tem muito teste ja pronto, entao nao sai do zero.

Mas nao tem tudo - no meu caso, prefiro escrever os criterios de aceite ao refinar o codigo, conforme a funcionalidade vai tomando forma e amadurecendo.

Mas um detalhe aqui (e onde eu concordo com o UncleBoB, LucasMontano): se um DEV diz que "teste nao sao imporantes" pode ter certeza que ele nao esta usando IA de forma pesada e revisa codigo na mao (o que eh insano para volumetria).

PRD, checklist, SDD, TDD sao tudo isso ? Nao - sao formas humanas que adaptamos para uso no desenvolvimento com IA: ainda acho que vai surgir um "SCRUM" que leve em conta:

  • Que a IA vai desenvolver o codigo de forma autonoma (codificacao agentica)

  • Que certifique que a IA nao esteja gerando codigo lixo

  • Que certifique que a IA esteja seguindo boas praticas (SOLID, CLEAN)

  • Que certifique que a IA esteja gerando codigo seguro

  • Que certifique que a IA esteja gerando um codigo auditavel

  • Metricas/KPIs de observabilidade/auditabilidade (p.ex. prometheus, grafana, zabbix, icinga) garantindo que a aplicacao em homologacao/producao cumpre o esperado (detalhe aqui: KPI sao interessantes para avaliar nao apenas se a API funciona, mas tempo de resposta e verificar se o ultimo PR nao jogou a performance no ralo).

  • Que os humanos precisam estar no circuito, avaliando o resultado do desenvolvimento, mas abstraidos do "operacional" da geracao do codigo.

Eh esquisito ? Pacas - mas me parece o mais logico diante da direcao/rumo que o desenvolvimento usando agentes esta tomando.

Saude e Sucesso !

1

A analogia com boilerplates de SPECs faz bastante sentido, é exatamente como está evoluindo aqui também. Você começa do zero uma vez, depois replica o padrão.

A parte sobre um novo modelo de processo para IA é o ponto mais interessante. Acho que o gargalo maior ainda é auditabilidade: saber se o que o agente gerou segue boas práticas sem precisar revisar linha a linha. Testes ajudam, mas não cobrem tudo.

Você já tentou alguma abordagem sistemática para isso, além dos testes, tipo review automatizado por outro agente?

3

Meus 2 cents extendidos,

O que ja esta pronto, aprovado, publicado e funcionando - review automatico por agente (nao quebra o que ja esta funcionando, porra !)

OBS: Aqui falo em repositorio de homologacao (privado do projeto/equipe), e nao github. Producao eh espelho da homologacao, so com menos dados e escolhidos a dedo para simular as questoes mais criticas.

So durante o desenvolvimento, e na parte especifica que estou trabalhando ocorre o review manual (dentro do razoavel e focado mais naquilo que testes nao cobririam ou que ainda esta em modelagem).

Estabilizou na homologacao - so automatico.

Onde isso muda: se precisar refatorar - os testes ainda cobrem, mas precisa "pastorear" a IA para nao fazer merda.

Saude e Sucesso !

1

Essa separacao faz sentido: automatico onde ja esta estavel, manual onde ainda esta fluido. O ponto do refactor com IA eu sinto bastante no BloodLink, a IA tende a resolver o problema mas perder invariantes que nao estao nos testes. Pastorear e a palavra certa.

O que eu ainda nao resolvi bem e como cobrir aquele pedaco que nao daria pra testar: logica de negocio implicita, regras que vieram de conversa e nunca foram documentadas. Voce tem alguma estrategia pra isso antes de abrir pra refactor automatico?

3

Meus 2 cents,

Voce tem alguma estrategia pra isso antes de abrir pra refactor automatico?

Sim, ja ajustada ao longo dos anos:

  • Um energetico sem acucar (TNT, Bally, Monster) antes

  • Acender uma vela branca e um copo de agua com acucar para meu anjo da guarda

  • Copo termico com agua gelada para o "durante" (hidrate-se !)

  • Resista a tentacao de pedir 10 alteracoes simultaneas, por mais simples que parecam: um passo de cada vez te leva ao topo, um salto de 5 passos pode te fazer tropecar, rolar escada abaixo e ter de comecar novamente.

  • Alteracao finalizada eh git commit. Nao quer multiplos commits para nao baguncar ?
    Lembre-se das opcoes: git stash save "alteracaoX", do git commit --amend --no-edit, do git rebase -i e do git reset --soft - veja qual se adapta melhor ao teu estilo de trabalho.

  • Nunca esquecer: entrou em um beco sem saida ? rollback e comeca denovo (mas anota como eh que foi parar naquele buraco para evitar da proxima vez e de uma olhada no LOG para ter certeza que nenhuma SPEC ou SKILL ficou abandonada no meio do caminho).

  • Nunca esquecer: contexto longo eh o caminho da alucinacao - em algum ponto do tempo a IA vai comecar a alucinar, esquecer ou perder informacoes importantes (mesmo escritas em PRD/ Checklist/ SDD/ etc). Esteja preparado para abandonar o contexto atual a qualquer momento e reiniciar a sessao do zero: confie nos DOCs (p.ex. PRD, Checklist e SPECs) para manter o projeto nos eixos.

Saude e Sucesso !

2

A dica de contexto longo ser caminho para alucinação é a mais subestimada. Já perdi horas numa sessão que parecia produtiva mas a IA tinha começado a contradizer specs do início. Hoje quebro em sessões menores com handoff explícito no CLAUDE.md. O commit por alteração também mudou minha relação com o processo: para de parecer burocracia e vira rede de segurança real. Você costuma usar /compact ou reinicia sessão do zero quando percebe que o contexto tá pesado?

3

Meus 2 cents extendidos,

Prefiro reiniciar do zero: pode ser ma-vontade minha ou apenas pre-conceito, mas o contexto compactado/resumido nunca parece funcionar direito.

Mas fiquei curioso com a tua resposta, sobre "quebrar sessoes menores com handoff explicito no CLAUDE.md": voce poderia explicar como isso tem funcionado e o "comando/prompt" que voce tem usado para isso funcionar ?

Saude e Sucesso !

1

O handoff funciona assim: no final de cada sessão, eu peço pro Claude escrever um resumo do estado atual direto no CLAUDE.md, tipo: 'estamos implementando X, falta Y, o próximo passo é Z'. Na sessão seguinte, começo com 'leia o CLAUDE.md e continue de onde parou'.

Não uso nenhum prompt mágico, é bem literal. O que importa é que o resumo tenha contexto suficiente pra uma sessão nova começar sem depender de memória de conversa anterior. Funciona melhor pra tarefas que têm começo, meio e fim claros, tipo uma feature específica.

Compactação automática funciona às vezes, mas o handoff manual é mais confiável porque você controla o que vai no contexto inicial.

Como você estrutura suas sessões hoje, deixa o contexto acumular até dar problema ou corta em algum ponto?

3
3
1

Distinção válida, e eu misturei os dois no post. TDD de verdade é o ciclo red-green-refactor contínuo, onde o teste guia o design da implementação. O que descrevi nos meus casos práticos é mais test-first pontual: escrevo o teste para definir o comportamento, implemento, e paro aí. Não é o loop completo do TDD.

1

Faz sentido: a IA escreve o boilerplate do teste e você fica com o trabalho que importa, que é pensar no comportamento esperado. O custo que bloqueava todo mundo era exatamente esse.

O que me curioso é se a IA te incentivou a testar mais casos extremos, ou ela tende a gerar os testes "felizes" e deixar os edge cases pra você cobrir manualmente?

3

Acho que o TDD assim como outras práticas surgiram para resolver problemas, porém ao longo dos anos o programador foi limitado a posição de escrever código e a maioria ficou bem com isso.

Acho que um programador resolve um problema, mas nós fomos ensinados a pensar no problema apenas como um codigo e a solução como uma linguagem.

É fácil perceber isso, quando olhamos projetos aqui mesmo do tabnews e Plenos e Sêniors, não se dão ao trabalho nem de criar uma branch no github, fazem tudo na main, quando vemos diversos cursos ensinando linguagens que ninguém usa, mas nenhum ensinando sobre planejamento ou teste.

Acredito que o problema não é o TDD, o problema é o fato que a base dos programadores é baseada tanto em framework e linguagem, que o básico de testes muitos não sabe, que em vez de planejar, já abre o vscode e sai codando o que vem a cabeça.

Essa é apenas minha forma de vê as coisas, a IA chega escrevendo código mais rápido doque qualquer programador é capaz, mas a questão segue sendo: qual ia é melhor e não o que eu preciso estudar para ser um desenvolvedor melhor.

TDD na prática não é usado, pois o tempo para desenvolver o projeto é curto, como falei: o dev não aprende nem a planejar, então os prazos sempre ficam apertados e código vai para teste em produção e depois a gente corrige.

Não vou mentir, assim como cleancode, isso é aquela prática que na teoria é boa, mas no dia a dia com prazos limitados e zero noção de entrega, você deixa de lado, porque o cliente quer saber se funciona, se voce está num projeto com uma equipe bem estruturada e tudo planejado, fica fácil aplicar certas coisas e perceber que não e nada demais, porém na maior parte do tempo, voce está em projetos que ninguém tem noção do tempo gasto para nada e o resultado é o que já sabemos: coloca em prod e quando o cliente reclamar a gente ajeita.

Sempre que possível aprenda a teoria das coisas e aplique em pequenos projetos de final de semana, independente doque for, esse codigo vai para o lixo, mas você aos poucos está aplicando aquela teoria que você leu, mesmo que não precise disse agora, em algum momento pode surgi a oportunidade de você usar e muito desses conhecimentos se conectam com outros, nada vai realmente ser jogado fora, além de algumas linhas de código.

Livros seguem sendo ainda uma excelente fonte de consulta, não precisa ser escravo deles, pegue algum, leia, veja um vídeo, a teoria vai fazer sentido mesmo que em diversos vídeos o programador fale abobrinha as vezes.

1

Concordo com o ponto sobre a base fraca em planejamento. O TDD acaba sendo sintoma disso: não é só sobre teste, é sobre pensar antes de sair codando. O que me preocupa com a IA é exatamente o que você apontou: ela escreve código rápido, mas quem define se o comportamento esperado está certo ainda é o dev. Sem testes, você só sabe que o código compila, não que faz o que deveria. Você acredita que isso vai forçar a próxima geração a aprender testes por necessidade, ou vai continuar sendo opcional no mercado?

3

Quando eu olho para trás eu penso que estamos criando novos problemas e novas possibilidades, de forma direta, acho que um programador Jr ele agora tem que ter uma base mais generalista e isso vai chegar nos próximos cargos, acho que a base da linguagem vai diminuir, mas o conjunto necessário de conhecimentos vai aumentar.

Antes você queria entrar rápido no mercado, bastava as vagas tinhas Desenvedor Front: HTML, CSS, Javascript e React.

Um monte de git com o mesmo projeto ou projetos parecidos, acredito que vamos voltar levemente para o que vimos no passado ou o que temos em empresas com 1 ou 2 dev, você é tudo ao mesmo tempo e se precisar ainda puxa fio e fura parede durante o expediente.

Voce não domina muito uma coisa, mas sabe uma média de muitas e vai se virando em 3 para fazer tudo.

Aquela frase do Akita faz muito sentido, um sênior com IA, facilmente vai assumir um projeto inteiro e fazer sozinho.

Mas boa parte do t trabalho é em software em produção, então acho que vamos gastar mais tempo tomando decisões e planejamento, doque fazemos hoje, também acho que as temidas vagas de liderança, vão seguir crescendo mais, pois 1 bom lider com uma equipe menor vai fazer muita coisa.

Estágio, infelizmente esse não sei o que vai ser, pois não vejo essa posição sendo valorizada e sim limitada a cada vez mais assumir tarefas simples e que o impacto no software será quase zero.

Vamos esperar e vê, estou curioso.

1

Essa visão do dev 'fullstack de tudo' voltando faz sentido, e acho que o TDD se encaixa nisso: quando você é o único tomando decisões no projeto, teste bem escrito vira rede de segurança, não burocracia.

O ponto sobre estágio é o que mais me preocupa. Se o impacto dos juniores já era questionado antes, com IA vai piorar. O estágio vai virar uma triagem de quem consegue usar as ferramentas certas rápido, não um período de aprendizado real.

Mas tenho dúvida se 'dominar uma média de muitas coisas' vai ser suficiente. Um sênior com IA consegue cobrir muito chão, mas quando vai fundo num problema específico de infra ou banco, ainda precisa de alguém que entenda de verdade. Ou você acha que a IA vai cobrir isso também?

3

Concordo com vc, eu uso TDD em casos específicos de regras de negócio, pois são eles q precisam dos parametros primeiro antes de como deve funcionar por dentro, afinal em grande parte das regras de negócio nós sabemos o q precisamos, só precisamos colocar para manipular ele, e por isso acho legal usar TDD nesses momentos. E o legal q dá pra usar IA nessa parte, pois se vc criar os testes antes, o código q gerar com a IA tem q estar de acordo com o teste. Claro q imagino q vc saiba disso, só quis comentar isso pq vc não citou, eheheh.

Eu sou dev flutter, antes eu fazia testes até pra widgets, só q ficava um gargalo na manutenção, e ela q mais atrapalhava do q ajudava, pois diferente de uma regra de negócio q precisa ser consiso com 100% de certeza, eu não preciso dizer se um componente precisa ter cor vermelha ou azul ou tamanho x ou y, pois isso é algo q muda constantemente e dá pra mitigar partes do problema padronizando designs.

Ai no meu código, eu tenho normalmente testes de unidade para as regras de negócio e testes e2e para ver se as páginas estão ligadas uma com as outras corretamente, ações dos componentes estão tudo em ordem, e outras coisas q tem mais relacionadas a ação e reação visual. Para APIs externas eu uso interface para melhor controle do q necessito e facilita eu trocar de API se aquela antiga não serve mais, sem precisar dar aquela super refatoração q normalmente acontece qndo ligamos a API direto no código.

1

O ponto da IA com testes primeiro é exato. Quando você escreve o teste antes, está especificando o contrato. A IA vira só um gerador de implementação que tem que satisfazer a spec, não inventar comportamento. Funciona bem na prática.

Sobre widgets no Flutter, concordo totalmente. Testar cor e tamanho é testar detalhe de CSS, basicamente. Muda constantemente e não representa comportamento real. O fluxo que importa é: botão clicou, página navegou, dado apareceu. Isso o e2e pega sem criar gargalo de manutenção.

A separação que você fez é o setup que faz sentido: unit para regras de negócio, e2e para fluxos visuais, interfaces para isolar APIs externas. Chega no mesmo lugar que o TDD prega, mas sem a rigidez de aplicar em tudo.